sql >> Databasteknik >  >> NoSQL >> MongoDB

Använda map/reduce för att kartlägga egenskaperna i en samling

OK, det här är lite mer komplicerat eftersom du måste använda lite rekursion.

För att få rekursionen att hända måste du kunna lagra vissa funktioner på servern.

Steg 1:definiera vissa funktioner och placera dem på serversidan

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

Steg 2:definiera kartan och reducera funktioner

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

Steg 3:kör kartan förminskning och titta på resultat

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

Resultaten du får är:

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

Det finns ett uppenbart problem här, vi lägger till några oväntade fält här:1. _id-data2. .0 (på ägg och typ)

Steg 4:Några möjliga korrigeringar

För problem #1 åtgärden är relativt enkel. Ändra bara map fungera. Ändra detta:

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

till detta:

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

Problem #2 är lite mer knäpp. Du ville ha alla nycklar och tekniskt "egg.0" är en giltig nyckel. Du kan ändra m_sub att ignorera sådana numeriska tangenter. Men det är också lätt att se en situation där detta slår tillbaka. Säg att du har en associativ array inuti en vanlig array, då vill du att "0" ska visas. Jag överlåter resten av den lösningen till dig.



  1. Hur tar man tillbaka borttaget utrymme utan `db.repairDatabase()`?

  2. 5 sätt att kontrollera storleken på en samling i MongoDB

  3. Hur fungerar exemplet med meddelanderäkning i Meteor docs?

  4. Laravel:Hur kontrollerar jag Redis tillgänglighet?