我对 Mongoose 完全陌生。
我有这个架构:
const houseSchema = new mongoose.Schema({
_id: String,
housename: {type: String,unique: true},
adress: String,
people: [ {
name: String,
age: Number
} ],
});
和文件:
let house = new House({
_id: 20,
housename: "white",
adress: "St1",
people:[
{name: "Jon", age: 23},
{name: "Ann", age:50},
{name: "Pat", age:20},
{name: "Helen", age:15}]
});
我想通过 id 找到这个文档,并按年龄过滤人员数组,然后返回没有过滤对象的完整文档。所以预期的输出是:(对于年龄>21):
{
_id: 20,
housename: "white",
adress: "St1",
people:[
{_id:"65976faeaa644d02c4090826", name: "Jon", age: 23},
{_id:"65976faeaa644d02c4090827", name: "Ann", age:50}
]
}
经过数小时的尝试,我对这个问题的解决方案是:
app.get("/api/test", (req, res) => {
var searchID = "20";
var minAge = 21;
House.aggregate([{$match: {_id: searchID}}])
.unwind("people").match({'people.age': {$gt: minAge}})
.group({
_id: "$_id",
people: {$push: "$people"}
})
.exec((err,data)=>{
res.json(data);
});
});
所以首先我匹配 id,然后倒带 people 数组 - 这样我就可以将其过滤掉,然后我尝试重新加入第一个表单。 但是分组后我丢失了 housename 和 adress 字段。 这是输出:
{"_id":"20",
"people":[
{"_id":"65976faeaa644d02c4090826","name":"Jon","age":23},{"_id":"65976faeaa644d02c4090827","name":"Ann","age":50}]}
我不知道如何在输出中保留 housename 和 adress 字段。我尝试过添加.projection({housename:1 ,adress:1 ... }); ,但它什么也没做,我认为这些键在 group() 之后的管道中不存在。我也一直在考虑在 match() 之后将这些值保存到 vars 中,然后在最后添加它们,但我不知道如何在链的中间访问它们。
您可以使用简单的
$filter
来过滤符合您的过滤条件的 people
对象,如下所示:
app.get("/api/test", async (req, res) => { //< Mark as async
var searchID = "20";
var minAge = 21;
try{
const data = await House.aggregate([
{
$match: {
"_id": searchID
}
},
{
"$addFields": {
people: {
$filter: {
input: "$people",
as: "p",
cond: {
$gte: [
"$$p.age",
minAge
]
}
}
}
}
}
]);
res.json(data);
} catch(err){
console.log(err);
res.json({message: 'Error on server'});
}
});
请参阅此处了解工作示例。