如何解决基于数组中子对象属性的MongoDB聚合管道过滤器
给出具有以下结构的文档:
{ 'id': 1,name: 'bob',type: 'foo',children: [{'id': 2},{'id': 3}]}
{ 'id': 2,type: 'foo' }
{ 'id': 3,type: 'bar' }
{ 'id': 4,children: [{'id': 5},{'id': 6}]}
{ 'id': 5,type: 'foo' }
{ 'id': 6,type: 'foo' }
如何编写聚合管道查询以查找所有文档,如果它们有子项,则所有子项的类型均为foo
(父项的类型为'foo')?
其他说明:
-
children
是一组对象,这些对象的属性引用同一集合中的其他文档 - 并非所有文档都有孩子
- 不能更改文档结构
- 我已经研究了$ unwind和$ lookup,但这会产生许多文档,而我只希望在其末尾找到父文档。
解决方法
在使用聚合管道API进行了一些额外的玩弄之后,这是一个潜在的解决方案。
步骤是:
- 首先基于
$match
准则type
,以确保随后在管道中仅使用具有适当type
的父文档。 - 对子文档执行简单的
$lookup
。尽管似乎没有明确记录,但是$lookup
可以毫不费力地在数组中使用嵌套对象的属性。 - 使用
$elemMatch
和一些否定符对结果文档进行最终匹配。
这是使用Robo3T的外观(应该很容易翻译成其他查询客户端):
注意:在这种特殊情况下,id
只是要加入文档的占位符,不是“官方” _id
mongo字段
db.getCollection('items').aggregate([
{ $match : { "type": "foo" } },{
$lookup: {
from: "items",localField: "children.id",foreignField: "id",as: "items"
}
},{
$match : {
"items": {
$not: {
$elemMatch: {
"type": { $ne: "foo" }
}
}
}
}
}
])
这将排除文档1和3,因为3具有“条”的类型,而1包含“条”。
这可能不是最佳解决方案,我尚未在大型数据集上对其进行过测试。另外,使用$elemMatch
进行的最终比赛非常混乱,因此欢迎提出改进建议。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。