MongoDB 查询帮助 - 查询子对象中任意键的值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19802502/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
MongoDB Query Help - query on values of any key in a sub-object
提问by mc5382
I want to perform a query on this collection to determine which documents have any keys in things that match a certain value. Is this possible?
我想对该集合执行查询,以确定哪些文档在与某个值匹配的事物中具有任何键。这可能吗?
I have a collection of documents like:
我有一系列文件,例如:
{
"things": {
"thing1": "red",
"thing2": "blue",
"thing3": "green"
}
}
EDIT: for conciseness
编辑:为了简洁
回答by JohnnyHK
If you don't know what the keys will be and you need it to be interactive, then you'll need to use the (notoriously performance challenged) $where
operator like so (in the shell):
如果您不知道键是什么并且需要它是交互式的,那么您需要$where
像这样使用(众所周知的性能挑战)运算符(在外壳中):
db.test.find({$where: function() {
for (var field in this.settings) {
if (this.settings[field] == "red") return true;
}
return false;
}})
If you have a large collection, this may be too slow for your purposes, but it's your only option if your set of keys is unknown.
如果您有大量集合,这对于您的目的来说可能太慢了,但如果您的密钥集未知,这是您唯一的选择。
MongoDB 3.6 Update
MongoDB 3.6 更新
You can now do this without $where
by using the $objectToArray
aggregation operator:
您现在可以在不$where
使用$objectToArray
聚合运算符的情况下执行此操作:
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'}}
])
回答by WiredPrairie
I'd suggest a schema change so that you can actually do reasonable queries in MongoDB.
我建议更改架构,以便您实际上可以在 MongoDB 中进行合理的查询。
From:
从:
{
"userId": "12347",
"settings": {
"SettingA": "blue",
"SettingB": "blue",
"SettingC": "green"
}
}
to:
到:
{
"userId": "12347",
"settings": [
{ name: "SettingA", value: "blue" },
{ name: "SettingB", value: "blue" },
{ name: "SettingC", value: "green" }
]
}
Then, you could index on "settings.value"
, and do a query like:
然后,您可以对 进行索引"settings.value"
,并执行如下查询:
db.settings.ensureIndex({ "settings.value" : 1})
db.settings.find({ "settings.value" : "blue" })
The change really is simple ..., as it moves the setting name and setting value to fully indexable fields, and stores the list of settings as an array.
更改确实很简单...,因为它将设置名称和设置值移动到完全可索引的字段,并将设置列表存储为数组。
If you can't change the schema, you could try @JohnnyHK's solution, but be warned that it's basically worst case in terms of performance and it won't work effectively with indexes.
如果您无法更改架构,您可以尝试@JohnnyHK的解决方案,但请注意,就性能而言,这基本上是最坏的情况,并且无法有效地与索引一起使用。
回答by twboc
Sadly, none of the previous answers address the fact that mongo can contain nested values in arrays or nested objects.
遗憾的是,之前的答案都没有解决 mongo 可以在数组或嵌套对象中包含嵌套值的事实。
THIS IS THE CORRECT QUERY:
这是正确的查询:
{$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")
}}
Since calling typeof on array or nested object will return 'object' this means that the query will iterate on all nested elements and will iterate through all of them until the key with value will be found.
由于在数组或嵌套对象上调用 typeof 将返回“object”,这意味着查询将迭代所有嵌套元素,并将迭代所有这些元素,直到找到带值的键。
You can check previous answers with a nested value and the results will be far from desired.
您可以使用嵌套值检查以前的答案,结果将与预期相去甚远。
Stringifying the whole object is a hit on performance since it has to iterate through all memory sectors one by one trying to match them. And creates a copy of the object as a string in ram memory (both inefficient since query uses more ram and slow since function context already has a loaded object).
对整个对象进行字符串化会影响性能,因为它必须一个一个地遍历所有内存扇区以尝试匹配它们。并在 ram 内存中以字符串形式创建对象的副本(由于查询使用更多的 ram 和速度慢,因为函数上下文已经加载了对象,因此效率低下)。
The query itself can work with objectId, string, int and any basic javascript type you wish.
查询本身可以使用 objectId、string、int 和您希望的任何基本 javascript 类型。