MongoDB在列表列表中查找值

时间:2015-10-17 18:16:11

标签: mongodb mongodb-query pymongo

我正在使用MongoDB搜索包含列表列表的元素,其中列表中的至少一个项目与搜索参数匹配。

这是我目前所拥有的结构的一个例子。

{  
   "Item 1":{  
      "data":[  
         ["green", 1]
      ]
   },
   "Item 2":{  
      "data":[  
         ["blue", 9],
         ["green", 1]
      ]
   }
}

我想搜索数据列表中值为“绿色”的所有项目。

我目前有这个:

my_data.find({'data': {'$in': ['green']}})

但是,没有返回任何结果。

1 个答案:

答案 0 :(得分:7)

你需要一条"直接路径"任何查询的元素和"数据"不是"顶级"你需要在这里搜索的路径,而是#34;项目1和#34;或"项目2"在文件和"数据"是其中的一个子元素。

基本情况是使用"dot notation",其中根元素是"已知"至少可能存在,并且还注意到$in运算符不仅仅是为了匹配数组中的值,因为MongoDB并不关心。但是你需要一个嵌套的$elemMatch代替:

db.my_data.find({
    "$or": [
        { "Item 1.data": { 
            "$elemMatch": { 
                "$elemMatch": { "$eq": "green" }
            }
        }},
        { "Item 2.data": {
            "$elemMatch": {
                "$elemMatch": { "$eq": "green" }
            }
        }}
    ]
})

没有"通配符"用于匹配前一个路径的一部分,因此有必要在$or条件内声明完整路径以搜索文档中的每个可能路径。

如果写出所有可能的前缀键是不切实际的,那么您唯一的另一种方法是使用$where的JavaScript评估来确定匹配的逻辑:

db.my_data.find(function() {
    var doc = this;
    delete doc._id;

    var matched = false;
    for ( k in doc ) {
        matched = doc[k].data.some(function(el) { 
            return el.some(function(inner) {
                return inner === "green";
            });
        });
        if (matched) break;
    }
    return matched;
})

或者使用"数据"实际测试可能元素的逻辑的一些变化。数组包含你的"绿色"值。它不是一个很好的解决方案,因为$where需要在每个文档上执行才能评估条件,因此无法使用索引来过滤结果。这意味着扫描整个集合,基本上是最慢的方法。

还要显示" shell快捷方式"写这个,因为function()内容只是作为"字符串"提交。在$where的pymongo或其他语言驱动程序的参数中,但基本的上下文是它是在服务器上评估的JavaScript代码。

更好的是更改文档,以便始终存在要查询的元素的一致路径。如:

{
    "items": [
        { "name": "Item 1", "data": [["green", 1]] },
        { "name": "Item 2", "data": [["blue", 9], ["green", 1]] }
    ]  
}

然后你可以发出这个简单的查询:

 db.my_data.find({ "items.data": { "$elemMatch": { "$elemMatch": { "$eq": "green" } } } })

作为"路径"总是"items.data"这允许只有一条路径才能测试所有元素