如何展开子文档数组,然后反转该过程,而不丢失其他键?

问题描述 投票:0回答:1

我对 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 数组 - 这样我就可以将其过滤掉,然后我尝试重新加入第一个表单。 但是分组后我丢失了 housenameadress 字段。 这是输出:

{"_id":"20",
"people":[
{"_id":"65976faeaa644d02c4090826","name":"Jon","age":23},{"_id":"65976faeaa644d02c4090827","name":"Ann","age":50}]}

我不知道如何在输出中保留 housenameadress 字段。我尝试过添加.projection({housename:1 ,adress:1 ... }); ,但它什么也没做,我认为这些键在 group() 之后的管道中不存在。我也一直在考虑在 match() 之后将这些值保存到 vars 中,然后在最后添加它们,但我不知道如何在链的中间访问它们。

node.js mongoose mongoose-schema
1个回答
0
投票

您可以使用简单的

$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'});
   }
});

请参阅此处了解工作示例。

© www.soinside.com 2019 - 2024. All rights reserved.