RethinkDB:​​从表到数组的外部联接

时间:2017-03-17 18:58:11

标签: rethinkdb rethinkdb-javascript

我有三个表,类,课程和userSchedules,如下所示:

{ "classId": "24ab7b14-f935-44c1-b91b-8598123ea54a", "courseNumber": "PO101" , "days": "MWF" , "professor": "Abramius Darksbayn" , "seatsAvailable": 23 , "time": 11 }

课程 { "courseNumber": "PO101" , "courseName": "Intro to Potions" , "creditHours": 3 , "description": "Potions..." }

userSchedules { "userId": "123", "classes": [ "24ab7b14-f935-44c1-b91b-8598123ea54a", "ab7b4414-a833-4ac2-c84a-98123ea54a97" ] , }

我想编写一个连接类和课程(在courseNumber上)然后外连接到userSchedules的查询。因此,我希望始终返回所有类及其相应的课程,如果用户已注册该课程,我想返回。所以我希望结果看起来像这样:

{ "classId": "24ab7b14-f935-44c1-b91b-8598123ea54a", "days": "MWF" , "professor": "Abramius Darksbayn" , "seatsAvailable": 23 , "time": 11, "course": { "courseNumber": "PO101" , "courseName": "Intro to Potions" , "creditHours": 3 , "description": "Potions..." }, isEnrolled: true }

我真的很难弄清楚如何完成这项工作,其次,最有效的方法是做到这一点。任何帮助将不胜感激!谢谢!

修改 好吧,我找到了一种方法来完成大部分工作,但它看起来真的很多代码,我也想知道它的性能。 即使没有"右边" !!result("right")总是返回true。从外部联接的一面。有更好的方法来做到这一点:

r.table('classes') .eqJoin('courseNumber', r.table('courses')) .outerJoin( r.table('userSchedules').getAll(userId).concatMap(schedule => schedule('classes')), (joinedClass, scheduledClassId) => joinedClass('left')('classId').eq(scheduledClassId)) .map(result => { return { classId: result('left')('left')('classId'), days: result('left')('left')('days'), professor: result('left')('left')('professor'), seatsAvailable: result('left')('left')('seatsAvailable'), time: result('left')('left')('time'), course: result('left')('right'), enrolled: result.hasFields('right') } })

编辑2: 我弄清楚为什么isEnrolled没有工作。我已经编辑了上述查询以显示我最近的努力。

1 个答案:

答案 0 :(得分:2)

如果您想让查询更具可读性,可以将其更改为:

const allUserClasses = 
          r.table('userSchedules')
           .getAll(userId)
           .concatMap(schedule => schedule('classes'))

r.table('classes')
  .eqJoin('courseNumber', r.table('courses'))
  .map(joined => joined('left').without('courseNumber').merge({course: joined('right') })
  .outerJoin(allUserClasses,
    (joinedClass, scheduledClassId) => joinedClass('classId').eq(scheduledClassId))
  .map(result => result('left').merge({ enrolled: result.hasFields('right') })

此外,如果你有一个固定的小数组外连接总是一个矫枉过正,这更合适:

r.table('userSchedules')
 .get(userId)('classes')
 .do(userClasses =>
    r.table('classes')
     .eqJoin('courseNumber', r.table('courses'))
     .map(joined => joined('left')
         .without('courseNumber')
         .merge({
            course: joined('right'),
            enrolled: userClasses.contains(joined('left')('classId')) 
         })
     )
 )