使用 $unwind、$lookup 和 $group 的复杂聚合中的 mongodb 正确列表顺序
Posted
技术标签:
【中文标题】使用 $unwind、$lookup 和 $group 的复杂聚合中的 mongodb 正确列表顺序【英文标题】:mongodb correct list order in complex aggregation with $unwind, $lookup and $group 【发布时间】:2018-06-28 21:12:59 【问题描述】:我有一个问题,使用聚合自动取消引用子对象并保持列表顺序这样做。首先:我的数据模型。让我们将其分解为两个集合(我使用简化的 id 以便于理解):
会议:
'id': '1',
'some': 'abc',
'data': 'def',
'agendaItem': [
ObjectId('2'),
ObjectId('3')
]
议程项目:
'id': ObjectId('2'),
'some': 'ghi',
'data': 'jkl'
,
'id': ObjectId('3'),
'some': 'mno',
'data': 'pqr'
我的单(!)查询的结果应该是这样的:
'id': ObjectId('1'),
'some': 'abc',
'data': 'def',
'agenda_items': [
'id': ObjectId('2'),
'some': 'ghi',
'data': 'jkl'
,
'id': ObjectId('3'),
'some': 'mno',
'data': 'pqr'
]
重要的部分是议程项目列表应该保持相同的顺序,id 2 必须在顶部。
目前,我使用带有展开、查找和分组的聚合来执行这样的查询:
[
'$unwind':
'preserveNullAndEmptyArrays': True,
'path': '$agendaItem'
,
'$lookup':
'from': 'agenda_item',
'as': 'agendaItem',
'foreignField': '_id',
'localField': 'agendaItem'
,
'$unwind':
'preserveNullAndEmptyArrays': True,
'path': '$agendaItem'
,
'$group':
'agendaItem':
'$addToSet': '$agendaItem'
]
这给了我想要的结果 - 除了一个例外:列表完全混淆了,这意味着在此示例中 ObjectId('3') 在 ObjectId('2') 之前。
在 MongoDb 的这篇博文中使用 addFields:http://www.kamsky.org/stupid-tricks-with-mongodb/using-34-aggregation-to-return-documents-in-same-order-as-in-expression 是一种解决方案,但我不知道如何将它放入 $unwind + $lookup 链中。你能帮助我吗?还是我的策略完全错误?
德语背景顺便说一句:https://oparl.org/spezifikation/online-ansicht/ 和 https://mirror.oparl.org/body/5a3d010888dbe04745b24e0a/meeting
【问题讨论】:
你为什么使用 addToSet ?$addToSet
不保证维持秩序。使用$push
并在$group
阶段之前添加$sort
阶段以实现稳定排序。所以最后两个阶段应该是$sort:"agendaItem.id":1, '$group': '_id':'$id', 'agendaItem': '$push': '$agendaItem'
我想是因为我仍然有理解聚合框架的问题,所以我忽略了addToSet
的问题。但这对现有值很有用。所以后续问题:我不想让它按 id 排序,而是按照它在 MongoDB 列表中的保存方式。我想解决方案是$addField
,但我不知道在哪里添加它。你能给我一个提示吗?
我猜你是在 3.4 上,因为你提到了 $addFields
。只是不要 $unwind
和 $group
(它在 3.4 中不需要)。试试这个,不要尝试其他阶段db.col.aggregate([ '$lookup': 'from': 'agenda_item', 'as': 'agendaItem', 'foreignField': '_id', 'localField': 'agendaItem' ])
$addField
是我在谷歌上搜索的解决方案。这是一个新项目,所以我可以选择任何我想要的 MongoDB 版本。但是当 MongoDB 3.2 是另一个项目的当前版本时,我创建了代码 sn-p。并且:您的提示效果很好。所以这在最后一个版本中变得“更”容易了,我只是没有检查简化现在是否可以完成这项工作。非常感谢!
很遗憾,@user2683814 建议的解决方案不起作用。如果localField
是一个数组,$lookup
阶段会查找数组的所有项并输出一个数组。但是,不能保证结果字段将按照与输入数组相同的顺序输出。
【参考方案1】:
我有完全相同的问题要解决。
可以在这里找到解决方案: Aggregate $lookup does not return elements original array order
【讨论】:
以上是关于使用 $unwind、$lookup 和 $group 的复杂聚合中的 mongodb 正确列表顺序的主要内容,如果未能解决你的问题,请参考以下文章
MongoDB $lookup 在 2 级嵌套文档上不使用 $unwind
MongoDB $lookup 在 2 级嵌套文档上不使用 $unwind