我正在使用MongoDB搜索包含列表列表的元素,其中列表中的至少一个项目与搜索参数匹配。
这是我目前所拥有的结构的一个例子。
{
"Item 1":{
"data":[
["green", 1]
]
},
"Item 2":{
"data":[
["blue", 9],
["green", 1]
]
}
}
我想搜索数据列表中值为“绿色”的所有项目。
我目前有这个:
my_data.find({'data': {'$in': ['green']}})
但是,没有返回任何结果。
答案 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"
这允许只有一条路径才能测试所有元素