RethinkDBでtableJoinする方法について。
リファレンス
今回つかうテーブルとドキュメント
ユーザーテーブル
メッセージテーブル
ユーザーとメッセージは1対多の関係になっている。
ReQLクエリ
innerJoinを使った場合
r.db('DBName').table('messages').innerJoin(r.db('trialDB').table('users'), (messageRow, userRow) => {
return messageRow('userId').eq(userRow('id'))
})
ちょっと長い。しかも、ドキュメントによると、innerJoinは遅いし効率が良くないので非推奨とのこと。(outerJoinも同様)
eqJoinを使った場合
r.db('DBName').table('messages').eqJoin('userId',
r.db('DBName').table('users'))
短い。
クエリ結果
ちなみに、クエリ結果はこんな感じ。left, rightの項目にそれぞれのテーブルからマッチしたドキュメントが記載されている。
{
"left": {
"id": 3 ,
"message": "What's up?" ,
"userId": 1
} ,
"right": {
"id": 1 ,
"name": "Sam"
}
}
{
"left": {
"id": 1 ,
"message": "Hi, John" ,
"userId": 1
} ,
"right": {
"id": 1 ,
"name": "Sam"
}
}
{
"left": {
"id": 2 ,
"message": "Hi there, Sam" ,
"userId": 2
} ,
"right": {
"id": 2 ,
"name": "John"
}
}
クエリ結果の整形
zipを使ってクエリ結果をマージ
先程のeqJoinの末尾にzip()を付け足すと、クエリ結果のrightをleftにマージできる。
r.db('DBName').table('messages').eqJoin('userId',
r.db('DBName').table('users')).zip()
↑のReQLを発行すると、以下の結果が取得できる。
{
"id": 1 ,
"message": "What's up?" ,
"name": "Sam" ,
"userId": 1
}
{
"id": 1 ,
"message": "Hi, John" ,
"name": "Sam" ,
"userId": 1
}
{
"id": 2 ,
"message": "Hi there, Sam" ,
"name": "John" ,
"userId": 2
}
ちょっとidがおかしなことになってます。
withoutをつかって不要な要素の削除
zipを使ってマージする前に、withoutを使ってrightドキュメントの結果からidを抜いておきます。
r.db('DBName').table('messages').eqJoin('userId',
r.db('DBName').table('users')).without({right: 'id'}).zip()
クエリ結果がきれいになりました。
{
"id": 3 ,
"message": "What's up?" ,
"name": "Sam" ,
"userId": 1
}
{
"id": 1 ,
"message": "Hi, John" ,
"name": "Sam" ,
"userId": 1
}
{
"id": 2 ,
"message": "Hi there, Sam" ,
"name": "John" ,
"userId": 2
}
idの順番が整列していなくて気持ち悪いです。
orederByで順序整理
orderByを使って、messageIdの順に整列させます。
r.db('DBName').table('messages').eqJoin('userId',
r.db('DBName').table('users')).without({right: 'id'}).zip().orderBy('id')
zipの結果に対して並び替えを行うので、zipの後に追記しました。
クエリ結果がこちら。
{
"id": 1 ,
"message": "Hi, John" ,
"name": "Sam" ,
"userId": 1
} ,
{
"id": 2 ,
"message": "Hi there, Sam" ,
"name": "John" ,
"userId": 2
} ,
{
"id": 3 ,
"message": "What's up?" ,
"name": "Sam" ,
"userId": 1
}
きちんと整列しています。