Dobře, je to trochu složitější, protože budete muset použít nějakou rekurzi.
Aby se rekurze uskutečnila, budete muset mít možnost uložit některé funkce na server.
Krok 1:definujte některé funkce a umístěte je na stranu serveru
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 } );
Krok 2:definujte mapu a zredukujte funkce
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; }
Krok 3:spusťte zmenšení mapy a podívejte se na výsledky
mr = db.runCommand({"mapreduce" : "things", "map" : map, "reduce" : reduce,"out": "things" + "_keys"});
db[mr.result].distinct("_id");
Výsledky, které získáte, jsou:
["_id", "_id.isObjectId", "_id.str", "_id.tojson", "egg", "egg.0", "foo", "foo.bar", "foo.bar.baaaar", "hello", "type", "type.0", "type.1"]
Je zde jeden zřejmý problém, přidáváme sem některá neočekávaná pole:1. údaje _id2. .0 (na vejci a typu)
Krok 4:Některé možné opravy
Pro problém č. 1 oprava je poměrně snadná. Stačí upravit map
funkce. Změňte toto:
emit(base + "." + key, null); if( isArray...
na toto:
if(key != "_id") { emit(base + "." + key, null); if( isArray... }
Problém č. 2 je trochu více kostkovaná. Chtěli jste vše klíče a technicky "vejce.0" je platný klíč. m_sub
můžete upravit ignorovat takové číselné klávesy. Ale je také snadné vidět situaci, kdy se to vrátí. Řekněme, že máte asociativní pole uvnitř běžného pole, pak chcete, aby se objevilo „0“. Zbytek řešení nechám na vás.