[英]get a sub document field in $project stage of aggregation
我正在使用以下模式:
問題架構:
var Question = new Schema({
title: String,
content: String,
createdBy: {
type: Schema.ObjectId,
ref: 'User',
required: true
},
answers: {
type: [ { type: Schema.Types.ObjectId, ref: 'Answer' } ]
}
});
答案架構:
var Answer = new Schema({
content:String,
createdBy: {
type: Schema.Types.ObjectId,
ref: 'User',
},
isBest: {
type: Boolean,
default: false
},
createdAt: Date,
votes: Number
});
我正在嘗試進行聚合,結果我可以得到所有問題的列表,其中包含特定字段,如title
、 createdBy
(將在聚合后填充) 、 answers_count
和has_best
字段,這將是如果question
已經有最佳答案(字段 isBest 的答案等於 true),則為 true 。
我嘗試使用$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);
});
});
此外,我嘗試$unwind
數組,然后$lookup
尋找答案,但在執行answers_count
時沒有結果。 這是我用$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);
});
});
因此,因為數組中的$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);
});
});
我有這個結果:
[
{
"_id": "5825f2846c7ab9ec004f14ce"
},
{
"_id": "5823b9309de40494239c95cd"
},
{
"_id": "582538366062607c0f4bcdaa"
},
{
"_id": "5855d319b6a475100c7beba2"
},
{
"_id": "5878156328dba3d02052b321"
}
]
這是我正在尋找的輸出:
[
{
_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
}
]
你可以試試下面的方法。
$lookup
- 此階段將問題文檔的所有answers
結合起來。
$project
- 此階段投影所有必填字段。 answers_count
- 計算answers
數組中的項目總數。 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.