当处理需要在Realtieme中多次加入的易失集合时,MapReduce是否是正确的选择?

时间:2014-09-25 11:52:14

标签: mongodb join mapreduce

我需要加入2个集合...所以我尝试了MongoDB提供的map-reduce功能。鉴于以下集合:

transactions

{ "_id": 1, "userId": 1000, "amount": 0.75, "btcAddress": "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i" }
{ "_id": 2, "userId": 2000, "amount": 0.55, "btcAddress": "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW63i" }

users

{ "_id": 1000, "username": "joe", "email": "joe@domain.com" }
{ "_id": 2000, "username": "tim", "email": "tim@domain.com" }

我需要制作这样的东西:

{ "_id": 1, "username": "joe", "email": "joe@domain.com", "amount": 0.75, "btcAddress": "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i" }
{ "_id": 2, "username": "tim", "email": "tim@domain.com", "amount": 0.55, "btcAddress": "1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW63i" }

文档很清楚,所以我只是定义了这样的映射函数......

transactions_map = function() {
    ...
}

users_map = function() {
    ...
}

...和reduce(merge)函数如下:

r = function(key, values) {
  ...
}

作为最后一步,我只是调用mapReduce

res = db.transactions.mapReduce(transactions_map, r, {out: {reduce : 'joined'}});
res = db.users.mapReduce(users_map, r, {out: {reduce : 'joined'}});

这可以产生并产生预期的结果......但是有一些考虑因素。 mapReduce生成一个临时集合,在我的情况下,这会引发并发问题。我想我需要在再次调用mapRedudce之前删除临时集合...但是这个过程可能会被一个小时多次触发并且被许多用户同时触发。 mapReduce似乎是为统计而设计的,而我需要实时非常类似于SQL join,因为transactions集合经常发生变化。

mapReduce还有替代品吗?或者至少是否有实施策略来处理像我这样的用例?

1 个答案:

答案 0 :(得分:1)

如果仅以联接为例,我认为 mapReduce 是不必要的。
我试着这样。

var result = [];
db.transactions.find().forEach(function(e) {
    var user = db.users.findOne({_id: e.userId}, {_id:0});
    delete e.userId;
    if (user) {
        for (var x in user) {
            e[x] = user[x];
        }
    }
    result.push(e);
});

如果结果非常大并且您想要保存到临时集合,则可以将新文档保存到循环中名为new ObjectId().str的集合中,以避免同时产生影响。