Python - Mongoengine高级查询列表字段

4 投票
1 回答
2284 浏览
提问于 2025-04-17 13:56

我有一个列表,里面包含了多个子列表,像这样:

li = [[('A', 'one'), ('A', 'two')], [('B', 'three'), ('B', 'four')]]

我需要查询一个Mongo数据库,找出所有对象,这些对象的列表字段中至少包含每个子列表中的一个项目。比如说,找出那些包含要么是 [('A', 'one')] 或者 [('A', 'two')],并且要么是 [('B', 'three')] 或者 [('B', 'four')] 的项目……

我现在使用的是mongoengine,不过如果有其他方法能完成这个任务,我也可以考虑换用其他工具。目前我做了很多这样的查询,以避免重复的结果:

final = set()
for sublist in li:
    query = Obj.objects(list_field__in=sublist)
    final &= set(query)

问题是,当处理大量查询结果时,这个过程非常慢(我觉得生成结果集需要很长时间)。有没有办法能加快这个过程?特别是,有没有办法能避免从查询结果中创建集合或列表?

我真的希望能写出类似这样的代码:

query = Obj.objects(list_field__in=li[0] AND list_field__in=li[1] AND ...)

编辑:下面的答案经过进一步测试后不适用,因为mongoengine不允许 Q(field=x) & Q(field=y)

编辑2:这是我想要执行的等效mongoDB查询:

db.obj.find({ "$and": [
    {"list_field": {"$in":
        [["A", "one"], ["A", "two"]]
    }},
    {"list_field": {"$in":
        [["B", "three"], ["B", "four"]]
    }}
]})

我能在mongoengine中做到这一点吗?它不让我用 Q(list_field__in=[('A', 'one'), ('A', 'two')]) | Q(list_field__in=[('B', 'three'), ('B', 'four')]) 这样的查询。

1 个回答

5

我觉得你可以试试使用Q类来实现这个功能:

  filter = reduce(Q.__and__, map(lambda x: Q(list_field__in=x), li))
  Obj.objects(filter)

撰写回答