Mongo嵌入式文档查询

Python爱好者

我有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:我可以直接从TasksDocument中获取标志值,但是我还需要检查任务是否与用户相关联。因此,我直接查询了该USerTasks文档。

拉胡尔·古普塔(Rahul Gupta)

我们可以ReferenceField's在单个查询中直接过滤包含字段的文档吗?

不可以,无法直接使用字段过滤文档,ReferenceField因为这样做将需要联接,而mongodb不支持联接。

根据有关数据库引用的MongoDB文档

MongoDB不支持联接。在MongoDB中,某些数据被非规范化,或与相关数据一起存储在文档中,以消除对联接的需要。

在官方网站的另一上:

如果使用关系数据库,则可以对用户和商店执行连接,并在单个查询中获得所有对象。但是MongoDB不支持联接,因此有时需要一些非规范化。

关系纯粹主义者可能已经感到不安,好像我们在违反某些普遍法律。但请记住,MongoDB集合不等同于关系表;每个都有一个独特的设计目标。标准化表提供了原子的,隔离的数据块。但是,文档更紧密地代表了整个对象。

因此,在1个查询,我们不能同时过滤器tasks与特定标志值与给定的user_id,并task_idUserTasks模型。

那么如何执行过滤呢?

要根据所需条件执行过滤,我们将需要执行2个查询。

在第一个查询中,我们将尝试Tasks使用给定的task_id过滤模型flag然后,在第二个查询中,我们将UserTasks使用给定user_idtask从第一个查询中检索到的模型进行过滤

例:

假设我们有个user_idtask_id并且需要检查相关任务的flag值是否为0

第一查询

我们首先retrive的my_task给定task_idflag作为0

my_task = Tasks.objects.get(task_id=task_id, flag=0) # 1st query

第二查询

然后在第二个查询中,您需要UserTask使用给定user_idmy_task对象模型进行过滤

my_user_task = UserTasks.objects.get(user_id=user_id, tasks=my_task) # 2nd query

仅当获得my_task具有给定task_idflag对象时,才应执行第二次查询另外,如果没有匹配的对象,您将需要添加错误处理。

如果我们已使用EmbeddedDocumentTasks模型怎么办?

假设我们已经将Tasks文档定义为,EmbeddedDocument并将模型中tasks字段定义UserTasksEmbeddedDocumentField,然后进行所需的过滤,我们可以完成以下操作:

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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章