MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Verwenden von map/reduce zum Zuordnen der Eigenschaften in einer Sammlung

OK, das ist etwas komplexer, weil Sie eine Rekursion verwenden müssen.

Um die Rekursion durchzuführen, müssen Sie in der Lage sein, einige Funktionen auf dem Server zu speichern.

Schritt 1:einige Funktionen definieren und serverseitig platzieren

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 } );

Schritt 2:Karte definieren und Funktionen reduzieren

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; }

Schritt 3:Führen Sie die Kartenreduzierung aus und sehen Sie sich die Ergebnisse an

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

Die Ergebnisse, die Sie erhalten, sind:

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

Hier gibt es ein offensichtliches Problem, wir fügen hier einige unerwartete Felder hinzu:1. die _id data2. die .0 (auf Ei und Typ)

Schritt 4:Einige mögliche Korrekturen

Für Problem Nr. 1 die korrektur ist relativ einfach. Ändern Sie einfach die map Funktion. Ändern Sie dies:

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

dazu:

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

Problem Nr. 2 ist etwas heikler. Du wolltest alles Tasten und technisch gesehen "egg.0" ist ein gültiger Schlüssel. Sie können m_sub ändern solche Zifferntasten zu ignorieren. Aber es ist auch leicht, eine Situation zu sehen, in der dies nach hinten losgeht. Angenommen, Sie haben ein assoziatives Array innerhalb eines regulären Arrays, dann möchten Sie, dass "0" erscheint. Den Rest der Lösung überlasse ich Ihnen.