sql >> Database >  >> NoSQL >> MongoDB

Map/reduce gebruiken om de eigenschappen in een collectie in kaart te brengen

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.



  1. Fout:het update-bewerkingsdocument moet atomaire operatoren bevatten bij het uitvoeren van updateOne

  2. Spring Boot-integratietesten met Embedded MongoDB

  3. Hoe een subdocument in mangoest vullen nadat het is gemaakt?

  4. mongodb:het verhogen van het maximale aantal verbindingen in mongodb