我在MongoDB集合中收集了大量event
个文档。每个文档中的字段包括:
userId
(数据库ID,如果用户已登录)visitorId
(Cookie id,始终存在)eventType
(用户刚刚完成的事件类型)特别感兴趣的是一个eventType
- “购买”类型。我要做的是运行一个基本上说:
获取执行特定活动的用户的所有购买活动的列表。
最初我的想法是简单地下载执行事件的所有用户的列表,然后将其用作大规模查询条件。然而,这感觉很难看,而且我想想对于更大的查询,它在内存方面会非常昂贵。
有更好/更聪明的方法吗?
答案 0 :(得分:2)
我非常怀疑使用聚合框架会有什么好处。另外我不清楚你可以在一个查询中做你想做的事情(我认为这是不可能的)。另一方面,我相信你的出发方式是最好的。我会做什么:
你有你的收藏:
db.events.insert({userId: 1, event: 1})
db.events.insert({userId: 2, event: 1})
db.events.insert({userId: 3, event: 4})
db.events.insert({userId: 1, event: 4})
db.events.insert({userId: 3, event: 2})
db.events.insert({userId: 1, event: 3})
db.events.insert({userId: 3, event: 1})
获取完成某些活动的所有唯一身份用户:
var usersSet = {};
db.events.find({event: 1}, {userId: 1, _id:0}).forEach(function(el){
return usersSet[el.userId] = 1;
});
注意,因为mongoshell没有正常的set数据类型(如果你使用js/node.js it finally has),我将它存储在对象中,稍后如果你的id是整数,它们将丢失它们的类型。这就是我之后用map(Number)
翻译它们的原因。
拥有您的用户,您可以通过活动执行类似的操作。如果您需要拥有所有事件(并非我正在做的那么独特),只需将eventSet
更改为eventArray
并按下返回功能。
var eventsSet = {}
db.events.find({
userId: {$in: Object.keys(usersSet).map(Number)}
}, {
event: 1, _id:0
}).forEach(function(el){
return eventsSet[el.event] = 1;
});
此Object.keys(eventsSet).map(Number)
将包含所有唯一事件。
答案 1 :(得分:1)
我想说这种查询不适合mongodb。它可以通过不同的方式完成,但它们都没有为真正的大数据集提供良好的性能。
它的想法是你可能有另一个集合来保持用户及其事件的发生。
{
userid : "_user_id",
events : ["event_type1", "event_type2"]
}
你需要保持这个集合是最新的(即每个事件的upsert)
或者您可以保留事件计数以供将来使用,例如:
{
userid : "_user_id",
event_type_1 : 5,
event_type_2 : 16,
event_type_3 : 2,
}
你可以查询存在和出现次数。对于第一个选项,您需要将新事件类型推送到特定用户的events
数组,对于第二个选项,您将自动增加事件类型的出现。