【问题标题】:How to filter sub-document in mongoDB? [duplicate]如何过滤 mongoDB 中的子文档? [复制]
【发布时间】:2016-09-01 08:06:45
【问题描述】:

我有这个 mlab 文档:

{
"_id": {
    "$oid": "572b2cdfc80eb653c302f5e9"
},
"year": 2014,
"students": [
    {
        "id": 5,
        "firstName": "Joe",
        "lastName": "know",
        "GPA": 67
    },
    {
        "id": 3,
        "firstName": "Peter",
        "lastName": "Jones",
        "GPA": 77
    },
    {
        "id": 6,
        "firstName": "Yossi",
        "lastName": "Haim",
        "GPA": 68
    },
    {
        "id": 13,
        "firstName": "Chen",
        "lastName": "Si",
        "GPA": 92
    }
]
}

我得到的:(年份也是一个参数)

gradeM= mongoose.model('Grade',grade);
      gradeM.find({'year':year},'-_id').exec(function (err, data) {
          if (err) console.log("err: " + err);
      console.log(JSON.stringify(data)); 
  });

尽管从集合中获取数据我做得很好,但我希望从返回的文档中排除 GPA

最终结果应如下所示:

 {
   "year": 2014,
   "students": [
    {
        "id": 13,
        "firstName": "Chen",
        "lastName": "Si",
        "GPA": 92
    }
]
}

我总是可以使用 JS 循环文档,但我正在寻找一种方法来立即获得准备好的结果。
谢谢

【问题讨论】:

    标签: javascript node.js mongodb mongoose


    【解决方案1】:

    您可以使用$elemMatch。

    尝试如下

    gradeM= mongoose.model('Grade',grade);
      gradeM.find({'year':year, students: { $elemMatch: GPA: { $lt: 90 } }},'-_id').exec(function (err, data) {
          if (err) console.log("err: " + err);
      console.log(JSON.stringify(data)); 
      });
    

    【讨论】:

      【解决方案2】:

      您可以尝试使用聚合

      gradeM.aggregate( {$match: {year: 2014}},{ $unwind: '$students'},
                         { $match: {'students.GPA': {$lt: 90}}},
                         { $group: {_id: '$_id',
                                    year : '$year',
                                    students: {$push: {id:'$students.id',
                                                       firstName:'$students.firstName'}}}})
      

      输出:

      { "_id" : ObjectId("572b2cdfc80eb653c302f5e9"), 
        "year":2014,
         "students" : [ { "id" : 5, "firstName" : "Joe" },
                        { "id" : 3, "firstName" : "Peter" },
                        { "id" : 6, "firstName" : "Yossi" } ] }
      

      另外,你可以试试

      gradeM.aggregate([
          { $match: {year: year}},
          { $project: {
              students: {$filter: {
                  input: '$students',
                  as: 'students',
                  cond: {$lt: ['$$students.GPA', 90]}
              }}
              }}
          ])
      

      【讨论】:

      • 第一个返回 [] 根据我拥有的数据不应该为空。如果我没有弄错是因为 mongoDB 版本无法识别 $filter,那么第二个会下降。感谢您的帮助
      • 让我试试……等一下
      • $filter 的好方法 - 喜欢它!
      • 非常感谢。乐于助人
      【解决方案3】:

      您可以 $unwind 学生,过滤他们,然后添加到组 - 请参阅下面的示例:

      db.yush.aggregate([
      {$match:{"year":2014}},
      {
                  $unwind : "$students"
              }, {
                  $match : {
                      "students.GPA" : {
                          $lt : 90
                      }                
                  }
              }, {
                  $group : {
                      _id : "$year"
                      ,
                      students : {
                          $push : "$students"
                      }
                  }
              }
          ])
      

      最后使用 $project 将 _id 更改为 year

      玩得开心 - 欢迎任何 cmets!

      【讨论】:

      • 这看起来不错,它根据需要给了我所有的 GPA>=90,但它会返回所有年份。如何根据进入函数的年份参数进行过滤?非常感谢
      • @YushN 添加了 $match 阶段作为第一个仅处理选定年份的阶段
      • 与 explixit ye​​ar 一起工作得很好,但是一旦我写了参数 year(它具有相同的值),我得到 []。谢谢
      • @YushN - 嗯,这很奇怪 - 不知道
      • 获胜者是:"year":parseInt(year) @profesor79 列表中的下一个,试图了解如何使用聚合回调返回作为我可以在浏览器上显示的 http 响应
      猜你喜欢
      • 1970-01-01
      • 2013-02-13
      • 2015-07-23
      • 2019-08-15
      • 1970-01-01
      • 2020-04-14
      • 2018-01-26
      相关资源
      最近更新 更多