MongoDB:查找数组中某个字段始终为真的所有文档
MongoDB: Finding all documents for which a certain field in an array is always true
这是我在官方MongoDB documentation上找到的bios
合集:
{
"_id" : 1,
"name" : {
"first" : "John",
"last" : "Backus"
},
"awards" : [
{
"award" : "W.W. McDowell Award",
"year" : 1967,
"by" : "IEEE Computer Society",
"monetaryRewards": false
}
]
},
{
"_id" : 2,
"name" : {
"first" : "John",
"last" : "McCarthy"
},
"awards" : [
{
"award" : "Turing Award",
"year" : 1971,
"by" : "ACM",
"monetaryRewards": true
},
{
"award" : "Kyoto Prize",
"year" : 1988,
"by" : "Inamori Foundation",
"monetaryRewards": true
}
]
},
{
"_id" : 3,
"name" : {
"first" : "Grace",
"last" : "Hopper"
},
"awards" : [
{
"award" : "Computer Sciences Man of the Year",
"year" : 1969,
"by" : "Data Processing Management Association",
"monetaryRewards": true
},
{
"award" : "Distinguished Fellow",
"year" : 1973,
"by" : " British Computer Society",
"monetaryRewards": true
},
{
"award" : "W. W. McDowell Award",
"year" : 1976,
"by" : "IEEE Computer Society",
"monetaryRewards": false
}
]
}
我正在尝试编写一个查询,使我能够检索所有 monetaryRewards
都为真的文档。因此,考虑到以前的文件:
_id = 1 -> there is only one monetaryRewards and it is false. The query should not select it;
_id = 2 -> There are three awards and the monetaryRewards fields are always true. The query should select it;
_id = 3 -> There are three awards where monetaryRewards is twice true and once false. The query should not select it;
我写了以下查询:
db.bios.find( { awards: {$not: {$elemMatch:{"monetaryRewards":false}}}} )
查询工作正常。后来我意识到我的 bios
集合也可能不包含 monetaryRewards
字段,例如可能有另一个文档:
{
"_id" : 4,
"name" : {
"first" : "Kristen",
"last" : "Nygaard"
},
"awards" : [
{
"award" : "Rosing Prize",
"year" : 1999,
"by" : "Norwegian Data Association",
"monetaryRewards":true
},
{
"award" : "Turing Award",
"year" : 2001,
"by" : "ACM"
}
}
在这种情况下,我的查询失败了,因为它将缺少 monetaryRewards
视为 true,而在我的情况下它应该是 false。
如何解决我的查询?
在这里你可以找到 mongoplayground ,你可以看到错误选择了 _id=4 的文档。
您可以 $map
awards.monetaryRewards
到辅助布尔数组。使用 $ifNull
来满足缺少字段的情况。然后使用$allElementsTrue
进行过滤。
db.collection.aggregate([
{
"$addFields": {
"filterArr": {
"$map": {
"input": "$awards",
"as": "a",
"in": {
$ifNull: [
"$$a.monetaryRewards",
false
]
}
}
}
}
},
{
"$match": {
$expr: {
"$allElementsTrue": "$filterArr"
}
}
},
{
$project: {
filterArr: false
}
}
])
这里是Mongo playground供您参考。
这是我在官方MongoDB documentation上找到的bios
合集:
{
"_id" : 1,
"name" : {
"first" : "John",
"last" : "Backus"
},
"awards" : [
{
"award" : "W.W. McDowell Award",
"year" : 1967,
"by" : "IEEE Computer Society",
"monetaryRewards": false
}
]
},
{
"_id" : 2,
"name" : {
"first" : "John",
"last" : "McCarthy"
},
"awards" : [
{
"award" : "Turing Award",
"year" : 1971,
"by" : "ACM",
"monetaryRewards": true
},
{
"award" : "Kyoto Prize",
"year" : 1988,
"by" : "Inamori Foundation",
"monetaryRewards": true
}
]
},
{
"_id" : 3,
"name" : {
"first" : "Grace",
"last" : "Hopper"
},
"awards" : [
{
"award" : "Computer Sciences Man of the Year",
"year" : 1969,
"by" : "Data Processing Management Association",
"monetaryRewards": true
},
{
"award" : "Distinguished Fellow",
"year" : 1973,
"by" : " British Computer Society",
"monetaryRewards": true
},
{
"award" : "W. W. McDowell Award",
"year" : 1976,
"by" : "IEEE Computer Society",
"monetaryRewards": false
}
]
}
我正在尝试编写一个查询,使我能够检索所有 monetaryRewards
都为真的文档。因此,考虑到以前的文件:
_id = 1 -> there is only one monetaryRewards and it is false. The query should not select it;
_id = 2 -> There are three awards and the monetaryRewards fields are always true. The query should select it;
_id = 3 -> There are three awards where monetaryRewards is twice true and once false. The query should not select it;
我写了以下查询:
db.bios.find( { awards: {$not: {$elemMatch:{"monetaryRewards":false}}}} )
查询工作正常。后来我意识到我的 bios
集合也可能不包含 monetaryRewards
字段,例如可能有另一个文档:
{
"_id" : 4,
"name" : {
"first" : "Kristen",
"last" : "Nygaard"
},
"awards" : [
{
"award" : "Rosing Prize",
"year" : 1999,
"by" : "Norwegian Data Association",
"monetaryRewards":true
},
{
"award" : "Turing Award",
"year" : 2001,
"by" : "ACM"
}
}
在这种情况下,我的查询失败了,因为它将缺少 monetaryRewards
视为 true,而在我的情况下它应该是 false。
如何解决我的查询?
在这里你可以找到 mongoplayground ,你可以看到错误选择了 _id=4 的文档。
您可以 $map
awards.monetaryRewards
到辅助布尔数组。使用 $ifNull
来满足缺少字段的情况。然后使用$allElementsTrue
进行过滤。
db.collection.aggregate([
{
"$addFields": {
"filterArr": {
"$map": {
"input": "$awards",
"as": "a",
"in": {
$ifNull: [
"$$a.monetaryRewards",
false
]
}
}
}
}
},
{
"$match": {
$expr: {
"$allElementsTrue": "$filterArr"
}
}
},
{
$project: {
filterArr: false
}
}
])
这里是Mongo playground供您参考。