2012-05-01 1 views
1

J'essaie de comprendre cette carte/réduire le système dans mongoDB. J'ai le schéma/la disposition de base suivant dans ma collection.mongoDB Map/Reduce

{ 
    _id: 1, 
    name: n1, 
    website: w1, 
    tags: [ 
     myTag1, 
     myTag3 
    ] 
} 

{ 
    _id: 2, 
    name: n2, 
    website: w2, 
    tags: [ 
     myTag2, 
     myTag3 
    ] 
} 

{ 
    _id: 3, 
    name: n3, 
    website: w3, 
    tags: [ 
     myTag2, 
     myTag4 
    ] 
} 

Comment puis-je récupérer un tableau de balises uniques? Je voudrais que cela me soit retourné pour un usage ultérieur.

{ 
    tags: [ 
     myTag1, 
     myTag2, 
     myTag3, 
     myTag4 
    ] 
} 

D'ailleurs ce que je suis venu avec, mais il renvoie simplement le _id et les balises de chaque élément au lieu de combiner les balises en un seul objet.

var map = function() {emit(this._id,{tags: this.tags});}; 

var reduce = function(key, values) { 
    var t = []; 

    values.forEach(function(doc) { 
     var tags = doc.tags; 
     tags.forEach(function(tag) { 
      if (!(tag in t)) { 
       t.push(tag); 
      } 
     }); 
    }); 

    return {tags: t}; 
}; 

var op = db.businesses.mapReduce(map, reduce, {out: "mr_results"}); 

db[op.result].find(); 

Répondre

2

Vous n'avez pas besoin d'utiliser map-reduce dans votre cas. Il suffit d'utiliser la fonction distinct:

db.businesses.distinct('tags') 

Vous pouvez l'essayer dans le shell mongo:

> use test 
switched to db test 
> db.businesses.insert({tags: ['tag1', 'tag2']}) 
> db.businesses.insert({tags: ['tag3', 'tag4']}) 
> db.businesses.find() 
{ "_id" : ObjectId("4fa05b2b036495bf4ac9c0cc"), "tags" : [ "tag1", "tag2" ] } 
{ "_id" : ObjectId("4fa05b33036495bf4ac9c0cd"), "tags" : [ "tag3", "tag4" ] } 

> db.businesses.distinct('tags') 
[ "tag1", "tag2", "tag3", "tag4" ] 

En outre, vous devez garder à l'esprit que map/reduce dans MongoDB ne convient pas pour effectuer des requêtes en temps réel .

+0

Cela se traduit par '[ \t [ myTag1, myTag3 ], \t [ myTag2, myTag3 ], \t [ myTag2, myTag4 ] ] ' J'ai besoin '[ \t [ myTag1, myTag2, \t \t myTag3, \t \t myTag4 ] ]' – Brandon

+0

Hmm, étrange. J'ai posté une mise à jour avec un exemple du shell mongo, peut-être que ça aide. – Matt

+0

C'est très étrange, le mien ne fait pas ce que montre cet exemple – Brandon

1

En utilisant MongoDB MapReduce, vous pouvez le faire comme suit:

function m() { 
    this.tags.forEach(function(x) { emit('tag', x); }); 
} 
function r(k, v) { 
    var res = {}; 
    v.forEach(function(x) { res[x] = true; }); 
    return res; 
} 
db.businesses.mapReduce(m, r, {out:'out'}); 
// Now the 'out' collection has a record whose "value" property 
// has a key for each of the tags in the source collection. 
function getTags(coll) { 
    var tags=[], o=db[coll].find()[0].value; 
    for (var i in o) { tags.push(i) } 
    return tags; // Same as Object.keys(db[coll].find()[0].value) 
} 
listTags('out'); // => ['myTag1', 'myTag2', 'myTag3', 'myTag4']