我有2个DynamicDocuments:
class Tasks(db.DynamicDocument):
task_id = db.UUIDField(primary_key=True,default=uuid.uuid4)
name = db.StringField()
flag = db.IntField()
class UserTasks(db.DynamicDocument):
user_id = db.ReferenceField('User')
tasks = db.ListField(db.ReferenceField('Tasks'),default=list)
我想将筛选UserTasks
通过检查文件是否flag
在给定的TASK_ID值(从任务文档)0
或者1
,考虑到TASK_ID和USER_ID。所以我以以下方式查询:
obj = UserTasks.objects.get(user_id=user_id,tasks=task_id)
这给我带来了一个UserTask
对象。
现在,我循环浏览任务列表,首先获取等效任务,然后按以下方式检查其标志值。
task_list = obj.tasks
for t in task_list:
if t['task_id'] == task_id:
print t['flag']
是否有任何更好/直接的查询UserTasks
文档的方式来获取任务文档的标志值。
PS:我可以直接从Tasks
Document中获取标志值,但是我还需要检查任务是否与用户相关联。因此,我直接查询了该USerTasks
文档。
我们可以ReferenceField's
在单个查询中直接过滤包含字段的文档吗?
不可以,无法直接使用字段过滤文档,ReferenceField
因为这样做将需要联接,而mongodb不支持联接。
MongoDB不支持联接。在MongoDB中,某些数据被非规范化,或与相关数据一起存储在文档中,以消除对联接的需要。
在官方网站的另一页上:
如果使用关系数据库,则可以对用户和商店执行连接,并在单个查询中获得所有对象。但是MongoDB不支持联接,因此有时需要一些非规范化。
关系纯粹主义者可能已经感到不安,好像我们在违反某些普遍法律。但请记住,MongoDB集合不等同于关系表;每个都有一个独特的设计目标。标准化表提供了原子的,隔离的数据块。但是,文档更紧密地代表了整个对象。
因此,在1个查询,我们不能同时过滤器tasks
与特定标志值与给定的user_id
,并task_id
在UserTasks
模型。
那么如何执行过滤呢?
要根据所需条件执行过滤,我们将需要执行2个查询。
在第一个查询中,我们将尝试Tasks
使用给定的task_id
和过滤模型flag
。然后,在第二个查询中,我们将UserTasks
使用给定user_id
和task
从第一个查询中检索到的模型进行过滤。
例:
假设我们有个user_id
,task_id
并且需要检查相关任务的flag
值是否为0
。
第一查询
我们首先retrive的my_task
给定task_id
和flag
作为0
。
my_task = Tasks.objects.get(task_id=task_id, flag=0) # 1st query
第二查询
然后在第二个查询中,您需要UserTask
使用给定user_id
和my_task
对象对模型进行过滤。
my_user_task = UserTasks.objects.get(user_id=user_id, tasks=my_task) # 2nd query
仅当获得my_task
具有给定task_id
和flag
值的对象时,才应执行第二次查询。另外,如果没有匹配的对象,您将需要添加错误处理。
如果我们已使用EmbeddedDocument
该Tasks
模型怎么办?
假设我们已经将Tasks
文档定义为,EmbeddedDocument
并将模型中的tasks
字段定义UserTasks
为EmbeddedDocumentField
,然后进行所需的过滤,我们可以完成以下操作:
my_user_task = UserTasks.objects.get(user_id=user_id, tasks__task_id=task_id, tasks__flag=0)
my_task
从任务列表中获取特定内容
上面的查询将返回一个UserTask
包含所有的文档tasks
。然后,我们将需要执行某种迭代以获得所需的任务。
为此,我们可以使用进行列表理解enumerate()
。然后,所需的索引将成为返回的1元素列表的第1个元素。
my_task_index = [i for i,v in enumerate(my_user_task.tasks) if v.flag==0][0]
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句