【问题标题】:$lookup when foreignField is in nested array当foreignField在嵌套数组中时的$lookup
【发布时间】:2018-11-27 09:38:27
【问题描述】:

我有两个收藏:

学生

 {    
    _id: ObjectId("657..."),  
    name:'abc'
 },  
 {  
    _id: ObjectId("593..."),  
    name:'xyz'
 }

图书馆

 {    
    _id: ObjectId("987..."),  
    book_name:'book1',
    issued_to: [
      {
       student: ObjectId("657...")
      },
      {
       student: ObjectId("658...")
      }
    ]
 },  
 {  
    _id: ObjectId("898..."),  
    book_name:'book2',
    issued_to: [
     {
       student: ObjectId("593...")
     },
     {
       student: ObjectId("594...")
     }
   ] 
 }

我想加入 Student 集合,该集合存在于 Library 集合的 issued_to 对象字段数组中。

我想对学生收藏进行查询以获取学生数据以及图书馆收藏,如果学生存在或不存在,则将检查issued_to数组,否则获取图书馆文档。 我试过 $lookup 的 mongo 3.6 但我没有成功。

db.student.aggregate([{$match:{_id: ObjectId("593...")}}, $lookup: {from: 'library', let: {stu_id:'$_id'}, pipeline:[$match:{$expr: {$and:[{"$hotlist.clientEngagement": "$$stu_id"]}}]}])

但它会引发错误,请在这方面帮助我。我还查看了在 stackoverflow 上提出的其他问题,例如。 question on stackoverflow, question2 on stackoverflow 但这些是比较简单的字段而不是对象数组。请帮帮我

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    您需要 $unwind 库集合中的 issued_to 以匹配 issued_to.student_id

    db.student.aggregate([
      { "$match": { "_id": mongoose.Types.ObjectId(id) } },
      { "$lookup": {
        "from": Library.collection.name,
        "let": { "studentId": "$_id" },
        "pipeline": [
          { "$unwind": "$issued_to" },
          { "$match": { "$expr": { "$eq": [ "$issued_to.student", "$$studentId" ] } } }
        ],
        "as": "issued_to"
      }}
    ])
    

    【讨论】:

      【解决方案2】:

      我不确定我是否完全理解您的问题,但这应该对您有所帮助:

      db.student.aggregate([{
          $match: { _id: ObjectId("657...") }
      }, {
          $lookup: {
              from: 'library',
              localField: '_id' ,
              foreignField: 'issued_to.student',
              as: 'result'
          }
      }])
      

      如果您只想获取每个学生的所有 book_names,您可以这样做:

      db.student.aggregate([{
          $match: { _id: ObjectId("657657657657657657657657") }
      }, {
          $lookup: {
              from: 'library',
              let: { 'stu_id': '$_id' },
              pipeline: [{
                  $unwind: '$issued_to' // $expr cannot digest arrays so we need to unwind which hurts performance...
              }, {
                  $match: { $expr: { $eq: [ '$issued_to.student', '$$stu_id' ] } }
              }, {
                  $project: { _id: 0, "book_name": 1 } // only include the book_name field
              }],
              as: 'result'
          }
      }])
      

      【讨论】:

      • 嘿,谢谢,@dnickless 我明白我在查询中遗漏了什么,非常感谢
      • 您对“$expr 无法消化数组...”的评论对我很有帮助。
      【解决方案3】:

      这可能不是一个很好的答案,但如果您可以将 Library 的架构更改为:

      {    
        _id: ObjectId("987..."),  
        book_name:'book1'
        issued_to: [
          ObjectId("657..."),
          ObjectId("658...")
        ]
      },  
      {  
        _id: "ObjectId("898...")",  
        book_name:'book2'
        issued_to: [
          ObjectId("593...")
          ObjectId("594...")
        ] 
      }
      

      那么当你这样做时:

      {
        $lookup: {
          from: 'student',
          localField: 'issued_to',
          foreignField: '_id',
          as: 'issued_to_students',  // this creates a new field without overwriting your original 'issued_to'
        }
      },
      

      根据上面的示例,您应该得到:

      {    
        _id: ObjectId("987..."),  
        book_name:'book1'
        issued_to_students: [
          { _id: ObjectId("657..."), name: 'abc', ... },
          { _id: ObjectId("658..."), name: <name of this _id>, ... }
        ]
      },  
      {  
        _id: "ObjectId("898...")",  
        book_name:'book2'
        issued_to: [
          { _id: ObjectId("593..."), name: 'xyz', ... },
          { _id: ObjectId("594..."), name: <name of this _id>, ... }
        ] 
      }
      

      【讨论】:

        猜你喜欢
        • 2019-06-29
        • 1970-01-01
        • 1970-01-01
        • 2018-11-30
        • 1970-01-01
        • 2020-02-20
        • 2018-10-06
        • 1970-01-01
        相关资源
        最近更新 更多