mongoose – 如何分组和填充?

我使用MongoDB和Mongoose作为我的ODM,我试图使用populategroup by在同一语句中进行查询。

这里是我的简单文件模型:

 var userSchema = new Schema({ username: String }); var messageSchema = new Schema({ from: { type: Schema.ObjectId, ref: 'User' }, to: { type: Schema.ObjectId, ref: 'User' }, message: String, date: { type: Date, default: Date.now } }); 

我只是试图把每个用户的消息,每个与他交谈的用户分组。 我试过这样的:

 this.find({ 'to': user }) .sort({ 'date': 1 }) .group('from') .populate(['from', 'to']) .exec(callback); 

但不幸的是,我的模型没有group方法。 你有什么解决scheme,让这个工作?

谢谢。

       

网上收集的解决方案 "mongoose – 如何分组和填充?"

使用$ lookup填充的例子,lookup填充为一个数组,因此$ unwind。

 Message.aggregate( [ { "$match": { "to": user } }, { "$sort": { "date": 1 } }, { "$group": { "_id": "from", "to": { "$first": "$to" }, "message": { "$first": "$message" }, "date": { "$first": "$date" }, "origId": { "$first": "$_id" } }}, { "$lookup": { "from": "users", "localField": "from", "foreignField": "_id", "as": "from" }}, { "$lookup": { "from": "users", "localField": "to", "foreignField": "_id", "as": "to" }}, { "$unwind": { "path" : "$from" } }, { "$unwind": { "path" : "$to" } } ], function(err,results) { if (err) throw err; return results; } ) 

这里使用的更好的select是.aggregate() ,它是一个本地代码实现,不像MongoDB的.group()方法,它使用JavaScript引擎来处理结果。

.populate()这样的方法虽然不是直接支持的,但这是devise的,因为聚合pipe道和其他方法不会严格地返回基于当前模型模式的响应。 既然“承担”是你所做的事情是错误的,那只是一个原始的对象反应。

然而,没有任何东西阻止您将响应“铸造”为mongoose文档,然后用所需的path调用.populate()的模型forms:

 Message.aggregate( [ { "$match": { "to": user } }, { "$sort": { "date": 1 } }, { "$group": { "_id": "from", "to": { "$first": "$to" }, "message": { "$first": "$message" }, "date": { "$first": "$date" }, "origId": { "$first": "$_id" } }} ], function(err,results) { if (err) throw err; results = result.map(function(doc) { doc.from = doc._id doc._id = doc.origId; delete doc.origId; return new Message( doc ) }); User.populate( results, { "path": "from to" }, function(err,results) { if (err) throw err; console.log( JSON.stringify( results, undefined, 4 ) ); }); } ) 

当然,这只是真正地返回来自每个“来自”的$first消息,正如操作员所暗示的那样。

也许你真正想要“分组”的意思是“sorting”:

 Message.find({ "to": user }) .sort({ "from": 1, "date": 1 }) .populate("from to") .exec(function(err,messsages) { if (err) throw err; console.log( JSON.stringify( messages, undefined, 4 ) ); }); 

正如上下文中所说的“所有消息”,而不是分组操作符(如.aggregate().aggregate() .group()收集方法.aggregate()所隐含的内容。 所以这些消息是通过sorting组合在一起的,而不是任何特定的分组。

后者听起来像你真正要问,但如果你真的打算真正的“分组”,那么就有聚合的例子,以及如何使用.populate()