Mongo 查询和响应 'GroupBy' 使用 Mongoose and/or underscore.js 实现

Mongo query and response 'GroupBy' implementation using Mongoose and/or underscore.js

我们有一个 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 的上下文中进行,这就是为什么在每个对话中,我们都有一个 _id 和一个name 代表对话中的其他用户。对于上面的示例,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

我试图为您创建一个 mongo 请求,但我不确定它是否相关... 我可以在一个请求中生成几乎与您需要的格式完全相同的格式:

db.messages.aggregate([{$match:{$or:[{"from.id":ObjectId("54bf1dc6c65b030c00faec0d")},{"to.id":ObjectId("54bf1dc6c65b030c00faec0d")}]}},{$group:{_id: ObjectId("54bf1dc6c65b030c00faec0d"), messages:{$push: "$$ROOT"}}}]);

问题是,你还需要指定id,我不确定这是你需要的。

使用这个我得到以下结果:

{
    "_id": ObjectId("54bf1dc6c65b030c00faec0d"),
    "messages": [
        {
            "_id": ObjectId("54d1b9f02cd45cae7e453633"),
            "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("54d1ba052cd45cae7e453634"),
            "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"
            }
        }
    ]
}

我没有使用 mongoose 所以这部分我帮不了你,但是有了 "mongodb" 模块,这个查询可以直接使用,所以应该可以用 mongo也是。

这个解决方案是对我之前对类似问题的解决方案的轻微修改 here

有问题的文档中的成员名称大小写不一致。 Martin Folwer 在整个 app/database 中应该是 Martin Fowler,而不是 Martin fowler。 (注意小 f)。您需要对您的文档进行此更改。

  • $group 消息,基于 tofrom 字段。 构造一个组键 - "message_between",值为 a $concat tofrom 字段中值的结果。

  • Martin FowlerJerry JonesJerry JonesMartin Fowler应该是下单group.To实现 那,我们让结果包含最后一个名字 按字母顺序,第一。因此,我们从 Martin FowlerJerry JonesJerry 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"
}