修改猫鼬响应数据

时间:2016-01-28 08:32:22

标签: node.js mongodb mongoose

我有一个API调用,它返回用户已收到JSON的所有消息。

模型数据如下所示:

{
    sender: ObjectId,
    reciever: ObjectId,
    message: String
}

修改API响应的JSON的正确方法是什么?

我想最终得到如此分组的数据:

{
    <senderid>:[ all of the messages from this sender],
    <other_sender>:[ all of the messages from this sender]
}

我是否必须在javascript中手动执行此操作,或者是否有更快的方法来利用mongoose?

1 个答案:

答案 0 :(得分:1)

使用聚合框架将是此任务的理想选择。您可以运行以下聚合管道,该管道使用 $group 运算符步骤对数据进行分组以处理它们。组管道运算符类似于SQL的GROUP BY子句。在SQL中,除非使用任何聚合函数,否则不能使用GROUP BY。同样,您也必须在MongoDB中使用聚合函数。在这种情况下,使用 $push 累加器运算符来创建消息数组。

由于 Model.aggregate() 会返回普通对象,因此您可以使用lodash库的 _.indexBy() 方法将生成的数组转换为所需的哈希键:

var pipeline = [
    {
        "$group": {
            "_id": "$sender",
            "messages": { "$push": "$message" }
        }
    }
];

Model.aggregate(pipeline,
    function(err, res) {
        if (err) return handleError(err);
        var hashmap = _.chain(res)
               .indexBy('_id')                 
               .mapValues('messages')                  
               .value();
        console.log(JSON.stringify(hashmap, undefined, 4));
    }
);

// Or use the aggregation pipeline builder.
Model.aggregate()
     .group({ "_id": "$sender", "messages": { "$push": "$message" } })
     .exec(function (err, res) {
        if (err) return handleError(err);
        var hashmap = _.chain(res)
               .indexBy('_id')                 
               .mapValues('messages')                  
               .value();
        console.log(JSON.stringify(hashmap, undefined, 4));
});

查看下面的演示。

var data = [
	{ _id: 'user1', messages: ['msg1', 'msg2'] }, 
	{ _id: 'user2', messages: ['msg3', 'msg1'] }, 
	{ _id: 'user3', messages: ['msg6', 'msg3'] },
	{ _id: 'user4', messages: ['msg4', 'msg8'] }
];

var hashmap = _.chain(data)
			   .indexBy('_id')				   
			   .mapValues('messages')
			   .tap(log)
			   .value();

function log(value) {
	pre.innerHTML += JSON.stringify(value, null, 4) + "\n"
}
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>
<pre id="pre"></pre>