我需要加入两个集合。。。所以我尝试了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
的替代品吗?或者至少有实现策略来处理像我这样的用例吗?
如果只是以连接为例,我认为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
的集合中,以避免同时发生影响。