Команда ReQL: eqJoin
Синтаксис команды
sequence.eqJoin(leftField, rightTable) → sequence sequence.eqJoin(function, rightTable) → sequence
Описание
Объединяет таблицы, используя поле или функцию в левой последовательности, соответствующую первичным ключам или вторичным индексам в правой таблице. eqJoin более эффективен, чем другие типы объединения ReQL, и работает значительно быстрее. Документы в наборе результатов состоят из пар документов левой и правой таблиц, соответствующих друг другу, когда поле в левой части существует, не является пустым и в указанном индексе правой части есть запись с соответствующим значением поля.
Результат выполнения eqJoin представляет собой поток или массив объектов. Каждый объект в возвращаемом наборе будет объектом вида { "left": <left-document>, "right": <right-document> }, где значения left и right будут объединёнными документами. Используйте команду zip для объединения left и right полей.
Результаты eqJoin по умолчанию не упорядочены. Указание optArg('ordered', 'true') заставит eqJoin упорядочить вывод на основе входного потока левой части. (Если для документа в левой части есть несколько совпадений в правой части, их порядок не гарантируется, даже если ordered является true.) Требование упорядоченных результатов может значительно замедлить eqJoin, и во многих случаях эта сортировка не потребуется. (См. первый пример, в котором упорядоченные результаты получаются с помощью orderBy после eqJoin.)
Предположим, что таблица players содержит следующие документы (показаны в формате JSON):
[
{ "id": 1, "player": "George", "gameId": 1 },
{ "id": 2, "player": "Agatha", "gameId": 3 },
{ "id": 3, "player": "Fred", "gameId": 2 },
{ "id": 4, "player": "Marie", "gameId": 2 },
{ "id": 5, "player": "Earnest", "gameId": 1 },
{ "id": 6, "player": "Beth", "gameId": 3 }
]
Таблица games содержит следующие документы:
[
{ "id": 1, "field": "Little Delving" },
{ "id": 2, "field": "Rushock Bog" },
{ "id": 3, "field": "Bucklebury" }
]
Пример: Сопоставьте игроков с играми, в которых они играли друг против друга.
Объедините эти таблицы, используя gameId в таблице player и id в таблице games:
r.table("players").eqJoin("gameId", r.table("games")).run(conn);
Это вернёт набор результатов, похожий на следующий:
[
{
"left" : { "gameId" : 3, "id" : 2, "player" : "Agatha" },
"right" : { "id" : 3, "field" : "Bucklebury" }
},
{
"left" : { "gameId" : 2, "id" : 3, "player" : "Fred" },
"right" : { "id" : 2, "field" : "Rushock Bog" }
},
...
]
Вероятно, вам нужно применить zip к этому результату. Для большей ясности, мы используем without для удаления id поля из таблицы games (оно конфликтует с id полем таблицы players и в любом случае избыточно), и отсортируем его по полям games.
r.table("players")
.eqJoin("game_id", r.table("games"))
.without(r.hashMap("right", "id"))
.zip()
.orderBy("game_id")
.run(conn);
[
{ "field": "Little Delving", "gameId": 1, "id": 5, "player": "Earnest" },
{ "field": "Little Delving", "gameId": 1, "id": 1, "player": "George" },
{ "field": "Rushock Bog", "gameId": 2, "id": 3, "player": "Fred" },
{ "field": "Rushock Bog", "gameId": 2, "id": 4, "player": "Marie" },
{ "field": "Bucklebury", "gameId": 3, "id": 6, "player": "Beth" },
{ "field": "Bucklebury", "gameId": 3, "id": 2, "player": "Agatha" }
]
Дополнительную информацию см. на странице Объединение таблиц в RethinkDB.
Пример: Используйте вторичный индекс в правой таблице вместо первичного ключа. Если у игроков есть вторичный индекс по городам, мы можем получить список арен с игроками в одном районе.
r.table("players").eqJoin("city_id", r.table("arenas"))
.optArg("index", "city_id").run(conn);
Пример: Используйте вложенный ключ в качестве поля объединения. Предположим, что документы в таблице players имеют структуру:
{ "id": 1, "player": "George", "game": {"id": 1} },
{ "id": 2, "player": "Agatha", "game": {"id": 3} },
...
Просто укажите поле, используя лямбда-выражение вместо строки.
r.table("players").eqJoin(
row -> row.g("game").g("id"),
r.table("games")
).without(r.hashMap("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").eqJoin(
player -> player.g("favorites").nth(0),
r.table("games")
).without(
r.array(r.hashMap("left", r.array("favorites", "game_id", "id")),
r.hashMap("right", "id"))
).zip().run(conn);
[
{ "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/java/eq_join/