Десятиминутное руководство по RethinkDB и Java
Прежде чем начать:
- Убедитесь, что вы установили RethinkDB — это займет всего минуту!
- Также убедитесь, что вы установили драйвер для Java.
- Прочитайте краткое руководство (30 секунд).

Запуск сервера
Для более подробного ознакомления обязательно прочитайте краткое руководство.
Linux и OS X
Запустите сервер из терминала.
$ rethinkdb
Windows
Запустите сервер из командной строки Windows.
C:\Users\Slava\RethinkDB\>rethinkdb.exe
Импорт драйвера
Вы можете использовать драйверы из Java следующим образом:
import com.rethinkdb.RethinkDB;
import com.rethinkdb.gen.exc.ReqlError;
import com.rethinkdb.gen.exc.ReqlQueryLogicError;
import com.rethinkdb.model.MapObject;
import com.rethinkdb.net.Connection;
public static final RethinkDB r = RethinkDB.r;
Теперь вы можете получить доступ к командам RethinkDB через класс r.
Открытие соединения
При первом запуске RethinkDB сервер открывает порт для клиентских драйверов (по умолчанию 28015). Давайте откроем соединение:
Connection conn = r.connection().hostname("localhost").port(28015).connect();
Переменная conn теперь инициализирована, и мы можем выполнять запросы.
Создание новой таблицы
По умолчанию RethinkDB создаёт базу данных test. Давайте создадим таблицу authors в этой базе данных:
r.db("test").tableCreate("authors").run(conn);
Результат будет (в формате JSON):
{
"config_changes": [
<table configuration data>
],
"tables_created": 1
}
(Поле config_changes содержит метаданные о только что созданной таблице; для получения более подробной информации прочитайте о команде tableCreate.) Следует обратить внимание на несколько моментов в этом запросе:
- Во-первых, мы выбираем базу данных
testс помощью командыdb. - Затем, мы добавляем команду
tableCreateдля создания самой таблицы. - Наконец, мы вызываем
run(conn)для отправки запроса на сервер.
Все запросы ReQL следуют этой общей структуре. Теперь, когда мы создали таблицу, давайте вставим данные!
Вставка данных
Давайте вставим три новых документа в таблицу authors.
r.table("authors").insert(r.array(
r.hashMap("name", "William Adama")
.with("tv_show", "Battlestar Galactica")
.with("posts", r.array(
r.hashMap("title", "Decommissioning speech")
.with("content", "The Cylon War is long over..."),
r.hashMap("title", "We are at war")
.with("content", "Moments ago, this ship received..."),
r.hashMap("title", "The new Earth")
.with("content", "The discoveries of the past few days...")
)
),
r.hashMap("name", "Laura Roslin")
.with("tv_show", "Battlestar Galactica")
.with("posts", r.array(
r.hashMap("title", "The oath of office")
.with("content", "I, Laura Roslin, ..."),
r.hashMap("title", "They look like us")
.with("content", "The Cylons have the ability...")
)
),
r.hashMap("name", "Jean-Luc Picard")
.with("tv_show", "Star Trek TNG")
.with("posts", r.array(
r.hashMap("title", "Civil rights")
.with("content", "There are some words I've known since...")
)
)
)).run(conn);
В ответ мы должны получить объект, похожий на этот:
{
"unchanged": 0,
"skipped": 0,
"replaced": 0,
"inserted": 3,
"generated_keys": [
"7644aaf2-9928-4231-aa68-4e65e31bf219",
"064058b6-cea9-4117-b92d-c911027a725a",
"543ad9c8-1744-4001-bb5e-450b2565d02c"
],
"errors": 0,
"deleted": 0
}
Сервер должен вернуть объект без ошибок и с тремя вставленными документами. Мы не указали первичные ключи (по умолчанию каждая таблица использует атрибут id для первичных ключей), поэтому RethinkDB сгенерировал их для нас. Сгенерированные ключи возвращаются через атрибут generated_keys.
Несколько моментов для рассмотрения в этом запросе:
- Каждое подключение устанавливает базу данных по умолчанию для использования в течение всего срока его действия (если вы не указываете её в
connect, база данных по умолчанию устанавливается вtest). Таким образом, мы можем опустить командуdb('test')в нашем запросе. Мы не будем явно указывать базу данных в дальнейшем, но если вы хотите добавлять командуdbперед своими запросами, это не навредит. - Команда
insertпринимает один документ или массив документов, если вы хотите выполнять вставки по частям. В этом запросе мы используем массив вместо выполнения трёх отдельных командinsertдля каждого документа.
Извлечение документов
Теперь, когда мы вставили данные, давайте посмотрим, как можно запросить базу данных!
Все документы в таблице
Чтобы извлечь все документы из таблицы authors, мы можем просто выполнить запрос r.table("authors").
Cursor cursor = r.table("authors").run(conn);
for (Object doc : cursor) {
System.out.println(doc);
}
Результатом является массив из трёх ранее вставленных документов вместе со сгенерированными значениями id.
Поскольку таблица может содержать большое количество документов, база данных возвращает объект-курсор. При итерации по курсору сервер будет отправлять документы клиенту порциями по мере их запроса. У нас в примере только три документа, поэтому мы можем безопасно извлечь все документы сразу. Функция toList автоматически итерируется по курсору и помещает документы в список Java.
Фильтрация документов по условию
Давайте попробуем извлечь документ, где атрибут name имеет значение William Adama. Мы можем использовать условие для фильтрации документов, добавив команду filter в конец запроса:
Cursor cursor = r.table("authors").filter(row -> row.g("name").eq("William Adama")).run(conn);
for (Object doc : cursor) {
System.out.println(doc);
}
Этот запрос возвращает курсор с одним документом — записью о Уильяме Адаме. Команда filter оценивает указанное условие для каждой строки в таблице и возвращает только соответствующие строки. Вот новые команды, которые мы использовали для построения условия выше:
-
rowотносится к документу, который сейчас посещается. -
row.g("name")относится к значению поляnameпосещаемого документа. - Команда
eqвозвращаетtrueесли два значения равны (в данном случае, полеnameи строкаWilliam Adama).
Давайте используем filter снова, чтобы получить всех авторов, у которых более двух постов:
Cursor cursor = r.table("authors").filter(row -> row.g("posts").count().gt(2)).run(conn);
for (Object doc : cursor) {
System.out.println(doc);
}
В этом случае мы используем предикат, который возвращает true только если длина массива в поле posts больше двух. Этот предикат содержит две команды, которые мы ещё не видели:
- Команда
countвозвращает размер массива. - Команда
gtвозвращаетtrueесли значение больше указанного значения (в данном случае, если количество постов больше двух).
Извлечение документов по первичному ключу
Мы также можем эффективно извлекать документы по их первичному ключу, используя команду get. Мы можем использовать один из идентификаторов, сгенерированных в предыдущем примере:
r.db("test").table("authors").get("7644aaf2-9928-4231-aa68-4e65e31bf219").run(conn);
Поскольку первичные ключи уникальны, команда get возвращает один документ. Таким образом, мы можем извлечь документ напрямую, не преобразуя курсор в массив.
Узнайте больше о том, как RethinkDB может эффективно извлекать документы с помощью вторичных индексов.
Потоки в реальном времени
Вы можете пропустить этот раздел, если пока не хотите изучать потоки в реальном времени. Вы всегда можете вернуться и начать поток позже.
RethinkDB переворачивает традиционную архитектуру баз данных, раскрывая новый интересный механизм доступа — вместо опроса изменений разработчик может указать RethinkDB на постоянную отправку обновлённых результатов запроса в приложения в реальном времени.
Чтобы начать поток, скопируйте и выполните следующий запрос в окне терминала:
import com.rethinkdb.RethinkDB;
import com.rethinkdb.net.Connection;
import com.rethinkdb.net.Cursor;
public static final RethinkDB r = RethinkDB.r;
Connection conn = r.connection().hostname("localhost").port(28015).connect();
Cursor cursor = r.table("authors").changes().run(conn);
for (Object doc : cursor) {
System.out.println(doc);
}
Приведённый выше код начнёт с таких сообщений:
{
"new_val": {
"id": "1d854219-85c6-4e6c-8259-dbda0ab386d4",
"name": "Laura Roslin",
"posts": [...],
"tv_show": "Battlestar Galactica",
"type": "fictional"
},
"old_val": {
"id": "1d854219-85c6-4e6c-8259-dbda0ab386d4",
"name": "Laura Roslin",
"posts": [...],
"tv_show": "Battlestar Galactica"
}
}
RethinkDB будет уведомлять вашу программу обо всех изменениях в таблице authors и будет включать старое и новое значение каждого изменённого документа. См. страницу документации changefeeds для получения более подробной информации о том, как использовать потоки в реальном времени в RethinkDB.
В следующих двух разделах мы будем обновлять и удалять некоторые документы. Для этого мы будем использовать JavaScript в Data Explorer. Откройте консоль администрирования RethinkDB в вашем веб-браузере и нажмите «Data Explorer».
Обновление документов
Давайте обновим все документы в таблице authors и добавим поле type для того, чтобы отметить, что все авторы до сих пор являются вымышленными:
r.table("authors").update(r.hashMap("type", "fictional")).run(conn);
Поскольку мы изменили три документа, результат должен выглядеть так:
{
"unchanged": 0,
"skipped": 0,
"replaced": 3,
"inserted": 0,
"errors": 0,
"deleted":0
}
Обратите внимание, что мы сначала выбрали всех авторов в таблице, а затем добавили команду update в конец запроса. Мы также могли обновить подмножество документов, предварительно отфильтровав таблицу. Давайте обновим запись Уильяма Адама, чтобы отметить его звание — адмирал:
r.table("authors").filter(
row -> row.g("name").eq("William Adama")
).update(r.hashMap("rank", "Admiral")).run(conn);
Поскольку мы обновили только один документ, мы получим такой объект:
{
"unchanged": 0,
"skipped": 0,
"replaced": 1,
"inserted": 0,
"errors": 0,
"deleted": 0
}
Команда update позволяет изменять существующие поля в документе, а также значения внутри массивов. Предположим, археологи Star Trek обнаружили новую речь Жана-Люка Пикара, которую мы хотели бы добавить к его постам:
r.table("authors").filter(
row -> row.g("name").eq("Jean-Luc Picard")
).update(
r.hashMap("posts", row -> row.g("posts")
.append(r.hashMap("title", "Shakespeare")
.with("content", "What a piece of work is man...")))
).run();
После обработки этого запроса RethinkDB добавит дополнительный пост к документу Жана-Люка Пикара.
Просмотрите справочник API для получения более подробной информации о многих других операциях с массивами, доступных в RethinkDB.
Удаление документов
Предположим, мы хотим обновить нашу базу данных и удалить каждый документ с менее чем тремя постами (извините, Лора и Жан-Люк):
r.table("authors").filter(row -> row.g("posts").count().lt(3)).delete().run(conn);
Поскольку у нас есть два автора с менее чем двумя постами, результатом является:
{
"unchanged": 0,
"skipped": 0,
"replaced": 0,
"inserted": 0,
"errors": 0,
"deleted": 2
}
Дополнительная информация
Хотите продолжить обучение? Ознакомьтесь с документацией:
- Прочитайте введение в RQL, чтобы углубиться в концепции ReQL.
- Узнайте, как использовать map-reduce в RethinkDB.
- Узнайте, как использовать соединения таблиц в RethinkDB.
- Перейдите к справочнику и просмотрите десятки примеров распространённых запросов RethinkDB.
© RethinkDB contributors
Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
https://rethinkdb.com/docs/guide/java/