查询类似对象的MongoDB数组

时间:2016-10-18 06:50:58

标签: mongodb mongodb-query

我使用旧的MongoDB,其中一个集合中的对象的结构如此。

{
  "_id": ObjectId("57fdfcc7a7c81fde38b79a3d"),
  "parameters": [
    {
      "key": "key1",
      "value": "value1"
    },
    {
      "key": "key2",
      "value": "value2"
    }
  ]
}

问题是参数是一个对象数组,这使得高效的查询变得困难。可以有大约50个不同的对象,它们都具有"key""value"属性。是否可以进行查询,查询在一个对象中定位"key""value"?我试过了

db.collection.find({$and:[{"parameters.key":"value"}, {"parameters.value":"another value"}]})

但此查询会命中parameters数组中的所有对象。

编辑。 Nikhil Jagtiani找到solution我的原始问题,但实际上我应该能够查询目标数组中的多个对象。例如。检查参数数组中两个不同对象的键和值。

3 个答案:

答案 0 :(得分:1)

请参考下面的mongo shell聚合查询:

db.collection.aggregate([
    {
        $unwind:"$parameters"
    },
    {
        $match:
            {
                "parameters.key":"key1",
                "parameters.value":"value1"
            }
    }

])

1)第1阶段 - Unwind:从输入文档解构数组字段,为每个元素输出文档。每个输出文档都是输入文档,数组字段的值由元素替换。

2)阶段2 - Match:过滤文档以仅将符合指定条件的文档传递到下一个管道阶段。

如果没有聚合,即使一个子文档匹配,查询也会返回整个文档。 此管道只返回所需的子文档。

编辑:如果您需要指定多个键值对,我们需要的是$ in for parameters字段。

db.collection.aggregate([{$unwind:"$parameters"},{$match:{"parameters":{$in:[{ "key" : "key1", "value" : "value1"},{ "key" : "key2", "value" : "value2" }]}}}])

将以下两对键值作为子文档进行匹配:

1){" key" :" key1"," value" :" value1" }

2){" key" :" key2"," value" :" value2" }

答案 1 :(得分:1)

聚合框架中有一个 $filter 运算符,非常适合此类查询。有点冗长但非常有效,您可以按如下方式使用它:

db.surveys.aggregate([
    { "$match": { 
        "$and": [
            {
                "parameters.key": "key1", 
                "parameters.value": "val1"
            },
            {
                "parameters.key": "key2", 
                "parameters.value": "val2"
            }           
        ]
    }},
    {
        "$project": {
            "parameters": {
                "$filter": {
                    "input": "$parameters",
                    "as": "item",
                    "cond": {
                        "$or": [
                            {
                                "$and" : [
                                    { "$eq": ["$$item.key", "key1"] },
                                    { "$eq": ["$$item.value", "val1"] }
                                ]
                            },
                            {
                                "$and" : [
                                    { "$eq": ["$$item.key", "key2"] },
                                    { "$eq": ["$$item.value", "val2"] }
                                ]
                            }
                        ]
                    }
                }
            }
        }
    }
])

您也可以在MongoDB 2.6中使用更多set operators而不使用 $unwind 执行此操作:

db.surveys.aggregate([
    { "$match": {
        "$and": [
            {
                "parameters.key": "key1", 
                "parameters.value": "val1"
            },
            {
                "parameters.key": "key2", 
                "parameters.value": "val2"
            }           
        ]
    }},
    { 
        "$project": {
            "parameters": {
                "$setDifference": [
                    { "$map": {
                        "input": "$parameters",
                        "as": "item",
                        "in": {
                             "$cond": [
                                { "$or": [
                                    {
                                        "$and" : [
                                            { "$eq": ["$$item.key", "key1"] },
                                            { "$eq": ["$$item.value", "val1"] }
                                        ]
                                    },
                                    {
                                        "$and" : [
                                            { "$eq": ["$$item.key", "key2"] },
                                            { "$eq": ["$$item.value", "val2"] }
                                        ]
                                    }
                                ]},
                                "$$item",
                                false
                            ]
                        }
                    }},
                    [false]
                ]
            }
        }
    }
])

对于使用MongoDB 2.4的解决方案,您需要使用 $unwind 运算符:

db.surveys.aggregate([
    { "$match": {
        "$and": [
            {
                "parameters.key": "key1", 
                "parameters.value": "val1"
            },
            {
                "parameters.key": "key2", 
                "parameters.value": "val2"
            }           
        ]
    }},
    { "$unwind": "$parameters" },
    { "$match": {
        "$and": [
            {
                "parameters.key": "key1", 
                "parameters.value": "val1"
            },
            {
                "parameters.key": "key2", 
                "parameters.value": "val2"
            }           
        ]
    }},
    {
        "$group": {
            "_id": "$_id",
            "parameters": { "$push": "$parameters" }            
        }
    }
]);

答案 2 :(得分:0)

  

是否可以进行查询,查询的目标是“key”和   一个物体内的“价值”?

如果您知道要预先查询哪个对象(id)(在查询查询中作为输入参数给出),则可以执行此操作。如果那是不可能的,那么我们可以尝试以下方法进行有效的查询。

在parameters.key上构建索引,如果需要也在parameters.value上构建索引。这将大大提高查询性能。

请参阅

https://docs.mongodb.com/manual/indexes/

https://docs.mongodb.com/manual/core/index-multikey/