Tan*_*iet 7 mongodb node.js mongodb-query aggregation-framework
在我的小型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);
Run Code Online (Sandbox Code Playgroud)
我希望根据答案数量列出热门问题列表.我用来执行我的目的的查询
Question.find()
.sort({'answers.length': -1})
.limit(5)
.exec(function(err, data) {
if (err) return next(err);
return res.status(200).send(data);
});
Run Code Online (Sandbox Code Playgroud)
但我什么都没得到.你有什么解决办法?
Bla*_*ven 11
你在这里的意思是你想要根据"answers"数组的"长度"对结果进行"排序",而不是像语法所暗示的那样称为"length"的"属性".对于记录,这里的语法是不可能的,因为您的模型是"引用的",这意味着此集合的文档中数组字段中存在的唯一数据是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
}
)
Run Code Online (Sandbox Code Playgroud)
聚合管道分阶段工作.首先,结果中有一个$project字段,$size用于返回指定数组的长度.
现在有一个具有"长度"的字段,您可以按照阶段进行操作,$sort并将$limit其作为自己的阶段应用于聚合管道中.
更好的方法是始终在文档中维护"answers"数组的length属性.这使得无需其他操作即可轻松排序和查询.使用$inc运算符$push或$pull数组中的项目来维护这一点非常简单:
Question.findByIdAndUpdate(id,
{
"$push": { "answers": answerId },
"$inc": { "answerLength": 1 }
},
function(err,doc) {
}
)
Run Code Online (Sandbox Code Playgroud)
或者在移除时反向:
Question.findByIdAndUpdate(id,
{
"$pull": { "answers": answerId },
"$inc": { "answerLength": -1 }
},
function(err,doc) {
}
)
Run Code Online (Sandbox Code Playgroud)
即使您没有使用原子操作符,在您更新"长度"时也适用相同的原则.然后查询排序很简单:
Question.find().sort({ "answerLength": -1 }).limit(5).exec(function(err,result) {
});
Run Code Online (Sandbox Code Playgroud)
由于该财产已存在于文件中.
因此,要么在.aggregate()不更改数据的情况下执行此操作,要么将数据更改为包含作为属性的长度,并且查询将非常快.
nit*_*ngh 10
您还可以使用:
db.question.find().sort({"answers":-1}).limit(5).pretty();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4338 次 |
| 最近记录: |