在对话中查找上一条消息

时间:2014-08-26 20:34:30

标签: node.js mongodb mongoose mongodb-query

我有2个架构:

var UserSchema   = new Schema({
    login: {type:String, unique: true, trim:true, index:true},
    password: String
)};

var MessageSchema   = new Schema({
    text: String,
    from_id: {type:mongoose.Schema.ObjectId, ref: 'user', index:true},
    to_id: {type:mongoose.Schema.ObjectId, ref: 'user', index:true},
    date: Number
});

现在举例来说,我在数据库中有4个用户。假设user1向每个其他用户发送了5条消息,user2和user3均回复了user1消息。现在我需要从每个对话框中只返回一条最近的消息。我怎么能这样做?

2 个答案:

答案 0 :(得分:1)

这样做的一个好方法是使用MongoDB的聚合框架。

我不是100%明确你的具体用例,但我认为使用$unwind将所有消息放在同一个地方,然后过滤{{1} }}如果您希望它仅显示最新的消息,则为$setUnion$sort

这是指向快速参考的链接:http://docs.mongodb.org/manual/meta/aggregation-quick-reference/

希望这有帮助,祝你好运!

答案 1 :(得分:1)

这里所做的一切都是mongo控制台,你必须自己翻译给你的司机

简单方法

如果您要查询特定会话,请在邮件中添加conversation_id(可能是用户名组合或只是随机字符串),然后您可以与

汇总
db.messages.aggregate({$sort:{date:-1}},
                      {$group:{_id:"$conversation_id", message:{$first:"$$ROOT"}})

或者只是将消息嵌入像David K这样的对话文档中。似乎已经认为你已经在做了什么。

"我想要这个工作"方式

我构建了一个可以满足您需求的聚合,但是在看到这个之后你可能想要用简单的方法(可能有人会想到更短的一个)。

首先在您的架构之后建模集合:

> db.chat.find().pretty()
{       "from" : 1,
        "to" : 2,
        "text" : "First from 1 to 2",
        "date" : 1}
{       "from" : 2,
        "to" : 1,
        "text" : "First answer from 2 to 1",
        "date" : 2}
{       "from" : 1,
        "to" : 2,
        "text" : "Second from 1 to 2",
        "date" : 3}
{       "from" : 1,
        "to" : 3,
        "text" : "First 1 to 3",
        "date" : 3}
{       "from" : 3,
        "to" : 1,
        "text" : "Reply 3 to 1",
        "date" : 4}

_id规定了可读性,当您看到两个对话时,用户12之间以及13之间的对话。

现在是聚合查询:

db.chat.aggregate({$project: {to:1,from:1,date:1,text:1,duplicator:{$const: [0,1]}}},
                  {$unwind:"$duplicator"},
                  {$group:{_id:"$_id",
                         parts:{$push:{$cond:[{$eq:"$duplicator",0]},"$from","$to"]}},
                         messages:{$addToSet: {text:"$text",date:"$date"}}}},
                  {$unwind:"$parts"},
                  {$sort:{parts:1}},
                  {$group:{_id:"$_id",
                           parts:{$push:"$parts"},
                           messages:{$first:"$messages"}}},
                  {$sort:{"messages.date":-1}},
                  {$group:{_id:"$parts", last_message:{$first:"$messages"}}})

输出:

{  "_id" : [1,2],
   "last_message" : [{ "text" : "Second from 1 to 2",
                       "date" : 3 }]
}
{  "_id" : [1,3],
        "last_message" : [{"text" : "Reply 3 to 1",
                           "date" : 4}]
}

最后两部分($sort$group)与简单方法相同。其余的是为参与者构建一个名为conversation_id的{​​{1}}。这是由

完成的
  • 添加新阵列parts
  • 展开该数组以获取每条消息的副本
  • 为每条消息在数组duplicator中推送tofromparts将使用conversation_id

上述步骤受到启发by this answer

  • 然后再展开parts
  • parts他们因为$sort
  • [1,2] != [2,1]他们再次成为一个数组

Tose步骤会产生一个会话ID,然后可以像上面两行aggreate中提出的那样使用它。

课程

根据你想要查询它的方式构建你的模式,因为用奇怪的聚合强奸mongodb只是有趣,直到它在自卫中踢你的球......


"你错误地提出了你的问题"

如果您只想要特定会话的最后一条消息,可以使用

$group