我对Mongoose完全陌生.

我有这样的Schema:

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}
    ]
 }

经过几个小时的try ,我对这个问题的解决方案是:

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数组,这样我就可以过滤掉它,然后我try 重新加入到第一个形式.However after grouping I lose housename and adress fields.的输出如下:

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

我不知道如何在输出中保持housenameadress字段.我已经try 添加.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: {
                     $gt: [
                        "$$p.age",
                        minAge 
                     ]
                  }
               }
            }
         }
      }
      ]);
      res.json(data);
   } catch(err){
      console.log(err);
      res.json({message: 'Error on server'});
   }
});

有关工作示例,请参见HERE.

使用$addFields在这里很重要,因为:

将新字段添加到文档.$addFields输出包含输入文档中的所有现有字段和新添加的字段的文档.这个 $addFields阶段相当于$project阶段,它显式指定输入文档中的所有现有字段并添加新字段.

我认为这就是你在$project号车上遇到麻烦的地方.我所做的就是使用$addFields用新的过滤版本覆盖现有的people属性.

Node.js相关问答推荐

postgresql层与应用层的序列化

GraphQL MongoDB Mongoose填充字段未获取多个类别

(0,core_1.default)不是使用@middy/core的lambda处理程序上的函数

我的 MERN 网站一直告诉我我的一个函数不是一个函数

我的 React + Express 应用程序不断向我的数组添加一个空对象

为什么 docker 容器内的应用程序无法访问它自己的 API 端点?

dayjs的isSameOrAfter方法未按预期工作

Cloudflare 522 错误 - javascript 客户端连接到 node 服务器

使用`useLocalStorage`和`useDebounce`时如何解决Next.js中的react-hydration-error

Mongodb 从文档中获取聚合结果中的特定属性

Aptana Studio 是否有 NodeJS 插件?

我可以向NPM添加调试脚本吗?

使用 nvm-windows 时更新 npm

添加git信息到create-react-app

具有多个条件的mongoose 查找

对不同对象中的函数使用相同的键时,V8 中的函数调用缓慢

为什么我会收到错误:解决方法指定过多?

Heroku + Node:找不到模块错误

在 Node.js 上使用 Connect 无法获取 /

react-native run-android 无法识别