【问题标题】:how to create a mongodb query that finds if a number is between two fields?如何创建一个 mongodb 查询来查找一个数字是否在两个字段之间?
【发布时间】:2014-05-25 05:44:10
【问题描述】:

数据库中的对象有一个“属性”数组,可以保存不同的对象。其中一些表示数字或范围,看起来像:

{'value': 10}

或

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

在查询集合以获取特定数字(例如 X)时,我想查找值等于 X 或 minValue

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

缺点是如果属性数组包含多个指定 minValue 和 maxValue 的对象,则 X 可以在它们之间。例如

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

将匹配 X = 8。可以改进查询以尊重属性中的对象结构吗?

【问题讨论】:

  • 你能展示一些收集的文件吗?

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

您基本上想以这种形式使用$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 }
)

【讨论】:

    猜你喜欢
    • 2020-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-12
    • 1970-01-01
    • 1970-01-01
    • 2016-07-10
    • 2017-04-20
    相关资源
    最近更新 更多