MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Usando map/reduce para mapear as propriedades em uma coleção


OK, isso é um pouco mais complexo porque você precisará usar alguma recursão.

Para que a recursão aconteça, você precisará armazenar algumas funções no servidor.

Etapa 1:defina algumas funções e coloque-as no lado do servidor

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

Etapa 2:definir as funções de mapa e redução

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

Etapa 3:execute a redução do mapa e veja os resultados

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

Os resultados que você obterá são:
["_id", "_id.isObjectId", "_id.str", "_id.tojson", "egg", "egg.0", "foo", "foo.bar", "foo.bar.baaaar", "hello", "type", "type.0", "type.1"]

Há um problema óbvio aqui, estamos adicionando alguns campos inesperados aqui:1. os dados _id2. o .0 (no ovo e tipo)

Etapa 4:algumas correções possíveis


Para o problema nº 1 a correção é relativamente fácil. Basta modificar o map função. Mude isso:
emit(base + "." + key, null); if( isArray...

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

Problema nº 2 é um pouco mais arriscado. Você queria todos keys e tecnicamente "egg.0" é uma chave válida. Você pode modificar m_sub ignorar essas teclas numéricas. Mas também é fácil ver uma situação em que isso sai pela culatra. Digamos que você tenha um array associativo dentro de um array regular, então você quer que o "0" apareça. Vou deixar o resto dessa solução para você.