如何在mongoose中将embeded对象id转换为字符串?

时间:2016-02-17 14:45:02

标签: node.js mongodb mongoose

我的消息模型是

    owner: Object Id, ref User
    recipient: Object Id, ref User
    message: String
    read: boolean, default false,
    created: datetime

我需要在每个对话中获取最后的消息。我找到了一些有用的代码:

Message.aggregate(
    {$match:{$or:[{"owner":req.user._id},{"recipient":req.user._id}]}},
    {$sort:{created:-1}},
    {
        $group:{"_id":{
        "last_message_between":{
            $cond:[
                {
                    $gt:[
                    {$substr:["$recipient",0,1]},
                    {$substr:["$owner",0,1]}]
                },
                {$concat:["$recipient"," and ","$owner"]},
                {$concat:["$owner"," and ","$recipient"]}
            ]
        }
        },"message":{$first:"$$ROOT"}
        }
    },
    function(err, res)
    {
        if (err) return handleError(err);
        console.log(res);
        res.end();
    }
  )

但问题是我的refs是objectIds而不是字符串,所以上面的代码不起作用。我尝试使用toString转换refs但没有运气。如何将我的对象引用转换为字符串,以便我可以实现上述逻辑?或者有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

目前,您无法在聚合管道内将ObjectId转换为String。尽管如此,仍然可以使用聚合管道解决您的问题(并且不需要更改您的数据模式),但解决方案非常难看,而且肯定缺乏性能......

Ugly Aggregation

db.msg.aggregate([
    {$match: {
        $or: [
            {"owner": ObjectId("bbbbbbbbbbbbbbbbbbbbbbbb")},
            {"recipient": ObjectId("bbbbbbbbbbbbbbbbbbbbbbbb")}
        ]
    }},

    // the next section objective is to create a unique conversation identifier

    {$group:{
        _id :"$_id",
        message: {"$last": "$message"},
        created: {"$last": "$created"},
        ownerArr: {"$push": "$owner"},
        recipientArr: {"$push": "$recipient"},
    }},
    {$project:{
        _id: 1,
        message: 1,
        created: 1,
        conversationId: {"$setUnion": ["$ownerArr", "$recipientArr"]}
    }},
    {$unwind: "$conversationId"},
    {$sort: {"conversationId": 1}},
    {$group:{
        _id: "$_id",
        conversationId: {"$push": "$conversationId"},
        message: {"$last": "$message"},
        created: {"$last": "$created"}
    }},

    // end of conversationId section

    // the solution is now trivial

    {$sort: {"created": 1}},
    {$group:{
        _id: "$conversationId",
        lastMessageId: {"$last": "$_id"},
        lastMessage: {"$last": "$message"},
        lastCreated: {"$last": "$created"}
    }}
])

测试用例

> db.msg.find().toArray()
[
    {
        "_id" : ObjectId("56c4944645f0a14b5b3f5b9d"),
        "owner" : ObjectId("bbbbbbbbbbbbbbbbbbbbbbbb"),
        "recipient" : ObjectId("aaaaaaaaaaaaaaaaaaaaaaaa"),
        "message" : "qwerty",
        "created" : ISODate("2015-01-01T00:00:00Z")
    },
    {
        "_id" : ObjectId("56c4944a45f0a14b5b3f5b9e"),
        "owner" : ObjectId("aaaaaaaaaaaaaaaaaaaaaaaa"),
        "recipient" : ObjectId("bbbbbbbbbbbbbbbbbbbbbbbb"),
        "message" : "qwerty",
        "created" : ISODate("2016-01-01T00:00:00Z")
    },
    {
        "_id" : ObjectId("56c4944d45f0a14b5b3f5b9f"),
        "owner" : ObjectId("aaaaaaaaaaaaaaaaaaaaaaaa"),
        "recipient" : ObjectId("cccccccccccccccccccccccc"),
        "message" : "qwerty",
        "created" : ISODate("2016-01-01T00:00:00Z")
    },
    {
        "_id" : ObjectId("56c4945145f0a14b5b3f5ba0"),
        "owner" : ObjectId("bbbbbbbbbbbbbbbbbbbbbbbb"),
        "recipient" : ObjectId("aaaaaaaaaaaaaaaaaaaaaaaa"),
        "message" : "qwerty",
        "created" : ISODate("2014-01-01T00:00:00Z")
    },
    {
        "_id" : ObjectId("56c4945f45f0a14b5b3f5ba1"),
        "owner" : ObjectId("bbbbbbbbbbbbbbbbbbbbbbbb"),
        "recipient" : ObjectId("cccccccccccccccccccccccc"),
        "message" : "qwerty",
        "created" : ISODate("2014-01-01T00:00:00Z")
    }
]

结果

{ "_id" : [ ObjectId("aaaaaaaaaaaaaaaaaaaaaaaa"), ObjectId("bbbbbbbbbbbbbbbbbbbbbbbb") ], "lastMessageId" : ObjectId("56c4944a45f0a14b5b3f5b9e"), "lastMessage" : "qwerty", "lastCreated" : ISODate("2016-01-01T00:00:00Z") }
{ "_id" : [ ObjectId("bbbbbbbbbbbbbbbbbbbbbbbb"), ObjectId("cccccccccccccccccccccccc") ], "lastMessageId" : ObjectId("56c4945f45f0a14b5b3f5ba1"), "lastMessage" : "qwerty", "lastCreated" : ISODate("2014-01-01T00:00:00Z") }