所以我有一个跟踪我们应用登录的MongoDB文档。基本结构如此出现:
[_id] => MongoId Object
(
[$id] => 50f6da28686ba94b49000003
)
[userId] => 50ef542a686ba95971000004
[action] => login
[time] => 1358354984
现在 - 面临的挑战是:这些条目大约有20,000个。我一直被要求查看每个用户登录的次数(由userId定义)...所以我正在寻找一种好方法来做到这一点。我见过几种可能的方法(例如,在SQL中,我可以通过按UserID分组并对其进行计数来减少登录次数 - 例如SELECT userID,count(*)from ... .group by UserId ...然后对其进行子选择(CASE WHEN或顶部选择中的某些内容)。 无论如何 - 想知道是否有人对最佳方法有任何建议。最糟糕的情况我可以限制结果集并在内存中进行分组 - 但理想情况下希望直接从Mongo获得完整的答案。 另一个限制(即使在我超越第一组之后)是我希望按日期做一个独特的计数......这将更加艰难!
答案 0 :(得分:2)
现在 - 面临的挑战是:这些条目大约有20,000个。
在20,000时,使用聚合框架(http://docs.mongodb.org/manual/applications/aggregation/)可能会更好:
$db->user->aggregate(array(
array( '$group' => array( '_id' => '$userId', 'num_logins' => array( '$sum' => 1 ) ) )
));
这将按userId
分组(http://docs.mongodb.org/manual/reference/aggregation/#_S_group)并计算(总和:http://docs.mongodb.org/manual/reference/aggregation/sum/#_S_sum)分组登录的数量。
注意:如注释中所述,聚合帮助程序是PHP驱动程序的1.3+版本。在1.3版之前,您必须直接使用command
函数。
答案 1 :(得分:0)
您可以使用MapReduce按用户ID对结果进行分组
http://docs.mongodb.org/manual/applications/map-reduce/#map-reduce-examples
或者您可以使用Group方法:
db.logins.aggregate(
{ $group : {
_id : "$userId",
loginsPerUser : { $sum : 1 }
}}
);
对于MongoDB 20K甚至更多,走路和组合它们不会有问题,所以不用担心性能。
答案 2 :(得分:0)
http://docs.mongodb.org/manual/reference/command/group/
db.user.group({key: {userId: 1}, $reduce: function ( curr, result ) { result.total++ }, initial: {total: 0}});
我在几秒钟内就在191000行上运行了这个,但是组限制为20,000个唯一条目,所以它真的不适合你。