我使用的是MongoDB,我希望对组内的记录进行排序和跳过。
以下是示例数据:
{
"_id" : ObjectId("51cd7274267d959cb9f95cea"),
"creation_time" : 100,
"delivered" : true,
"id" : 1,
"user_id" : 10
}
现在我想要的是每个用户(_id
)的所有文档的user_id
,其中没有。用户的文档大于4.在跳过这4个文档后,我还想要_id
个文档。因此,如果用户有6个文档,那么我想要最后2个文档的_id
(按creation_time排序),以便我可以将这2个旧文档存档到另一个数据库。
我使用以下查询:
db.newsdb.aggregate([
{
$match: {
delivered: true
}
},
{
$group: {
_id: {
user_id: "$user_id",
creation_time: "$creation_time"
}
}
}
])
现在问题是我想对每个用户的文档执行$sort
和$skip
操作,而不是对所有用户的文档执行操作。所以我想要这样的东西:
{
$group: {
_id: {
user_id: "$user_id",
creation_time: "$creation_time"
}
},
$sort: {
user_id:1,
creation_time:1
},
$skip: 4
}
但似乎mongo db不支持它。我收到以下错误:
Error: Printing Stack Trace
at printStackTrace (src/mongo/shell/utils.js:37:7)
at DBCollection.aggregate (src/mongo/shell/collection.js:897:1)
at (shell):1:11
Mon Jul 1 14:47:55.762 JavaScript execution failed: aggregate failed: {
"errmsg" : "exception: A pipeline stage specification object must contain exactly one field.",
"code" : 16435,
"ok" : 0
} at src/mongo/shell/collection.js:L898
答案 0 :(得分:0)
目前在聚合框架中无法做到这一点。
您需要为每个用户单独进行查询。您可以做的最好的事情是循环遍历所有执行查询的用户,以便为您提供不是前4名的文档:
[user list].forEach(function(u) {
var listToArchive = db.newsdb.find({user_id: u},{_id:1}).sort({creation_time:-1}).skip(4);
/* do what you need to with listToArchive _id's */
} )
答案 1 :(得分:0)
在思考太多之后,我想出了一个使用map-reduce的解决方案,因为使用聚合框架似乎是不可能的。
这是reduce函数,即user_id
的简单组文档。
var mapf = function () {
emit(this.user_id, {
_id: this._id,
creation_time: this.creation_time
})
}
在减少功能时,我检查是否至少有四个条目。如果为true,则values
数组按creation_time
排序,并跳过前4个文档。
var redf = function (key, values) {
var result = {};
if (values.length > 4) {
values.sort(function (a, b) {
return a.creation_time > b.creation_time;
});
// unfortunately, mongodb doesn't support array as result of reduce function
result['oids'] = values.slice(3);
}
return result;
}
现在是时候运行map-reduce命令了。结果将插入plus_four_users
集合。
db.newsdb.mapReduce(mapf, redf, { out : "plus_four_users" })
这将产生类似的结果:
> db.newsdb.find({}, { user_id : 1, creation_time : 1 })
{ "_id" : ObjectId("51d612423dab6225ca6e6d36"), "creation_time" : 100, "user_id" : 10 }
{ "_id" : ObjectId("51d612503dab6225ca6e6d37"), "creation_time" : 200, "user_id" : 10 }
{ "_id" : ObjectId("51d612553dab6225ca6e6d38"), "creation_time" : 300, "user_id" : 10 }
{ "_id" : ObjectId("51d612593dab6225ca6e6d39"), "creation_time" : 400, "user_id" : 10 }
{ "_id" : ObjectId("51d6125d3dab6225ca6e6d3a"), "creation_time" : 500, "user_id" : 10 }
{ "_id" : ObjectId("51d6126f55ebf2ff5a13d1c9"), "creation_time" : 600, "user_id" : 10 }
{ "_id" : ObjectId("51d6127455ebf2ff5a13d1ca"), "creation_time" : 300, "user_id" : 11 }
{ "_id" : ObjectId("51d6127955ebf2ff5a13d1cb"), "creation_time" : 400, "user_id" : 11 }
{ "_id" : ObjectId("51d6127c55ebf2ff5a13d1cc"), "creation_time" : 500, "user_id" : 11 }
{ "_id" : ObjectId("51d6127f55ebf2ff5a13d1cd"), "creation_time" : 600, "user_id" : 11 }
{ "_id" : ObjectId("51d6128555ebf2ff5a13d1ce"), "creation_time" : 700, "user_id" : 11 }
> db.plus_four_users.find().pretty()
{
"_id": 10,
"value": {
"oids": [
{
"_id": ObjectId("51d6125d3dab6225ca6e6d3a"),
"creation_time": 500
},
{
"_id": ObjectId("51d6126f55ebf2ff5a13d1c9"),
"creation_time": 600
}
]
}
}
{
"_id": 11,
"value": {
"oids": [
{
"_id": ObjectId("51d6128555ebf2ff5a13d1ce"),
"creation_time": 700
}
]
}
}
希望能帮到你!