【问题标题】:MongoDB find value in list of listsMongoDB在列表列表中查找值
【发布时间】:2015-10-17 18:16:11
【问题描述】:

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

这是我目前拥有的结构示例。

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

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

我目前有这个:

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

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

【问题讨论】:

标签: mongodb mongodb-query pymongo


【解决方案1】:

您需要任何查询元素的“直接路径”,并且“数据”不是您需要在此处搜索的路径的“顶级”,而是“项目 1”或“项目 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",这允许仅针对该路径的单一条件来测试所有元素

【讨论】:

  • 感谢您提供真正全面的答案。这是一个巨大的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-10
  • 2017-12-13
  • 1970-01-01
  • 2019-08-18
  • 2012-09-26
  • 2017-03-26
相关资源
最近更新 更多