gpt4 book ai didi

mongodb - 几个数组的交集

转载 作者:可可西里 更新时间:2023-11-01 09:39:47 24 4
gpt4 key购买 nike

我有一些文档具有数组属性项。我想获取 n 个文档之间的截距。

db.things.insert({name:"A", items:[1,2,3,4,5]})
db.things.insert({name:"B", items:[2,4,6,8]})
db.things.insert({name:"C", items:[1,2]})
db.things.insert({name:"D", items:[5,6]})
db.things.insert({name:"E", items:[9,10]})
db.things.insert({name:"F", items:[1,5]})

数据:

{ "_id" : ObjectId("57974a0d356baff265710a1c"), "name" : "A", "items" : [ 1, 2, 3, 4, 5 ] },
{ "_id" : ObjectId("57974a0d356baff265710a1d"), "name" : "B", "items" : [ 2, 4, 6, 8 ] },
{ "_id" : ObjectId("57974a0d356baff265710a1e"), "name" : "C", "items" : [ 1, 2 ] },
{ "_id" : ObjectId("57974a0d356baff265710a1f"), "name" : "D", "items" : [ 5, 6 ] },
{ "_id" : ObjectId("57974a0d356baff265710a20"), "name" : "E", "items" : [ 9, 10 ] },
{ "_id" : ObjectId("57974a1a356baff265710a21"), "name" : "F", "items" : [ 1, 5 ] }

例如:things.mane.A 拦截 things.mane.C 拦截 things.mane.F:

[ 1, 2, 3, 4, 5 ] 拦截 [ 1, 2 ] 拦截 [ 1, 5 ]

必须是:[1]

我认为使用 $setIntersection 是可行的,但我找不到路。

我可以处理两个文档,但如何处理更多文档?

    db.things.aggregate({$match:{"name":{$in:["A", "F"]}}}, 
{$group:{_id:null, "setA":{$first:"$items"}, "setF":{$last:"$items"} } },
{
"$project": {
"set1": 1,
"set2": 1,
"commonToBoth": { "$setIntersection": [ "$setA", "$setF" ] },
"_id": 0
}
}
)

{ "commonToBoth" : [ 5, 1 ] }

最佳答案

不特定于输入项数量的解决方案可能如下所示:

db.things.aggregate(
{
$match: {
"name": {
$in: ["A", "F"]
}
}
},
{
$group: {
_id: "$items",
count: {
$sum: 1
}
}
},
{
$group: {
_id: null,
totalCount: {
$sum: "$count"
},
items: {
$push: "$_id"
}
}
},
{
$unwind: {
path: "$items"
}
},
{
$unwind: {
path: "$items"
}
},
{
$group: {
_id: "$items",
totalCount: {
$first: "$totalCount"
},
count: {
$sum: 1
}
}
},
{
$project: {
_id: 1,
presentInAllDocs: {
$eq: ["$totalCount", "$count"]
}
}
},
{
$match: {
presentInAllDocs: true
}
},
{
$group: {
_id: null,
items: {
$push: "$_id"
}
}
}
)

这将输出这个

{
"_id" : null,
"items" : [
5,
1
]
}

当然,您可以添加最后一个 $project 阶段,使结果达到所需的形状。


解释

这背后的基本思想是,当我们计算文档的数量并计算每个项目的出现次数时,计数等于文档总计数的项目出现在每个文档中,因此在交集中结果。
这个想法有一个重要的假设:您的 items 数组中没有重复项(即它们是集合)。如果这个假设是错误的,那么您将不得不在管道的开头插入一个额外的阶段,以将数组转换为集合。
人们也可以用一种不同的、可能更短的方式构建这个管道,但我尽量保持资源使用率尽可能低,因此添加了可能不必要的(从功能的角度来看)阶段。例如,第二阶段按 items 数组分组,因为我的假设是不同的值/数组比文档少得多,因此管道的其余部分必须使用初始文档计数的一小部分.然而,从功能的角度来看,我们只需要文档的总数,因此我们可以跳过那个阶段,只做一个 $group 阶段来计算所有文档并将它们放入一个数组中以备后用- 这当然对内存消耗有很大的影响,因为我们现在有一个包含所有可能文档的数组。

关于mongodb - 几个数组的交集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38588964/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com