如何根据Array字段的长度对文档进行sorting

在我的小型ExpressJS应用程序中,我有一个像这样定义的问题模型

var mongoose = require('mongoose'), Schema = mongoose.Schema; /** * Question Schema */ var Question = new Schema({ title: { type: String, default: '', trim: true, required: 'Title cannot be blank' }, content: { type: String, default: '', trim: true }, created: { type: Date, default: Date.now }, updated: { type: Date, default: Date.now }, author: { type: Schema.ObjectId, ref: 'User', require: true }, answers : [{ type: Schema.ObjectId, ref: 'Answer' }] }); module.exports = mongoose.model('Question', Question); 

我想根据答案编号得到热门的问题列表。 我用来执行我的目的的查询

 Question.find() .sort({'answers.length': -1}) .limit(5) .exec(function(err, data) { if (err) return next(err); return res.status(200).send(data); }); 

但我什么都没有得到 你有什么解决办法?

你在这里的意思是,你想根据“answers”数组的“长度”对结果进行“sorting”,而不是像你的语法所暗示的那样,称为“length”。 对于logging来说,这个语法在这里是不可能的,因为你的模型是“引用的”,这意味着这个集合文档中的数组字段中唯一存在的数据就是这些引用文档的ObjectId值。

但是你可以使用.aggregate()方法和$size运算符来完成这个工作:

 Question.aggregate( [ { "$project": { "title": 1, "content": 1, "created": 1, "updated": 1, "author": 1, "answers": 1, "length": { "$size": "$answers" } }}, { "$sort": { "length": -1 } }, { "$limit": 5 } ], function(err,results) { // results in here } ) 

聚合pipe道分阶段工作。 首先,结果中的字段有一个$project ,您可以使用$size来返回指定数组的长度。

现在有一个“长度”的字段,您可以按照$sort$limit的顺序来执行这些步骤,这些步骤在聚合pipe道中作为自己的阶段来应用。

更好的方法是始终保持文档中“answers”数组的长度属性。 这使得无需其他操作就可以轻松地进行sorting和查询。 使用$inc操作符来维护这一点很简单,因为您可以从数组中获取$push$pull项目:

 Question.findByIdAndUpdate(id, { "$push": { "answers": answerId }, "$inc": { "answerLength": 1 } }, function(err,doc) { } ) 

或者在删除时反过来:

 Question.findByIdAndUpdate(id, { "$pull": { "answers": answerId }, "$inc": { "answerLength": -1 } }, function(err,doc) { } ) 

即使您不使用primefaces操作符,那么在您更新“长度”时也适用相同的原则。 然后用一种查询很简单:

 Question.find().sort({ "answerLength": -1 }).limit(5).exec(function(err,result) { }); 

由于该文件已经存在。

因此,要么使用.aggregate() ,而要对数据没有任何改变,或者改变你的数据一直包括长度作为一个属性,你的查询将是非常快的。

你也可以使用:

 db.question.find().sort({"answers":-1}).limit(5).pretty();