如果至少有一个元素匹配时如何聚合2个列表?
问题描述:
例如,我在收集如果至少有一个元素匹配时如何聚合2个列表?
{ _id: 1, list: ["A", "B"] }
{ _id: 2, list: ["C", "A"] }
{ _id: 3, list: ["E", "F"] }
{ _id: 4, list: ["E", "D"] }
{ _id: 5, list: ["U", "I"] }
{ _id: 6, list: ["D", "K"] }
6项我会做一个查询,合并所有的名单至少有1个元素匹配的项目。所以结果将是:
{ _id: 7, list: ["A", "B", "C"] }
{ _id: 8, list: ["E", "F", "D", "K"] }
我是新来的MongoDB,所以任何人都可以帮助我这个查询吗?非常感谢。
答
我发现这个解决方案几乎可以解决您的问题。
{ "_id" : "E", "matchedIds" : [ 6, 3, 4 ], "size" : 2 }
{ "_id" : "A", "matchedIds" : [ 1, 2 ], "size" : 2 }
的matchedIds
表示文档id
-s它们具有list
阵列中常见值:
db.lists.aggregate([
{$unwind:"$list"},
{$group:{_id:"$list", merged:{$addToSet:"$_id"}, size:{$sum:1}}},
{$match:{size: {$gt: 1}}},
{$project:{_id: 1, merged:1, size: 1, merged1: "$merged"}},
{$unwind:"$merged"},
{$unwind:"$merged1"},
{$group:{_id:"$merged", letter:{$first:"$_id"}, size:{$sum: 1}, set: {$addToSet:"$merged1"}}},
{$sort:{size:1}},
{$group:{_id: "$letter", mergedIds:{$last:"$set"}, size:{$sum:1}}},
{$match: {size:{$gt:1}}}
])
我在蒙戈壳,其给出以下输出测试此。
我觉得在上面的聚合中可以做一些优化,但最初我发现这个,会试着找其他方法。另外,您可以在聚合管道末端使用$lookup
聚合,以将id
-s与set
的值匹配。我无法测试这个,因为我的mongo版本不支持$lookup
。但是,如果你使用Node.js或其他东西,你可以在一些for循环中手动获取这些值。
{ "_id" : 1, "list" : [ "A", "B" ] }
{ "_id" : 2, "list" : [ "C", "A" ] }
{ "_id" : 3, "list" : [ "E", "F" ] }
{ "_id" : 4, "list" : [ "E", "D" ] }
{ "_id" : 5, "list" : [ "U", "I" ] }
{ "_id" : 6, "list" : [ "D", "K" ] }
{ "_id" : 7, "list" : [ "A", "L" ] }
但这:
编辑
如果相交列出的每个列表的数量不超过3个
例如这将工作这种算法只会工作将不会:
{ "_id" : 1, "list" : [ "A", "B" ] }
{ "_id" : 2, "list" : [ "C", "A" ] }
{ "_id" : 3, "list" : [ "E", "F" ] }
{ "_id" : 4, "list" : [ "E", "D" ] }
{ "_id" : 5, "list" : [ "U", "I" ] }
{ "_id" : 6, "list" : [ "D", "K" ] }
{ "_id" : 7, "list" : [ "L", "K" ] }
这里带有7,6,4,3的ID的列表具有交集,因此相交列表的数量是4,在这种情况下提供的算法将不起作用。它将工作只有交集的数量少于4对每个列表
最后通知
看来你不能这样做在蒙戈数据库层合并计算达到您想要的结果。如果您正在构建应用程序,那么在应用程序层中执行计算也会更好。
你使用什么环境,比如Node.js,Java或mongo shell? – Karlen
@卡伦:哦,我想用mongo shell:D有什么建议吗,Karlen? – Blurie