TeT*_*TeT 3 mongodb mongodb-query aggregation-framework
数据库中的对象有一个“属性”数组,可以容纳不同的对象。其中一些显示数字或范围,看起来像:
{'value': 10}
Run Code Online (Sandbox Code Playgroud)
或者
{'minValue': 4, 'maxValue': 8}
Run Code Online (Sandbox Code Playgroud)
当查询特定数字(如 X)的集合时,我想找到值等于 X 或 minValue <= X <= maxValue 的所有文档。我第一次尝试查询看起来像
db.Pool0.find({$or: [{'properties.value': X}, {'properties.minValue': {$lte: X}, 'properties.maxValue': {$gte: X}}]}, {'_id': 1}).pretty()
Run Code Online (Sandbox Code Playgroud)
缺点是如果属性数组包含多个指定 minValue 和 maxValue 的对象,则 X 可以介于其中任何一个之间。例如
"properties" : [
{
"minValue" : 4,
"maxValue" : 6
},
{
"minValue" : 10,
"maxValue" : 20
}
]
Run Code Online (Sandbox Code Playgroud)
将匹配 X = 8。能否改进查询以便尊重属性中的对象结构?
你基本上想$elemMatch
结合使用$or
这种形式的条件:
db.collection.find({
"$or": [
{
"properties": { "$elemMatch": {
"minValue": { "$lte": 8 },
"maxValue": { "$gte": 8 }
}}
},
{
"properties.value": 8
}
]
})
Run Code Online (Sandbox Code Playgroud)
这包括满足包含范围的文档以及属性中字段的可能的其他键名称。
但请记住,匹配文档与匹配数组中的元素不同。因此,如果您只是希望返回匹配的数组元素并且您有多个元素,那么您可以使用聚合形式:
db.collection.aggregate([
// Matching documents is still good practice
{ "$match": {
"$or": [
{
"properties": { "$elemMatch": {
"minValue": { "$lte": 8 },
"maxValue": { "$gte": 8 }
}}
},
{
"properties.value": 8
}
]
}},
// Unwind to de-normalize
{ "$unwind": "$properties" },
// Then match to filter the elements
{ "$match": {
"$or": [
{
"properties.minValue": { "$lte": 8 },
"properties.maxValue": { "$gte": 8 }
},
{ "properties.value": 8 }
]
}},
// Reconstruct the filtered array
{ "$group": {
"_id": "$_id",
"properties": { "$push": "$properties" }
}}
])
Run Code Online (Sandbox Code Playgroud)
但是,如果您确定只有一个匹配项,那么只需将投影与 find 结合使用:
db.collection.find(
{
"$or": [
{
"properties": { "$elemMatch": {
"minValue": { "$lte": 8 },
"maxValue": { "$gte": 8 }
}}
},
{
"properties.value": 8
}
]
},
{ "properties.$": 1 }
)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4908 次 |
最近记录: |