[英]get a sub document field in $project stage of aggregation
I'm working with the followings schemas:我正在使用以下模式:
Question Schema:问题架构:
var Question = new Schema({
title: String,
content: String,
createdBy: {
type: Schema.ObjectId,
ref: 'User',
required: true
},
answers: {
type: [ { type: Schema.Types.ObjectId, ref: 'Answer' } ]
}
});
Answer Schema:答案架构:
var Answer = new Schema({
content:String,
createdBy: {
type: Schema.Types.ObjectId,
ref: 'User',
},
isBest: {
type: Boolean,
default: false
},
createdAt: Date,
votes: Number
});
I'm trying to do an aggregation where I can have as result the list of all questions with a certain fields like title
, createdBy
(which is going to be populated after the aggregate) , an answers_count
and a has_best
field which is going to be true if a question
already have a best answer (an answer with the field isBest equals to true) .我正在尝试进行聚合,结果我可以得到所有问题的列表,其中包含特定字段,如
title
、 createdBy
(将在聚合后填充) 、 answers_count
和has_best
字段,这将是如果question
已经有最佳答案(字段 isBest 的答案等于 true),则为 true 。
I've try with the $project
pipeline:我尝试使用
$project
管道:
Question.aggregate([{
$project: {
answers_count: { $size: '$answers' },
title: true,
createdAt: true,
createdBy: true,
has_best_answer: '$answers.isBest'
}
}, {
$sort: {
createdAt: -1
}
}], function(err, questions){
if(err){
return res.status(400).send({ message: err });
}
User.populate(questions, { path: 'createdBy', model: 'User', select: 'firstname lastname image' }, function(err, questions){
return res.json(questions);
});
});
Also I've try to $unwind
the array and then $lookup
for answers but no results when doing an answers_count
.此外,我尝试
$unwind
数组,然后$lookup
寻找答案,但在执行answers_count
时没有结果。 This is what I've tried with $unwind
and $lookup
.这是我用
$unwind
和$lookup
尝试过的。
Question.aggregate([
{
$unwind: '$answers'
},
{
$lookup: {
from: 'answers',
localField: 'answers',
foreignField: '_id',
as: 'answer'
}
},{
$project: {
title: true,
createdBy: true,
createdAt: true,
has_best_answer: '$answer.isBest'
}
}
], function(err, questions){
if(err){
return res.status(400).send({ message: err });
}
User.populate(questions, { path: 'createdBy', model: 'User', select:
'firstname lastname image' }, function(err, questions){
return res.json(questions);
});
});
So, because the $unwind
in the array, cannot $size
in answers array to do an answers_count
field, also when I tried to do $group
to having uniques questions id
like this:因此,因为数组中的
$unwind
不能在 answers 数组中使用$size
来执行answers_count
字段,所以当我尝试使用$group
来获得唯一questions id
时,如下所示:
Question.aggregate([
{
$unwind: '$answers'
},
{
$lookup: {
from: 'answers',
localField: 'answers',
foreignField: '_id',
as: 'answer'
}
},{
$project: {
title: true,
createdBy: true,
createdAt: true,
has_best_answer: '$answer.isBest'
}
},
{
$group: { _id: '$_id' }
}
], function(err, questions){
if(err){
return res.status(400).send({ message: err });
}
User.populate(questions, { path: 'createdBy', model: 'User', select: 'firstname lastname image' }, function(err, questions){
return res.json(questions);
});
});
I have this result:我有这个结果:
[
{
"_id": "5825f2846c7ab9ec004f14ce"
},
{
"_id": "5823b9309de40494239c95cd"
},
{
"_id": "582538366062607c0f4bcdaa"
},
{
"_id": "5855d319b6a475100c7beba2"
},
{
"_id": "5878156328dba3d02052b321"
}
]
This is the output that I'm looking for:这是我正在寻找的输出:
[
{
_id: '5825f2846c7ab9ec004f14ce',
title: 'Some question title',
createdBy: '5855d319b6a475100c7beba2', // this is going to be populated,
createdAt: '2016-11-10T00:02:56.702Z',
answers_count: 5,
has_best_answer: true
},
{
_id: '5825f2846c7ab9ec004f14ce',
title: 'Some other question title',
createdBy: '5855d319b6a475100c7beba2', // this is going to be populated,
createdAt: '2016-11-10T00:02:56.702Z',
answers_count: 2,
has_best_answer: false
}
]
You can try something like below.你可以试试下面的方法。
$lookup
- This stage joins all the answers
to a question documents. $lookup
- 此阶段将问题文档的所有answers
结合起来。
$project
- This stage projects all the required fields. $project
- 此阶段投影所有必填字段。 answers_count
- Counts the total the number of items in an answers
array. answers_count
- 计算answers
数组中的项目总数。 has_best_answer
- Iterates an answers
and compares if any of the isBest
field value is true. has_best_answer
- 迭代answers
并比较任何isBest
字段值是否为真。
Question.aggregate([
{
$lookup: {
from: 'answers',
localField: 'answers',
foreignField: '_id',
as: 'answers'
}
},{
$project: {
title: true,
createdBy: true,
createdAt: true,
answers_count: { $size: '$answers' },
has_best_answer:
{ $anyElementTrue: {
$map: {
input: "$answers",
as: "answer",
in: { $eq: [ "$$answer.isBest", true] }
}
}}
}
}
]);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.