MongoDB查询帮助 - 查询子对象中任何键的值

时间:2013-11-06 01:39:20

标签: mongodb

我想对此集合执行查询,以确定哪些文档在与特定值匹配的内容中具有任何键。这可能吗?

我有一系列文件,如:

{
    "things": {
        "thing1": "red",
        "thing2": "blue",
        "thing3": "green"
    }
}

编辑:为了简洁

3 个答案:

答案 0 :(得分:34)

如果您不知道密钥是什么并且您需要它是交互式的,那么您将需要使用(臭名昭着的性能挑战)$where运算符(在shell中):< / p>

db.test.find({$where: function() { 
    for (var field in this.settings) { 
        if (this.settings[field] == "red") return true;
    }
    return false;
}})

如果你有一个大集合,这对你的目的来说可能太慢,但如果你的一组密钥未知,那么这是你唯一的选择。

MongoDB 3.6更新

现在,您可以使用$objectToArray聚合运算符$where之后执行此操作:

db.test.aggregate([
  // Project things as a key/value array, along with the original doc
  {$project: {
    array: {$objectToArray: '$things'},
    doc: '$$ROOT'
  }},

  // Match the docs with a field value of 'red'
  {$match: {'array.v': 'red'}},

  // Re-project the original doc
  {$replaceRoot: {newRoot: '$doc'}}
])

答案 1 :(得分:33)

我建议更改架构,以便您可以在MongoDB中实际执行合理的查询。

自:

{
    "userId": "12347",
    "settings": {
        "SettingA": "blue",
        "SettingB": "blue",
        "SettingC": "green"
    }
}

为:

{
    "userId": "12347",
    "settings": [
        { name: "SettingA", value: "blue" },
        { name: "SettingB", value: "blue" },
        { name: "SettingC", value: "green" }
    ]    
}

然后,您可以在"settings.value"上编制索引,并执行以下查询:

db.settings.ensureIndex({ "settings.value" : 1})

db.settings.find({ "settings.value" : "blue" })

更改非常简单...,因为它将设置名称和设置值移动到完全可索引的字段,并将设置列表存储为数组。

如果您无法更改架构,可以尝试@JohnnyHKsolution,但要注意它在性能方面基本上是最糟糕的情况,并且无法有效地使用索引。

答案 2 :(得分:5)

可悲的是,之前的答案都没有解决mongo可以在数组或嵌套对象中包含嵌套值的事实。

这是正确的查询:

{$where: function() {
    var deepIterate = function  (obj, value) {
        for (var field in obj) {
            if (obj[field] == value){
                return true;
            }
            var found = false;
            if ( typeof obj[field] === 'object') {
                found = deepIterate(obj[field], value)
                if (found) { return true; }
            }
        }
        return false;
    };
    return deepIterate(this, "573c79aef4ef4b9a9523028f")
}}

由于在数组或嵌套对象上调用typeof将返回&#39; object&#39;这意味着查询将迭代所有嵌套元素,并将遍历所有嵌套元素,直到找到具有值的键。

您可以使用嵌套值检查以前的答案,结果将远非理想。

对整个对象进行字符串化会影响性能,因为它必须逐个迭代所有内存扇区以尝试匹配它们。并在ram内存中创建一个对象的副本作为字符串(由于函数上下文已经有一个加载的对象,因为查询使用更多ram和slow,因此效率低下。)

查询本身可以使用objectId,string,int和您希望的任何基本javascript类型。