【发布时间】:2022-01-23 02:04:06
【问题描述】:
我的文档如下所示:
docs = [
{
'id': 1,
'xs': [
{'name': 'foo', 'value': 0.5},
{'name': 'bar', 'value': 0.3},
],
},
{
'id': 2,
'xs': [
{'name': 'foo', 'value': 0.9},
{'name': 'bar', 'value': 0.1},
],
},
]
我想根据 xs.value 分别获取每个 xs.name 值的前 N 个文档(降序排序 + 限制)。
我尝试使用$unwind 和$sort 来执行此操作,但感觉有点慢。我有大约 6000 个文档,每个文档在 xs 中有 20 个元素,以下聚合大约需要 3 分钟:
steps = [
{'$match': query},
{'$unwind': '$xs'},
{'$match': {'xs.name': "foo"}},
{'$sort': {'xs.value': -1}},
{'$limit': 10}
]
关于如何加快速度的任何想法?我想我可以通过多种方式编写聚合,但我不确定哪种方式具有最大的加速潜力。
谢谢!
编辑: 以下步骤:
{'$match': {**query, 'xs.name': "foo"}},
{'$unwind': '$xs'},
{'$match': {'xs.name': "foo"}},
{'$limit': 1},
大约需要一分钟才能完成,甚至不需要排序
指数如下:
'xs.name': {'v': 2, 'key': [('xs.name', 1)]},
'xs.value-1': {'v': 2, 'key': [('xs.value', -1)]}}
编辑 2: 另一个尝试:
{'$match': query},
{'$project': {
'items': {
'$filter': {'input': '$xs', 'as': 'this', 'cond': {'$eq': ['$$this.name', "foo"]}}
},
}},
{'$limit': 1},
非常快,但是添加这个:
{'$sort': {'xs.value': -1}},
在$limit 之前让它变得很慢。
【问题讨论】:
-
您可能希望将您的
{'$match': {'xs.name': "foo"}}放入第一个$match以进行更有选择性的查询。另一件事是,您能否提供您当前的索引,以便我们了解可以提供哪些帮助? -
你是对的,但在我的用例中,所有对象的每个值都为
xs.name。我不将这些用作直接文档字段的原因是因为它们可能经常更改/以各种方式查询。我在xs.name上有一个升序索引,但我认为我在xs.value上缺少一个索引。 -
@eloaf,正如@ray 指出的那样,我认为您的
$match条件是瓶颈。据我所知,频繁的文档更改不会成为问题,您必须在匹配条件中添加xs.name,正如指出的那样。您能否提供query变量的值,以便我们可以相应地建议索引 -
谢谢我用一些额外的信息编辑了我的原始问题
-
我认为
$unwind可能会使情况变得更加复杂。如果查询最里面的xs数组条目级别,您可能需要考虑重构集合以将数组条目存储为单独的文档,例如this。xs级别的索引和查询会简单得多。
标签: mongodb aggregation-framework