我有以下邮件集合:
{
"_id" : ObjectId("56214d5632001bae07a6e6b3"),
"sender_id" : 8,
"receiver_id" : 2,
"content" : "fdgfd",
"state" : 1,
"timestamp" : 1445023062899.0000000000000000
},
{
"_id" : ObjectId("56214d5c32001bae07a6e6b4"),
"sender_id" : 2,
"receiver_id" : 8,
"content" : "fasfa",
"state" : 1,
"timestamp" : 1445023068443.0000000000000000
},
{
"_id" : ObjectId("56214d8032001bae07a6e6b5"),
"sender_id" : 2,
"receiver_id" : 8,
"content" : "dfdsfds",
"state" : 1,
"timestamp" : 1445023104363.0000000000000000
},
{
"_id" : ObjectId("56214d8032001bae07a6e6b6"),
"sender_id" : 2,
"receiver_id" : 8,
"content" : "fdsf",
"state" : 1,
"timestamp" : 1445023104825.0000000000000000
},
{
"_id" : ObjectId("56214d8132001bae07a6e6b7"),
"sender_id" : 2,
"receiver_id" : 8,
"content" : "sfsdfs",
"state" : 1,
"timestamp" : 1445023105436.0000000000000000
},
{
"_id" : ObjectId("56214d8132001bae07a6e6b8"),
"sender_id" : 2,
"receiver_id" : 8,
"content" : "f",
"state" : 1,
"timestamp" : 1445023105963.0000000000000000
},
{
"_id" : ObjectId("56214d8432001bae07a6e6b9"),
"sender_id" : 2,
"receiver_id" : 8,
"content" : "qwqwqwq",
"state" : 1,
"timestamp" : 1445023108202.0000000000000000
},
{
"_id" : ObjectId("56214db032001bae07a6e6ba"),
"sender_id" : 9902,
"receiver_id" : 2,
"content" : "fsafa",
"state" : 1,
"timestamp" : 1445023152297.0000000000000000
}
我试图获取与用户2一起发送消息的所有唯一用户ID以及最后一条内容消息。所以结果应该是:
[ { user: 8, lastContent: "qwqwqwq" }, { user: 9902, lastContent: "fsafa" } ]
到目前为止,我有以下代码:
db.getCollection('messenger').group({
keyf: function(doc) {
return { user: doc.user };
},
cond: {
$or : [
{ sender_id : 2 },
{ receiver_id : 2 }
]
},
reduce: function( curr, result ) {
result.user = (curr.sender_id == 2 ? curr.receiver_id : curr.sender_id);
result.content = curr.content;
},
initial: { } })
但我只得到最后一个身份证。结果:
{
"0" : {
"user" : 9902.0000000000000000,
"content" : "fsafa"
} }
任何人都可以帮我吗?
答案 0 :(得分:1)
您需要使用.aggregate()
方法。您需要使用$match
运算符减少管道中文档的大小,该运算符会过滤掉receiver_id
不等于2
的所有文档。之后,您需要timestamp
按content
降序排列$sort
,这有助于我们获取最后一条消息的sender_id
。现在是$group
阶段,您可以在其中对文档进行分组,并使用$addToSet
运算符返回不同的receiver_id
和不同的user_ids
数组以及$last
运算符最后的消息内容。现在要获得sender_id
,我们需要使用$project
运算符在$setUnion
离子之后得到的receiver_id
和db.messenger.aggregate([
{ "$match": {
"$or": [
{ "sender_id": 2 },
{ "receiver_id": 2 }
]
}},
{ "$sort": { "timestamp": 1 } },
{ "$group": {
"_id": null,
"receiver_id": {
"$addToSet": { "$receiver_id" }
},
"sender_id": {
"$addToSet": { "$sender_id" }
},
"lastContent": { "$last": "$content" }
}},
{ "$project": {
"_id": 0,
"lastContent": 1,
"user_ids": {
"$setUnion": [
"$sender_id",
"$receiver_id"
]
}
}}
])
不同的联合。
{ "lastContent" : "fsafa", "user_ids" : [ 9902, 2, 8 ] }
返回:
2
现在,如果你想要的是与用户db.messenger.aggregate([
{ "$match": {
"$or": [
{ "sender_id": 2 },
{ "receiver_id": 2 }
]
}},
{ "$sort": { "timestamp": 1 } },
{ "$group": {
"_id": {
"sender": "$sender_id",
"receiver": "$receiver_id"
},
"lastContent": {
"$last": "$content"
},
"timestamp": { "$last": "$timestamp" },
"sender": { "$addToSet": "$sender_id" },
"receiver": { "$addToSet": "$receiver_id" }
}},
{ "$project": {
"_id": 0,
"user": {
"$setDifference": [
{ "$setUnion": [ "$sender", "$receiver" ] },
[ 2 ]
]
},
"lastContent": 1,
"timestamp": 1
}},
{ "$unwind": "$user" },
{ "$sort": { "timestamp": 1 } },
{ "$group": {
"_id": "$user",
"lastContent": { "$last": "$lastContent" }
} }
])
的最后一条内容消息不同的用户,那么它就是:
{ "_id" : 9902, "lastContent" : "fsafa" }
{ "_id" : 8, "lastContent" : "qwqwqwq" }
哪个收益率:
/*
* Creates the method Collection.reduce(Object, Closure).
* Unlike Collection.inject(Object, Closure), this method
* expects a closure with a single argument: the
* current element in the collection. The closure is
* re-created to run with the accumulated value as the
* owner and then called with the current element as the argument.
*/
Collection.metaClass.reduce = { Object initial, Closure closure ->
delegate.inject(initial) { acc, obj ->
closure.rehydrate(acc, acc, acc)(obj)
}
}
def nums = [1, 2, 3]
/*
* Number.&multiply returns the Number.multiply(Number) method
* as a Closure.
*/
def result = nums.reduce(1, Number.&multiply)
assert result == 6