gpt4 book ai didi

mongodb - 使用 map/reduce 映射集合中的属性

转载 作者:IT老高 更新时间:2023-10-28 13:03:50 25 4
gpt4 key购买 nike

更新: MongoDB Get names of all keys in collection 的后续行动.

正如 Kristina 所指出的那样,可以使用 Mongodb 的 map/reduce 列出集合中的键:

db.things.insert( { type : ['dog', 'cat'] } );
db.things.insert( { egg : ['cat'] } );
db.things.insert( { type : [] });
db.things.insert( { hello : [] } );

mr = db.runCommand({"mapreduce" : "things",
"map" : function() {
for (var key in this) { emit(key, null); }
},
"reduce" : function(key, stuff) {
return null;
}})

db[mr.result].distinct("_id")

//output: [ "_id", "egg", "hello", "type" ]

只要我们只想获取位于第一层深度的键,就可以了。但是,它将无法检索位于更深层次的那些 key 。如果我们添加一条新记录:

db.things.insert({foo: {bar: {baaar: true}}})

然后我们再次运行上面的 map-reduce +distinct 片段,我们将得到:

[ "_id", "egg", "foo", "hello", "type" ] 

但是我们不会得到嵌套在数据结构中的 barbaaar 键。问题是:我如何检索所有键,无论它们的深度如何?理想情况下,我实际上希望脚本深入到所有深度,产生如下输出:

["_id","egg","foo","foo.bar","foo.bar.baaar","hello","type"]      

提前谢谢你!

最佳答案

好的,这有点复杂,因为您需要使用一些递归。

要实现递归,您需要能够在服务器上存储一些函数。

第一步:定义一些函数,放到服务器端

isArray = function (v) {
return v && typeof v === 'object' && typeof v.length === 'number' && !(v.propertyIsEnumerable('length'));
}

m_sub = function(base, value){
for(var key in value) {
emit(base + "." + key, null);
if( isArray(value[key]) || typeof value[key] == 'object'){
m_sub(base + "." + key, value[key]);
}
}
}

db.system.js.save( { _id : "isArray", value : isArray } );
db.system.js.save( { _id : "m_sub", value : m_sub } );

第 2 步:定义 map 和 reduce 函数

map = function(){
for(var key in this) {
emit(key, null);
if( isArray(this[key]) || typeof this[key] == 'object'){
m_sub(key, this[key]);
}
}
}

reduce = function(key, stuff){ return null; }

第 3 步:运行 map reduce 并查看结果

mr = db.runCommand({"mapreduce" : "things", "map" : map, "reduce" : reduce,"out": "things" + "_keys"});
db[mr.result].distinct("_id");

你会得到的结果是:

["_id", "_id.isObjectId", "_id.str", "_id.tojson", "egg", "egg.0", "foo", "foo.bar", "foo.bar.baaaar", "hello", "type", "type.0", "type.1"]

这里有一个明显的问题,我们在这里添加了一些意想不到的字段: 1. _id 数据 2. .0(关于鸡蛋和类型)

第 4 步:一些可能的修复方法

对于问题#1,修复相对容易。只需修改 map 函数。改变这个:

emit(base + "." + key, null); if( isArray...

到这里:

if(key != "_id") { emit(base + "." + key, null); if( isArray... }

问题 #2 有点冒险。您想要 all 键,并且从技术上讲,“egg.0”is 是一个有效的键。您可以修改 m_sub 以忽略此类数字键。但也很容易看到事与愿违的情况。假设您在常规数组中有一个关联数组,那么您希望“0”出现。我将把剩下的解决方案留给你。

关于mongodb - 使用 map/reduce 映射集合中的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2997004/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com