foreignField在嵌套数组中时的$ lookup

时间:2018-06-18 13:58:33

标签: mongodb mongodb-query aggregation-framework

我有两个系列:

学生

 {    
    _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...")
     }
   ] 
 }

我想加入学生集合,该集合存在于图书馆集合中 issued_to 对象字段数组中。

我想查询学生集合以获取学生数据以及库集合,如果学生存在或不存在则将检查issued_to数组,否则获取库文档。 我尝试过查找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 stackoverflowquestion2 on stackoverflow但这些是简单的字段而不是对象数组。请帮帮我

3 个答案:

答案 0 :(得分: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"
  }}
])

答案 1 :(得分:1)

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

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

如果您只想为每个学生获得所有book_name,您可以这样做:

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

答案 2 :(得分:0)

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

{    
  _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>, ... }
  ] 
}