ReQLでTableJoin（１対多）

RethinkDBでtableJoinする方法について。

## リファレンス

[Table joins in RethinkDB](https://www.rethinkdb.com/docs/table-joins/)

## 今回つかうテーブルとドキュメント

### ユーザーテーブル

<img width="483" alt="Screen Shot 2016-09-18 at 7.36.08 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/77614/9506f448-bd22-2867-ef7b-c535acd34f61.png">

### メッセージテーブル

<img width="589" alt="Screen Shot 2016-09-18 at 7.36.15 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/77614/e8ab1714-bb5c-cc9c-3a52-7d0b866c9895.png">


ユーザーとメッセージは１対多の関係になっている。


## ReQLクエリ

### innerJoinを使った場合

[ReQL command: innerJoin](https://www.rethinkdb.com/api/javascript/inner_join/)

```js
r.db('DBName').table('messages').innerJoin(r.db('trialDB').table('users'), (messageRow, userRow) => {
  return messageRow('userId').eq(userRow('id'))
})
```
ちょっと長い。しかも、ドキュメントによると、innerJoinは遅いし効率が良くないので非推奨とのこと。（outerJoinも同様）


### eqJoinを使った場合

[ReQL command: eqJoin](https://www.rethinkdb.com/api/javascript/eq_join/)

```js
r.db('DBName').table('messages').eqJoin('userId', 
r.db('DBName').table('users'))
```

短い。

## クエリ結果

ちなみに、クエリ結果はこんな感じ。left, rightの項目にそれぞれのテーブルからマッチしたドキュメントが記載されている。

```js
{
  "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を使ってクエリ結果をマージ

[ReQL command: zip](https://www.rethinkdb.com/api/javascript/zip/)

先程のeqJoinの末尾にzip()を付け足すと、クエリ結果のrightをleftにマージできる。

```js
r.db('DBName').table('messages').eqJoin('userId', 
r.db('DBName').table('users')).zip()
```


↑のReQLを発行すると、以下の結果が取得できる。

```js

{
  "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を抜いておきます。

[ReQL command: without](https://www.rethinkdb.com/api/javascript/without/)

```js
r.db('DBName').table('messages').eqJoin('userId',
r.db('DBName').table('users')).without({right: 'id'}).zip()
```

クエリ結果がきれいになりました。

```js
{
  "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の順に整列させます。

[ReQL command: orderBy](https://www.rethinkdb.com/api/javascript/order_by/)


```js
r.db('DBName').table('messages').eqJoin('userId',
r.db('DBName').table('users')).without({right: 'id'}).zip().orderBy('id')
```

zipの結果に対して並び替えを行うので、zipの後に追記しました。

クエリ結果がこちら。

```js
{
  "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
}
```

きちんと整列しています。