我有一个集合objects
。
{
"_id" : ObjectId("55fa65046db58e7d0c8b456a"),
"object_id" : "1651419",
"user" : {
"id" : "65593",
"cookie" : "9jgkm7ME1HDFD4K6j8WWvg",
},
"createddate" : ISODate("2015-09-17T10:00:20.945+03:00")
}
每次用户访问对象的页面时,它都会作为单独的记录存储在集合中。现在我需要获取最后N 访问对象的数组。它应该是 distinct ,因此数组应该有N个唯一记录。此外,它应按createddate
排序。
因此,如果用户访问了object_id = 1
,那么object_id = 2
两次,之后访问object_id = 3
并再次访问object_id = 1
,数组应该包含:
{
visits : [1, 3, 2]
}
(与上次访问的时间不同并分类。)
我尝试使用像
这样的结构db.objects.aggregate([
{$match: {'user.id' : '65593'}},
{$sort: { 'createddate':-1 }},
{$project: {'id': '$user.id', 'obj' : '$object_id'}},
{$group: {_id:'$id', 'obj': {$addToSet: '$obj'}}},
{$project:{_id:0, 'obj':'$obj'}}
])
但它会返回未排序的数组,而且我也无法限制数组大小。
答案 0 :(得分:3)
MongoDB的$addToSet
运算符和“集合”通常不以任何方式排序。 Insead,先通过分组获取“不同”值,然后在排序后应用于数组:
db.objects.aggregate([
{ "$match": { "user.id": "65593" } },
{ "$sort": { "user.id": 1, "createddate": -1 } },
{ "$group": {
"_id": {
"_id": "$user.id",
"object_id": "$object_id"
},
"createddate": { "$first": "$createddate" }
}},
{ "$sort": { "_id._id": 1, "createddate": -1 } },
{ "$group": {
"_id": "$_id._id",
"obj": { "$push": "$_id.object_id" }
}}
])
因此,如果您希望在$sort
之前按日期发现oder,但由于$group
不保证任何结果顺序,因此在您与{{{{}}分组之前,您需要再次$sort
3}}构建数组的操作。
请注意,您可能会以某种方式减少“createddate”,因为一般的“distinct”项似乎是“user.id”和“object_id”字段,所以这确实需要某种累加器并且需要包含在您的订购中。
然后数组项将按照您期望的顺序。
如果您需要$limit
,则必须处理$unwind
并将结果分开限制。在第一组之后交替处理“限制”并在此处进行排序。
但是当然这对于单个主要分组_id
来说是唯一可行的,即“user.id”。未来的mongodb版本将支持$slice
,这将使多个分组ID更加实用,并且通常会更简单。但是仍然不可能在初始组之前“限制”多个主要groupind id的数组项。
答案 1 :(得分:0)
我找到了我期望的解决方案。
db.objects.aggregate([
{$match: {'user.id' : '65593'}},
{$group : {
_id : '$object_id',
dt : {$max: '$createddate'}
}
},
{$sort: {'dt':-1}},
{$limit:5},
{$group : {
_id :null,
'objects' : {$push:'$_id'}
}
},
{$project: {_id:0, 'objects':'$objects'}}
])
它返回限制为由createddate
向后排序的N个不同数组。
感谢大家的帮助!