Mongodb 获取聚合框架中的最后一个组合
Mongodb get last combination in aggregation framework
有一组消息:
{
"date": NumberLong(1421134514),
"sender": "53172480f9cd0e682840b9f7",
"recipient": "52f37fbaf9cd0e02773c97b1",
"isRead": false,
"_id": "54b4cab2f6a48ce34f8b5a75",
"text": "Hello!"
},
{
"date": NumberLong(1421135561),
"sender": "53172480f9cd0e682840b9f7",
"recipient": "52f37fbaf9cd0e02773c97b1",
"isRead": false,
"_id": "54b4cec9f6a48ce34f8b6429",
"text": "Hello 2!"
},
{
"date": NumberLong(1421135618),
"sender": "53072122f9cd0ee76306dc5a",
"recipient": "52f37fbaf9cd0e02773c97b1",
"isRead": false,
"_id": "54b4cf02f6a48ce54f8b62f9",
"text": "Hello 3!"
},
{
"date": NumberLong(1421136457),
"sender": "52f37fbaf9cd0e02773c97b1",
"recipient": "52ea178ff9cd0e9f24d776b4",
"isRead": false,
"_id": "54b4d249f6a48ce54f8b6b9f"
"text": "Hello 4!"
}
需要选择后面的对话,当前用户要么是发送者,要么是接收者。
例如,对于 ID = '52f37fbaf9cd0e02773c97b1' 的用户,应获得 3 条记录。
原来构建了两个单独的查询:
$result = \DB::$connection->message->aggregate(array(
array('$match' => array('sender' => \Core::getModule('users')->user->_id)),
array('$group' => array('_id' => '$recipient')),
));
$result2 = \DB::$connection->message->aggregate(array(
array('$match' => array('recipient' => \Core::getModule('users')->user->_id)),
array('$group' => array('_id' => '$sender')),
));
是否可以以某种方式将这两个查询合并为一个并按日期对记录进行排序?
这里您需要的是为 "sender and recipient" 的每个组合生成的 "unique key" 值。如果您想定期执行此操作,那么我建议将值存储在文档中。但这是您可以使用聚合框架摆脱问题的一种方式:
db.messages.aggregate([
{ "$project": {
"combined": { "$map": {
"input": { "$literal": ["A","B"] },
"as": "bin",
"in": { "$cond": [
{ "$eq": [ "$$bin", "A" ] },
"$sender",
"$recipient"
]}
}},
"doc": "$$ROOT"
}},
{ "$unwind": "$combined" },
{ "$sort": { "_id": 1, "combined": 1, "doc.date": -1 } },
{ "$group": {
"_id": "$_id",
"combined": { "$push": "$combined" },
"doc": { "$first": "$doc" }
}},
{ "$group": {
"_id": "$combined",
"doc": { "$first": "$doc" }
}}
])
这将您的示例缩小到 "unique" 3 种组合 "sender / recipient" 和 returns "pair" 之间对话的最后一个文档:
{
"_id" : [
"52f37fbaf9cd0e02773c97b1",
"53172480f9cd0e682840b9f7"
],
"doc" : {
"_id" : "54b4cec9f6a48ce34f8b6429",
"date" : NumberLong(1421135561),
"sender" : "53172480f9cd0e682840b9f7",
"recipient" : "52f37fbaf9cd0e02773c97b1",
"isRead" : false,
"text" : "Hello 2!"
}
}
{
"_id" : [
"52f37fbaf9cd0e02773c97b1",
"53072122f9cd0ee76306dc5a"
],
"doc" : {
"_id" : "54b4cf02f6a48ce54f8b62f9",
"date" : NumberLong(1421135618),
"sender" : "53072122f9cd0ee76306dc5a",
"recipient" : "52f37fbaf9cd0e02773c97b1",
"isRead" : false,
"text" : "Hello 3!"
}
}
{
"_id" : [
"52ea178ff9cd0e9f24d776b4",
"52f37fbaf9cd0e02773c97b1"
],
"doc" : {
"_id" : "54b4d249f6a48ce54f8b6b9f",
"date" : NumberLong(1421136457),
"sender" : "52f37fbaf9cd0e02773c97b1",
"recipient" : "52ea178ff9cd0e9f24d776b4",
"isRead" : false,
"text" : "Hello 4!"
}
}
有一组消息:
{
"date": NumberLong(1421134514),
"sender": "53172480f9cd0e682840b9f7",
"recipient": "52f37fbaf9cd0e02773c97b1",
"isRead": false,
"_id": "54b4cab2f6a48ce34f8b5a75",
"text": "Hello!"
},
{
"date": NumberLong(1421135561),
"sender": "53172480f9cd0e682840b9f7",
"recipient": "52f37fbaf9cd0e02773c97b1",
"isRead": false,
"_id": "54b4cec9f6a48ce34f8b6429",
"text": "Hello 2!"
},
{
"date": NumberLong(1421135618),
"sender": "53072122f9cd0ee76306dc5a",
"recipient": "52f37fbaf9cd0e02773c97b1",
"isRead": false,
"_id": "54b4cf02f6a48ce54f8b62f9",
"text": "Hello 3!"
},
{
"date": NumberLong(1421136457),
"sender": "52f37fbaf9cd0e02773c97b1",
"recipient": "52ea178ff9cd0e9f24d776b4",
"isRead": false,
"_id": "54b4d249f6a48ce54f8b6b9f"
"text": "Hello 4!"
}
需要选择后面的对话,当前用户要么是发送者,要么是接收者。
例如,对于 ID = '52f37fbaf9cd0e02773c97b1' 的用户,应获得 3 条记录。
原来构建了两个单独的查询:
$result = \DB::$connection->message->aggregate(array(
array('$match' => array('sender' => \Core::getModule('users')->user->_id)),
array('$group' => array('_id' => '$recipient')),
));
$result2 = \DB::$connection->message->aggregate(array(
array('$match' => array('recipient' => \Core::getModule('users')->user->_id)),
array('$group' => array('_id' => '$sender')),
));
是否可以以某种方式将这两个查询合并为一个并按日期对记录进行排序?
这里您需要的是为 "sender and recipient" 的每个组合生成的 "unique key" 值。如果您想定期执行此操作,那么我建议将值存储在文档中。但这是您可以使用聚合框架摆脱问题的一种方式:
db.messages.aggregate([
{ "$project": {
"combined": { "$map": {
"input": { "$literal": ["A","B"] },
"as": "bin",
"in": { "$cond": [
{ "$eq": [ "$$bin", "A" ] },
"$sender",
"$recipient"
]}
}},
"doc": "$$ROOT"
}},
{ "$unwind": "$combined" },
{ "$sort": { "_id": 1, "combined": 1, "doc.date": -1 } },
{ "$group": {
"_id": "$_id",
"combined": { "$push": "$combined" },
"doc": { "$first": "$doc" }
}},
{ "$group": {
"_id": "$combined",
"doc": { "$first": "$doc" }
}}
])
这将您的示例缩小到 "unique" 3 种组合 "sender / recipient" 和 returns "pair" 之间对话的最后一个文档:
{
"_id" : [
"52f37fbaf9cd0e02773c97b1",
"53172480f9cd0e682840b9f7"
],
"doc" : {
"_id" : "54b4cec9f6a48ce34f8b6429",
"date" : NumberLong(1421135561),
"sender" : "53172480f9cd0e682840b9f7",
"recipient" : "52f37fbaf9cd0e02773c97b1",
"isRead" : false,
"text" : "Hello 2!"
}
}
{
"_id" : [
"52f37fbaf9cd0e02773c97b1",
"53072122f9cd0ee76306dc5a"
],
"doc" : {
"_id" : "54b4cf02f6a48ce54f8b62f9",
"date" : NumberLong(1421135618),
"sender" : "53072122f9cd0ee76306dc5a",
"recipient" : "52f37fbaf9cd0e02773c97b1",
"isRead" : false,
"text" : "Hello 3!"
}
}
{
"_id" : [
"52ea178ff9cd0e9f24d776b4",
"52f37fbaf9cd0e02773c97b1"
],
"doc" : {
"_id" : "54b4d249f6a48ce54f8b6b9f",
"date" : NumberLong(1421136457),
"sender" : "52f37fbaf9cd0e02773c97b1",
"recipient" : "52ea178ff9cd0e9f24d776b4",
"isRead" : false,
"text" : "Hello 4!"
}
}