我将一些草率的XML数据导入到了Mongo数据库中。每个文档都有嵌套的子文档,深度约为5-10。我希望找到具有特定字段的特定值的()文档,其中字段可能出现在子文档中的任何深度(并且可能多次出现)。
目前,我正在将每个文档拖到Python中,然后搜索该字典,但是如果我能够声明一个过滤器原型,数据库将只返回在其内容中某个地方具有字段名的特定值的文档,那就太好了。
下面是一个示例文档:
{
"foo": 1,
"bar": 2,
"find-this": "Yes!",
"stuff": {
"baz": 3,
"gobble": [
"wibble",
"wobble",
{
"all-fall-down": 4,
"find-this": "please find me"
}
],
"plugh": {
"plove": {
"find-this": "Here too!"
}
}
}
}因此,我希望找到具有" find -this“字段的文档,并且(如果可能的话)能够找到具有" find -this”字段特定值的文档。
发布于 2015-07-03 06:56:00
在BSON文档的某些语句中,您是正确的,而不是XML文档。由于XML被加载到由“节点”组成的树结构中,因此在任意密钥上进行搜索非常容易。
MonoDB文档的处理并不那么简单,这在许多方面都是一个“数据库”,因此人们通常期望它具有一定的数据位置的“一致性”,以便于“索引”和搜索。
然而,这是可以做到的。但是,这当然意味着在服务器上执行递归进程,这意味着使用JavaScript处理$where。
作为一个基本的shell示例,但是通用function只是其他地方的$where操作符的一个字符串参数:
db.collection.find(
function () {
var findKey = "find-this",
findVal = "please find me";
function inspectObj(doc) {
return Object.keys(doc).some(function(key) {
if ( typeof(doc[key]) == "object" ) {
return inspectObj(doc[key]);
} else {
return ( key == findKey && doc[key] == findVal );
}
});
}
return inspectObj(this);
}
)因此,基本上,测试对象中的键,看看它们是否匹配所需的“字段名”和内容。如果其中一个键恰好是"object“,那么将其递归到函数中,然后再次检查。
JavaScript .some()确保找到的“第一个”匹配将从搜索函数返回,给出true结果,并返回“键/值”在某个深度存在的对象。
注意,$where本质上意味着遍历整个集合,除非有其他有效的查询筛选器可以应用于集合上的“索引”。
所以,小心使用,或者根本不使用,只需将数据重构成更可行的形式即可。
但这会给你的对手。
发布于 2016-04-29 09:13:33
下面是一个示例,用于递归搜索文档结构中任意位置的键值:
db.getCollection('myCollection').find({
"$where" : function(){
var searchKey = 'find-this';
var searchValue = 'please find me';
return searchInObj(obj);
function searchInObj(obj){
for(var k in obj){
if(typeof obj[k] == 'object' && obj[k] !== null){
if(searchInObj(obj[k])){
return true;
}
} else {
if(k == searchKey && obj[k] == searchValue){
return true;
}
}
}
return false;
}
}
})https://stackoverflow.com/questions/31197652
复制相似问题