对于我的收藏夹中的每个物品,我都需要查找其他具有相交子收藏夹的其他物品的数量。例如,给定这个集合
[{id:1,"sub":[1, 2, 3]},
{id:2,"sub":[2, 3, 4]},
{id:3,"sub":[4, 5, 6],
{id:4,"sub":[7, 8, 9]}]
预期结果是
[{id:1,"count":1},
{id:2,"count":2},
{id:3,"count":1},
{id:4,"count":0"}]
[从纯MongoDB查询语言的算法开始:您必须重组文档,以便每个文档包含其初始sub
数组和所有其他sub
值的数组。为此,您需要同时运行$group和$unwind。然后,只需将$map和$setIntersect全部清空并等于自身数组,然后使用$filter
db.collection.aggregate([
{
$group: {
_id: null,
current: { $push: "$$ROOT" },
all: { $push: "$sub" }
}
},
{
$unwind: "$current"
},
{
$project: {
id: "$current.id",
count: {
$size: {
$filter: {
input: {
$map: {
input: "$all",
in: { $setIntersection: [ "$$this", "$current.sub" ] }
}
},
cond: {
$and: [
{ $ne: [ "$$this", [] ] },
{ $ne: [ "$$this", "$current.sub" ]}
]
}
}
}
}
}
}
])
由于聚合非常复杂,因此在C#中以强类型的方式运行它毫无意义。您所能做的就是使用BsonDocument
类来构建管道,例如:
var groupDef = new BsonDocument()
{
{ "_id", "" },
{ "current", new BsonDocument(){ { "$push", "$$ROOT" } } },
{ "all", new BsonDocument(){ { "$push", "$sub" } } },
};
var projectDef = BsonDocument.Parse(@"{
id: ""$current.id"",
_id: 0,
count: {
$size: {
$filter: {
input: {
$map: {
input: ""$all"",
in: {
$setIntersection: [
""$$this"",
""$current.sub""
]
}
}
},
cond: {
$and: [
{
$ne: [
""$$this"",
[]
]
},
{
$ne: [
""$$this"",
""$current.sub""
]
}
]
}
}
}
}
}");
var result = mongoDBCollection.Aggregate()
.Group(groupDef)
.Unwind("current")
.Project(projectDef)
.ToList();