我需要使用 MongoDB 过滤器聚合来计算 2 个数组之间匹配元素的数量。我尝试在过滤器的条件字段上使用 $eq 和 $setIntersection,但即使所有 4 个元素都匹配,匹配元素的数量也仅返回 1。
用户场景如下:
现在,它在我的查询中只返回 1。如果存在不匹配,例如用户输入 1, 2, 3, 5 那么它应该返回 3 匹配。
这是查询:
db.collection.aggregate({
$match: {
"entries.numbers": {
$in: [
1,
2,
3,
4
]
}
}
},
{
"$addFields": {
"matchingCount": {
$size: {
$filter: {
input: "$entries",
as: "e",
cond: {
$eq: [
"$$e.numbers",
[
1,
2,
3,
4
]
]
}
}
}
}
}
})
1.Wrt
但即使 4 个元素全部匹配,匹配元素的数量也仅返回 1。
如果从
$size
阶段删除 $addFields
部分,您会看到 matchingCount
实际上是一个对象的列表,因此 $size
返回 1。
"matchingCount": [
{
"name": "Josh",
"numbers": [ 1, 2, 3, 4 ]
}
]
此外,在管道中的任何位置更改
[ 1, 2, 3, 4 ]
的顺序或根本不匹配。所以你真的应该只使用集合。
entries
都在一个文档中,作为对象数组。
因此,如果您想要所有具有 至少一个正确猜测的匹配条目:
输入集合,数字顺序与“中奖”不同
[1, 2, 3, 4]
:
[
{
"_id": "1234",
"entries": [
{"name": "Josh", "numbers": [4, 1, 3, 2]},
{"name": "only three", "numbers": [1, 2, 3, 5]},
{"name": "none", "numbers": [9, 8, 7, 6]} // no matches
]
}
]
查询:
db.collection.aggregate([
{ $unwind: "$entries" },
{
// separated for clarity
$addFields: {
intersect: {
$setIntersection: [
"$entries.numbers",
[ 1, 2, 3, 4 ]
]
}
}
},
{
// remove docs which have no match
$match: {
intersect: { $ne: [] }
}
},
{
// can be combined with the stage above
$addFields: {
matchingCount: { $size: "$intersect" }
}
},
{
// if you only want guesses with at least three matches
$match: {
$expr: {
$gte: [
// change this two whatever you want
"$matchingCount",
3
]
}
}
},
{
$unset: [ "fields", "you", "don't", "want" ]
}
])
我的示例数据库的结果:
[
{
"_id": "1234",
"entries": { "name": "Josh", "numbers": [ 4, 1, 3, 2 ] },
"intersect": [ 1, 2, 3, 4 ],
"matchingCount": 4
},
{
"_id": "1234",
"entries": { "name": "only three", "numbers": [ 3, 5, 1, 2 ] },
"intersect": [ 1, 2, 3 ],
"matchingCount": 3
}
]
这是一个组合阶段版本,以及 操场:
db.collection.aggregate([
{ $unwind: "$entries" },
{
// can be combined with the stage above
$addFields: {
matchingCount: {
$size: {
$setIntersection: [
"$entries.numbers",
[ 1, 2, 3, 4 ]
]
}
}
}
},
{
// if you only want guesses with at least three matches
$match: {
$expr: {
$gte: [
// change this two whatever you want
"$matchingCount",
3
]
}
}
}
])
尝试这个查询:
db.collection.aggregate([
{
$match: {
"entries.numbers": { $in: [1, 2, 3, 4] }
}
},
{
$addFields: {
matchingNumbers: {
$setIntersection: ["$entries.numbers", [1, 2, 3, 4]]
}
}
},
{
$addFields: {
matchingCount: { $size: "$matchingNumbers" }
}
}
])