OK, dit is een beetje ingewikkelder omdat je wat recursie moet gebruiken.
Om de recursie te laten plaatsvinden, moet je enkele functies op de server kunnen opslaan.
Stap 1:definieer enkele functies en plaats ze server-side
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 } );
Stap 2:definieer de kaart en verminder functies
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; }
Stap 3:voer de kaart uit, verklein en bekijk de resultaten
mr = db.runCommand({"mapreduce" : "things", "map" : map, "reduce" : reduce,"out": "things" + "_keys"});
db[mr.result].distinct("_id");
De resultaten die u krijgt zijn:
["_id", "_id.isObjectId", "_id.str", "_id.tojson", "egg", "egg.0", "foo", "foo.bar", "foo.bar.baaaar", "hello", "type", "type.0", "type.1"]
Er is hier een duidelijk probleem, we voegen hier enkele onverwachte velden toe:1. de _id-gegevens2. de .0 (op ei en type)
Stap 4:Enkele mogelijke oplossingen
Voor probleem #1 de oplossing is relatief eenvoudig. Wijzig gewoon de map
functie. Wijzig dit:
emit(base + "." + key, null); if( isArray...
naar dit:
if(key != "_id") { emit(base + "." + key, null); if( isArray... }
Probleem #2 is een beetje wispelturig. Je wilde allemaal sleutels en technisch gezien is "egg.0" is een geldige sleutel. U kunt m_sub
. wijzigen om dergelijke numerieke toetsen te negeren. Maar het is ook gemakkelijk om een situatie te zien waarin dit averechts werkt. Stel dat je een associatieve array binnen een reguliere array hebt, dan wil je dat die "0" verschijnt. Ik laat de rest van die oplossing aan jou over.