如何在任意深度查找 MongoDB 字段名称
How to find MongoDB field name at arbitrary depth
我将一些草率的 XML 数据导入 Mongo 数据库。每个文档都有嵌套的子文档,深度约为 5-10。我想 find() 具有特定字段的特定值的文档,其中该字段可能出现在子文档中的任何深度(并且可能出现多次)。
我目前正在将每个文档拉入 Python,然后搜索该词典,但如果我能声明一个过滤器原型,其中数据库将仅 return 个具有特定特征的文档,那就太好了其内容中某处字段名称的值。
这是一个示例文档:
{
"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" 字段值的文档。
你说得对,BSON 文件不是 XML 文件。由于 XML 被加载到由 "nodes" 组成的树结构中,因此搜索任意键非常容易。
MonoDB文档处理起来不是那么简单,这在很多方面都是"database",所以一般希望有一定的"uniformity"数据位置,才能使它"index" 和搜索都很容易。
不过,这是可以做到的。但这当然意味着在服务器上执行递归过程,这意味着 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);
}
)
所以基本上,测试对象中存在的键,看它们是否匹配所需的 "field name" 和内容。如果其中一个键恰好是 "object",则递归到函数中并再次检查。
JavaScript .some()
确保找到的 "first" 匹配将从搜索功能 return 给出 true
结果和 return在某个深度存在 "key/value" 的对象。
请注意,$where
本质上意味着遍历整个集合,除非有一些其他有效的查询过滤器可以应用于集合中的 "index"。
所以请谨慎使用,或者根本不用,只需将数据重组为更可行的形式即可。
但这会给你匹配。
这是一个例子,我用它来递归搜索文档结构中任何地方的键值:
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;
}
}
})
我将一些草率的 XML 数据导入 Mongo 数据库。每个文档都有嵌套的子文档,深度约为 5-10。我想 find() 具有特定字段的特定值的文档,其中该字段可能出现在子文档中的任何深度(并且可能出现多次)。
我目前正在将每个文档拉入 Python,然后搜索该词典,但如果我能声明一个过滤器原型,其中数据库将仅 return 个具有特定特征的文档,那就太好了其内容中某处字段名称的值。
这是一个示例文档:
{
"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" 字段值的文档。
你说得对,BSON 文件不是 XML 文件。由于 XML 被加载到由 "nodes" 组成的树结构中,因此搜索任意键非常容易。
MonoDB文档处理起来不是那么简单,这在很多方面都是"database",所以一般希望有一定的"uniformity"数据位置,才能使它"index" 和搜索都很容易。
不过,这是可以做到的。但这当然意味着在服务器上执行递归过程,这意味着 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);
}
)
所以基本上,测试对象中存在的键,看它们是否匹配所需的 "field name" 和内容。如果其中一个键恰好是 "object",则递归到函数中并再次检查。
JavaScript .some()
确保找到的 "first" 匹配将从搜索功能 return 给出 true
结果和 return在某个深度存在 "key/value" 的对象。
请注意,$where
本质上意味着遍历整个集合,除非有一些其他有效的查询过滤器可以应用于集合中的 "index"。
所以请谨慎使用,或者根本不用,只需将数据重组为更可行的形式即可。
但这会给你匹配。
这是一个例子,我用它来递归搜索文档结构中任何地方的键值:
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;
}
}
})