2012-05-01 3 views
1

Я пытаюсь выяснить эту карту/уменьшить систему в mongoDB. У меня есть следующая базовая схема/макет в моей коллекции.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 
    ] 
} 

Как я могу получить массив уникальных тегов? Я бы хотел, чтобы это было возвращено мне для дальнейшего использования.

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

Кстати, это то, что я придумал, но он просто возвращает _id и теги для каждого элемента вместо объединения тегов в один объект.

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

ответ

2

Нет необходимости использовать уменьшение карты в вашем случае. Просто используйте distinct функцию:

db.businesses.distinct('tags') 

Вы можете попробовать его в Монго оболочки:

> 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" ] 

Кроме того, следует иметь в виду, что карта/уменьшить в MongoDB не подходит для реального времени выполнения запросов ,

+0

Это приводит к '[ \t [ мойтег1, MyTag3 ], \t [ myTag2, MyTag3 ], \t [ myTag2, myTag4 ] ] ' мне нужно '[ \t [ мойтег1, myTag2, \t \t MyTag3, \t \t myTag4 ] ]' – Brandon

+0

Хм, странно. Я опубликовал обновление с примером из оболочки mongo, возможно, это помогает. – Matt

+0

Это ОЧЕНЬ странно, мой не делает то, что показывает этот пример вообще – Brandon

1

Использование MongoDB MapReduce вы могли бы сделать это следующим образом:

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']