Команда ReQL: eq_join
Синтаксис команды
sequence.eq_join(left_field, right_table[, :index => 'id', :ordered => false]) → sequence sequence.eq_join(function, right_table[, :index => 'id', :ordered => false]) → sequence
Описание
Объединяет таблицы с использованием поля или функции в левой последовательности, сопоставляющей первичные ключи или вторичные индексы в правой таблице. eq_join более эффективен, чем другие типы объединений ReQL, и работает гораздо быстрее. Документы в результирующем наборе состоят из пар документов из левой и правой таблиц, сопоставленных, когда поле в левой части существует и не является пустым, а запись с этим значением поля существует в указанном индексе в правой части.
Результирующий набор eq_join представляет собой поток или массив объектов. Каждый объект в возвращенном наборе будет объектом в формате { left: <left-document>, right: <right-document> }, где значения left и right будут объединёнными документами. Используйте команду zip для объединения полей left и right.
Результаты eq_join по умолчанию не упорядочены. Опциональный параметр :ordered => true заставит eq_join упорядочить вывод на основе входного потока слева. (Если для документа из левой части существует несколько совпадений в правой части, их порядок не гарантируется, даже если ordered true. Требование упорядоченных результатов может значительно замедлить eq_join, и во многих ситуациях это упорядочение не требуется. (См. первый пример, в котором упорядоченные результаты получаются с использованием order_by после eq_join.)
Предположим, что таблица игроков содержит следующие документы:
[
{ :id => 1, :player => 'George', :game_id => 1 },
{ :id => 2, :player => 'Agatha', :game_id => 3 },
{ :id => 3, :player => 'Fred', :game_id => 2 },
{ :id => 4, :player => 'Marie', :game_id => 2 },
{ :id => 5, :player => 'Earnest', :game_id => 1 },
{ :id => 6, :player => 'Beth', :game_id => 3 }
]
Таблица игр содержит следующие документы:
[
{ :id => 1, :field => 'Little Delving' },
{ :id => 2, :field => 'Rushock Bog' },
{ :id => 3, :field => 'Bucklebury' }
]
Пример: Сопоставление игроков с играми, в которых они играли друг против друга.
Объедините эти таблицы с помощью game_id в таблице игроков и id в таблице игр:
r.table('players').eq_join('game_id', r.table('games')).run(conn)
Это вернет результирующий набор, подобный следующему:
[
{
'left' => { 'game_id' => 3, 'id' => 2, 'player' => "Agatha" },
'right' => { 'id' => 3, 'field' => "Bucklebury" }
},
{
'left' => { 'game_id' => 2, 'id' => 3, 'player' => "Fred" },
'right' => { 'id' => 2, 'field' => "Rushock Bog" }
},
...
]
Скорее всего, вам нужно результат использования zip с этим. Для ясности, мы воспользуемся without для удаления поля id из таблицы игр (оно конфликтует с полем id для игроков и, в любом случае, избыточно), и отсортируем его по играм.
r.table('players').eq_join('game_id', r.table('games')).without({:right => "id"}).zip().order_by('game_id').run(conn)
[
{ 'field' => "Little Delving", 'game_id' => 1, 'id' => 5, 'player' => "Earnest" },
{ 'field' => "Little Delving", 'game_id' => 1, 'id' => 1, 'player' => "George" },
{ 'field' => "Rushock Bog", 'game_id' => 2, 'id' => 3, 'player' => "Fred" },
{ 'field' => "Rushock Bog", 'game_id' => 2, 'id' => 4, 'player' => "Marie" },
{ 'field' => "Bucklebury", 'game_id' => 3, 'id' => 6, 'player' => "Beth" },
{ 'field' => "Bucklebury", 'game_id' => 3, 'id' => 2, 'player' => "Agatha" }
]
Для получения дополнительной информации см. Объединения таблиц в RethinkDB.
Пример: Использование вторичного индекса в правой таблице вместо первичного ключа. Если у игроков есть вторичный индекс по городам, мы можем получить список арен с игроками в том же районе.
r.table('players').eq_join('city_id', r.table('arenas'), {:index => 'city_id'}).run(conn)
Пример: Использование вложенного ключа в качестве поля объединения. Предположим, что документы в таблице игроков были структурированы так:
{ :id => 1, :player => 'George', :game => {:id => 1} },
{ :id => 2, :player => 'Agatha', :game => {:id => 3} },
...
Просто укажите поле, используя блок вместо строки.
r.table('players').eq_join(
lambda { |player| player['game']['id'] },
r.table('games')).without({:right => 'id'}
).zip().run(conn)
[
{ 'field' => "Little Delving", 'game' => { 'id' => 1 }, 'id' => 5, 'player' => "Earnest" },
{ 'field' => "Little Delving", 'game' => { 'id' => 1 }, 'id' => 1, 'player' => "George" },
...
]
Пример: Использование функции вместо поля для объединения по более сложному выражению. Предположим, что у игроков есть списки любимых игр, отсортированных по порядку, в таком поле, как favorites: [3, 2, 1]. Получите список игроков и их любимую игру:
r.table('players').eq_join(
lambda { |player| player['favorites'].nth(0) },
r.table('games')
).without([{:left => ['favorites', 'game_id', 'id']}, {:right => 'id'}]).zip()
Результат:
[
{ 'field' => "Rushock Bog", 'name' => "Fred" },
{ 'field' => "Little Delving", 'name' => "George" },
...
]
© RethinkDB contributors
Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
https://rethinkdb.com/api/ruby/eq_join/