2012-05-01 121 views
1

我想弄清楚这个map/reduce系统在mongoDB。我的集合中有以下基本架构/布局。mongoDB地图/减少

{ 
    _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

有没有必要在您的情况下使用map-reduce。只需使用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中说的map/reduce不适合实时查询。

+0

导致 '[ \t [ MyTag1中, MyTag3中 ], \t [ myTag2, MyTag3中 ], \t [ myTag2, myTag4 ] ]' 我需要 '[ \t [ MyTag1中, myTag2, \t \t MyTag3中, \t \t myTag4 ] ]' – Brandon

+0

嗯,奇怪。我用mongo shell的一个例子发布了一个更新,可能有帮助。 – 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']