我需要加入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
还有替代品吗?或者至少是否有实施策略来处理像我这样的用例?
答案 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
的集合中,以避免同时产生影响。