假设我们有三个文件:
[
{
row: [
{identifier: 'a', value: 10},
{identifier: 'b', value: 24},
{identifier: 'c', value: 3},
]
},
{
row: [
{identifier: 'a', value: 11},
{identifier: 'b', value: 75},
{identifier: 'c', value: 4},
]
},
{
row: [
{identifier: 'a', value: 2},
{identifier: 'b', value: 1},
{identifier: 'c', value: 3},
]
}
]
如果不满足任何条件,则每行的值应为null
。条件必须包括identifier
。这对我来说是个问题。
[
{
row: [
{identifier: 'a', value: null}, // Because it's 'a' and lower than 10
{identifier: 'b', value: null}, // Because 'a' is lower than 10
{identifier: 'c', value: null} // Because 'a' is lower than 10
]
},
{
row: [
{identifier: 'a', value: 11}, // Because it's 'a' and not lower than 10
{identifier: 'b', value: 75}, // Because 'a' or 'c' are not lower than 10, greater than 5
{identifier: 'c', value: 4} // Because it's 'c' and greater than 5
]
},
{
row: [
{identifier: 'a', value: null}, // Because it's 'a' and lower than 10
{identifier: 'b', value: null}, // Because 'a' is lower than 10
{identifier: 'c', value: null} // Because 'a' is lower than 10
]
}
]
// ... Rest
$project: {
row: {
$cond: [
{
$eq: [
{
$size: {
$filter: {
input: '$row',
as: 'row',
cond: {
$and: [ // Using $or here produces an output
{
$and: [
{$eq: ['$$row.identifier', 'a']},
{$gt: ['$$row.value', 10]}
],
},
{
$and: [
{$eq: ['$$row.identifier', 'b']},
{$lt: ['$$row.value', 5]}
]
}
]
}
}
},
0
]
},
{
$map: {
input: '$row',
as: 'row',
in: {identifier: '$$row.identifier', value: null}
}
},
'$row'
]
}
}
// ... Rest
我以为MongoDB看到了这个:
(A AND B) AND (C AND D)
它首先评估括号,但事实并非如此。
当我用$nor
替换MongoDB时抛出:
MongoError:无法识别的表达式'$ nor'
当我将第一个$and
更改为$or
时,整个查询工作正常,但这不是我期望的结果。
一个条件是正常工作:
$eq: [
{
$size: {
$filter: {
input: '$row',
as: 'row',
cond: {
$or: [
{
$and: [
{$eq: ['$$row.identifier', 'a']},
{$gt: ['$$row.value', 10]}
]
}
]
}
}
}
},
0
]
现在所有行的值都变为null
。如果我添加第二个条件,它会被反转($gt
变成$lt
)。我不明白为什么。
您需要以下标准的预期输出。您还缺少$$
引用,该引用用于引用在filter运算符中的as
中创建的用户变量。
{
"$or":[
{"$and":[
{"$eq":["$$row.identifier","a"]},{"$lte":["$$row.value",10]}
]},
{"$and":[
{"$eq":["$$row.identifier","b"]},{"$lt":["$$row.value",5]}
]}
]
}
您可以使用$addFields
创建临时字段,该字段将表示当前文档是使用($allElementsTrue)匹配所有条件,然后使用$map生成预期输出
db.col.aggregate([
{
$addFields: {
matches: {
$allElementsTrue: {
$map: {
input: "$row",
as: "r",
in: {
$switch: {
branches: [
{ case: { $and: [{$eq: ["$$r.identifier", "a"]},{$lte: ["$$r.value", 10] }] },
then: false },
{ case: { $and: [{$eq: ["$$r.identifier", "b"]},{$gte: ["$$r.value", 5] }] },
then: false },
],
default: true
}
}
}
}
}
}
},
{
$project: {
row: {
$map: {
input: "$row",
as: "r",
in: {
$cond: {
if: { $eq: [ "$matches", true ] },
then: "$$r",
else: { identifier: "$$r.identifier", value: null }
}
}
}
}
}
}
])