我们有一个mongo集合messages,其格式如下:

/* 0 */
{
  "text" : "A message to John",
  "created" : ISODate("2015-01-29T23:50:10.488Z"),
  "to" : {
    "id" : ObjectId("54bf1dc6c65b030c00faec0d"),
    "name" : "John Smith"
  },
  "from" : {
    "id" : ObjectId("54bf1e1ceb5bf8800b0f5a8c"),
    "name" : "Martin Fowler"
  },
}
/* 1 */
{
  "text" : "Another message to John",
  "created" : ISODate("2015-01-30T00:37:38.106Z"),
  "to" : {
    "id" : ObjectId("54bf1dc6c65b030c00faec0d"),
    "name" : "John Smith"
  },
  "from" : {
    "id" : ObjectId("54bf1e1ceb5bf8800b0f5a8c"),
    "name" : "Martin fowler"
  },
}

/* 2 */
{
  "text" : "Just another message to Jerry",
  "created" : ISODate("2015-01-30T00:37:38.106Z"),
  "to" : {
    "id" : ObjectId("54bf1e80eb5bf8800b0f5a8d"),
    "name" : "Jerry Jones"
  },
  "from" : {
    "id" : ObjectId("54bf1e1ceb5bf8800b0f5a8c"),
    "name" : "Martin Fowler"
  },
}
/* 2 */
{
  "text" : "Message to Martin Fowler",
  "created" : ISODate("2015-01-30T00:37:38.106Z"),
  "to" : {
    "id" : ObjectId("54bf1e80eb5bf8800b0f5a8d"),
    "name" : "Martin Fowler"
  },
  "from" : {
    "id" : ObjectId("54bf1e1ceb5bf8800b0f5a8c"),
    "name" : "Jerry Jones"
  },
}


我们需要以对话格式显示上面的数据,然后将每个对话分组在一起。对话意味着它可以是tofrom

我们需要的数据示例如下所示:

{
   "result":[
      {
         "id":"54bf1dc6c65b030c00faec0d",
         "name":"Jerry Jones",
         "messages":[
            {
              "text" : "A message to John",
              "created" : ISODate("2015-01-29T23:50:10.488Z"),
              "to" : {
                "id" : ObjectId("54bf1dc6c65b030c00faec0d"),
                "name" : "John Smith"
              },
              "from" : {
                "id" : ObjectId("54bf1e1ceb5bf8800b0f5a8c"),
                "name" : "Martin Fowler"
              },
            }
            {
              "text" : "Another message to John",
              "created" : ISODate("2015-01-30T00:37:38.106Z"),
              "to" : {
                "id" : ObjectId("54bf1dc6c65b030c00faec0d"),
                "name" : "John Smith"
              },
              "from" : {
                "id" : ObjectId("54bf1e1ceb5bf8800b0f5a8c"),
                "name" : "Martin fowler"
              },
            }
         ]
      },
      {
         "id":"54bf1e80eb5bf8800b0f5a8d",
         "name":"John Smith",
         "messages":[
            {
              "text" : "Just another message to Jerry",
              "created" : ISODate("2015-01-30T00:37:38.106Z"),
              "to" : {
                "id" : ObjectId("54bf1e80eb5bf8800b0f5a8d"),
                "name" : "Jerry Jones"
              },
              "from" : {
                "id" : ObjectId("54bf1e1ceb5bf8800b0f5a8c"),
                "name" : "Martin Fowler"
              },
            }
            {
              "text" : "Message to Martin Fowler",
              "created" : ISODate("2015-01-30T00:37:38.106Z"),
              "to" : {
                "id" : ObjectId("54bf1e80eb5bf8800b0f5a8d"),
                "name" : "Martin Fowler"
              },
              "from" : {
                "id" : ObjectId("54bf1e1ceb5bf8800b0f5a8c"),
                "name" : "Jerry Jones"
              },
            }
         ]
      }
   ]
}


注意此查询总是在current user的上下文中进行的,这就是为什么在每个对话中,我们都有一个_idname代表对话中的另一个用户的原因。对于上面的示例,current user将为Martin Fowler

我们尝试了几种不同的方法来实现此目的,但是仍然遇到问题。我宁愿转向Mongo / Node社区,以了解如何正确完成它。如果有帮助的话,我们将mongoose与Node一起使用...

我们当前拥有的初始查询实现如下:

Message.find().or([{'from.id':req.user.id},{'to.id':req.user.id}]).exec(function(err,messages){

    //NEED TO IMPLEMENT THIS HERE CORRECTLY
});


注意req.user.idcurrent user的ID

最佳答案

此解决方案是对类似问题here的先前解决方案的略微修改。

在不一致的情况下,有争议的文件具有成员名称。在整个应用程序/数据库中,Martin Folwer应该是Martin Fowler,而不是Martin fowler。 (请注意小f)。您需要对文档进行此更改。


基于$groupto字段的from消息在一起。
构造一个组密钥-“ message_between”,其值为
tofrom字段中的值的$concat结果。
邮件从Martin FowlerJerry JonesJerry Jones
Martin Fowler应该放在一个小组中
这样,我们使结果包含最后一个名称
首先,按字母顺序。因此,对于从MartinFowlerJerry Jones以及Jerry JonesMartin Fowler的所有消息,我们的密钥是
Martin Fowler and Jerry Jones


码:

Model.aggregate(
//match all those records which involve the user.
{$match:{$or:[{"to.name":req.user.id},
              {"from.name":req.user.id}]}},
{$group:{"_id":{
    "message_between":{
        $cond:[
            {
                $gt:[
                {$substr:["$to.name",0,1]},
                {$substr:["$from.name",0,1]}]
            },
            {$concat:["$to.name"," and ","$from.name"]},
            {$concat:["$from.name"," and ","$to.name"]}
        ]
    },"name":{$cond:[{$eq:["$to.name",
                           req.user.id]},
                     "$from.name",
                     "$to.name"]}
    },"messages":{$push:"$$ROOT"}
    }
},
{$project:{"_id":0,"name":"$_id.name","messages":1}}
,function(err,resp){
   // handle response.
})


o / p:

{
        "messages" : [
                {
                        "_id" : ObjectId("54d1d819b62f332e93fbb906"),
                        "text" : "Just another message to Jerry",
                        "created" : ISODate("2015-01-30T00:37:38.106Z"),
                        "to" : {
                                "id" : ObjectId("54bf1e80eb5bf8800b0f5a8d"),
                                "name" : "Jerry Jones"
                        },
                        "from" : {
                                "id" : ObjectId("54bf1e1ceb5bf8800b0f5a8c"),
                                "name" : "Martin Fowler"
                        }
                },
                {
                        "_id" : ObjectId("54d1d819b62f332e93fbb907"),
                        "text" : "Message to Martin Fowler",
                        "created" : ISODate("2015-01-30T00:37:38.106Z"),
                        "to" : {
                                "id" : ObjectId("54bf1e80eb5bf8800b0f5a8d"),
                                "name" : "Martin Fowler"
                        },
                        "from" : {
                                "id" : ObjectId("54bf1e1ceb5bf8800b0f5a8c"),
                                "name" : "Jerry Jones"
                        }
                }
        ],
        "name" : "Jerry Jones"
}
{
        "messages" : [
                {
                        "_id" : ObjectId("54d1d819b62f332e93fbb904"),
                        "text" : "A message to John",
                        "created" : ISODate("2015-01-29T23:50:10.488Z"),
                        "to" : {
                                "id" : ObjectId("54bf1dc6c65b030c00faec0d"),
                                "name" : "John Smith"
                        },
                        "from" : {
                                "id" : ObjectId("54bf1e1ceb5bf8800b0f5a8c"),
                                "name" : "Martin Fowler"
                        }
                },
                {
                        "_id" : ObjectId("54d1d819b62f332e93fbb905"),
                        "text" : "Another message to John",
                        "created" : ISODate("2015-01-30T00:37:38.106Z"),
                        "to" : {
                                "id" : ObjectId("54bf1dc6c65b030c00faec0d"),
                                "name" : "John Smith"
                        },
                        "from" : {
                                "id" : ObjectId("54bf1e1ceb5bf8800b0f5a8c"),
                                "name" : "Martin Fowler"
                        }
                }
        ],
        "name" : "John Smith"
}

07-24 21:53