如何创建一个mongodb查询,查找数字是否在两个字段之间?

时间:2014-04-11 07:34:40

标签: mongodb mongodb-query aggregation-framework

数据库中的对象具有'属性'数组,可以容纳不同的对象。其中一些呈现数字或范围,看起来像:

{'value': 10}

{'minValue': 4, 'maxValue': 8}

当查询特定数字(如X)的集合时,我想查找其中值等于X或minValue< = X< = maxValue的所有文档。我第一次尝试查询看起来像是

db.Pool0.find({$or: [{'properties.value': X}, {'properties.minValue': {$lte: X}, 'properties.maxValue': {$gte: X}}]}, {'_id': 1}).pretty()

缺点是如果properties数组包含指定minValue和maxValue的多个对象,则X可以位于其中任何一个之间。例如

"properties" : [
    {
        "minValue" : 4,
        "maxValue" : 6
    },
    {
        "minValue" : 10,
        "maxValue" : 20
    }
]

将匹配X = 8.是否可以改进查询以便尊重属性中的对象结构?

1 个答案:

答案 0 :(得分:4)

您基本上希望在此表单中使用$elemMatch并结合$or条件:

db.collection.find({
    "$or": [
        {
            "properties": { "$elemMatch": {
                "minValue": { "$lte": 8 },
                "maxValue": { "$gte": 8 }
            }}
        },
        {
            "properties.value": 8
        }
    ]
})

这包括满足包含范围的文档以及属性中字段的可能的其他键名。

但请记住,匹配文档与数组中的匹配元素不同。因此,如果您只是希望返回匹配的数组元素并且您有多个,那么您使用聚合形式:

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" }
    }}
])

但是如果只有一个你确定的匹配,那么只需使用find:

db.collection.find(
    { 
        "$or": [
            {
                "properties": { "$elemMatch": {
                    "minValue": { "$lte": 8 },
                    "maxValue": { "$gte": 8 }
                }}
            },
            {
            "properties.value": 8
            }
        ]
    },
    { "properties.$": 1 }
)