在MongoDB中列出涉及用户的每个对话的最后一条消息

jim*_*ood 5 mongoose mongodb node.js

让我说我有一个mongo数据库的消息,如下所示:

{
  "_id": ObjectId("5458009c1ab2354c029d7178"),
  "to": "dan",
  "from": "wood",
  "message": "hi dan how are you?",
  "time": new Date(1415053468590),
  "__v": 0
}
{
  "_id": ObjectId("545800b45eaf364d026c1cba"),
  "to": "wood",
  "from": "dan",
  "message": "hi wood how are you?",
  "time": new Date(1415053492125),
  "__v": 0
}
{
  "_id": ObjectId("5458009c1ab2354c029d7178"),
  "to": "billy",
  "from": "wood",
  "message": "hi billy how are you?",
  "time": new Date(1415053468590),
  "__v": 0
}
{
  "_id": ObjectId("545800b45eaf364d026c1cba"),
  "to": "wood",
  "from": "billy",
  "message": "hi wood how are you?",
  "time": new Date(1415053492125),
  "__v": 0
}
Run Code Online (Sandbox Code Playgroud)

那么如何从用户"木材"可能具有的每个对话中检索最后一条消息?

其他人已经发布了一个关于如何在mysql中执行此操作的类似问题.我问如何在猫鼬中做到这一点.

我将发布它作为参考,它有助于: 私人消息系统.列出每个对话的最后一条消息

如果你可以帮助我,那会很棒.谢谢您的帮助.对此,我真的非常感激.我是mongoose,mongodb和node.js的新手.我来自php mysql背景.

如果您可以发布实际的代码以便我可以尝试并提供反馈,那将会很棒.谢谢.

我的数据库架构如下所示:

var messageSchema = new Schema({
to: { type: String, required: true},
from: { type: String, required: true},
message: { type: String, required: true},
time : { type : Date, default: Date.now }
});
Run Code Online (Sandbox Code Playgroud)

什么样的人运行这个网站的证据:http: //i62.tinypic.com/bbntx.jpg

离开这个网站,你可以告诉你这个网站运行的是什么样的不友好的人.我可能会问其他地方.他们实际上并不关心帮助你.他们关心他们的规则.你是一个不欢迎你的新人.我欢迎任何其他地方不像人们在这里做的那样被污染.

Bat*_*eam 7

欢迎来到堆栈溢出.你发布了一个不错的问题.请让我尽我所能帮助你.

这是一个聚合命令,可以在mongo shell中运行.请在内容中找到解释.

db.collection.aggregate([
//match all those records which involve Wood.
{$match:{$or:[{"to":"wood"},{"from":"wood"}]}},
// sort all the messages by descending order
{$sort:{time:-1}},
{
    // Now we need to group messages together, based on the to and from field.
    // We generate a key - "last_message_between", with the value being a concatenation
    // result of the values in to and from field.
    // Now, Messages from Wood to billy and Billy to wood should be treated under a single group right.
    // To achieve that, we do a small trick to make the result contain the name coming last
    // alphabetically, first. So our key for all the Messages from Wood to Billy and Billy to Wood would be 
    // "Wood and Billy".
    // And then we just display the first document that appears in the group, that would be the 
    // latest Message.
    $group:{"_id":{
    "last_message_between":{
        $cond:[
            {
                $gt:[
                {$substr:["$to",0,1]},
                {$substr:["$from",0,1]}]
            },
            {$concat:["$to"," and ","$from"]},
            {$concat:["$from"," and ","$to"]}
        ]
    }
    },"message":{$first:"$$ROOT"}
    }
}
])
Run Code Online (Sandbox Code Playgroud)

您可以在mongoose上运行以下内容.

Collection.aggregate(
{$match:{$or:[{"to":"wood"},{"from":"wood"}]}},
{$sort:{time:-1}},
{
    $group:{"_id":{
    "last_message_between":{
        $cond:[
            {
                $gt:[
                {$substr:["$to",0,1]},
                {$substr:["$from",0,1]}]
            },
            {$concat:["$to"," and ","$from"]},
            {$concat:["$from"," and ","$to"]}
        ]
    }
    },"message":{$first:"$$ROOT"}
    }
},
function(err, res)
{
    if (err) return handleError(err);
    console.log(res);
}
)
Run Code Online (Sandbox Code Playgroud)