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

Запуск сервера
Для более подробного ознакомления, обязательно прочитайте краткий старт.
Linux и OS X
Запустите сервер из терминала.
$ rethinkdb
Windows
Запустите сервер из командной строки Windows.
C:\Users\Slava\RethinkDB\>rethinkdb.exe
Импорт драйвера
Сначала запустите оболочку Ruby:
$ irb
Затем импортируйте драйвер RethinkDB:
require 'rethinkdb'
include RethinkDB::Shortcuts
Теперь вы можете получить доступ к командам RethinkDB через модуль r.
Открытие соединения
При первом запуске RethinkDB сервер открывает порт для клиентских драйверов (28015 по умолчанию). Давайте откроем соединение:
r.connect(:host=>"localhost", :port=>28015).repl
Команда repl — это удобный метод, который устанавливает по умолчанию соединение в вашей оболочке, так что вам не придётся передавать его команде run для выполнения запросов.
Примечание: команда
replполезна для экспериментов в оболочке, но в реальных приложениях вы должны явно передать соединение командеrun. Более подробную информацию см. в примере проекта.
Создание новой таблицы
По умолчанию RethinkDB создает базу данных test. Давайте создадим таблицу authors в этой базе данных:
r.db("test").table_create("authors").run
Результат будет:
{
:config_changes => [
<table configuration data>
],
:tables_created => 1
}
(Поле config_changes содержит метаданные о только что созданной таблице; для получения более подробной информации, прочитайте документацию по команде table_create.) Вот несколько моментов, которые следует отметить в этом запросе:
- Сначала мы выбираем базу данных
testс помощью командыdb. - Затем мы добавляем команду
table_createдля создания фактической таблицы. - Наконец, мы вызываем
runдля отправки запроса на сервер.
Все запросы ReQL следуют этой общей структуре. Теперь, когда мы создали таблицу, давайте вставим данные!
Вставка данных
Давайте вставим три новых документа в таблицу authors:
r.table("authors").insert([
{ "name"=>"William Adama", "tv_show"=>"Battlestar Galactica",
"posts"=>[
{"title"=>"Decommissioning speech", "content"=>"The Cylon War is long over..."},
{"title"=>"We are at war", "content"=>"Moments ago, this ship received..."},
{"title"=>"The new Earth", "content"=>"The discoveries of the past few days..."}
]
},
{ "name"=>"Laura Roslin", "tv_show"=>"Battlestar Galactica",
"posts"=>[
{"title"=>"The oath of office", "content"=>"I, Laura Roslin, ..."},
{"title"=>"They look like us", "content"=>"The Cylons have the ability..."}
]
},
{ "name"=>"Jean-Luc Picard", "tv_show"=>"Star Trek TNG",
"posts"=>[
{"title"=>"Civil rights", "content"=>"There are some words I've known since..."}
]
}
]).run
Мы должны получить объект, похожий на этот:
{
"unchanged"=>0,
"skipped"=>0,
"replaced"=>0,
"inserted"=>3,
"generated_keys"=>[
"71879b1b-e81e-48c4-a42c-f41f83d7133e",
"f0a93ef3-cec0-4364-bde6-f664088b9e77",
"f601347b-95a1-4ffe-83bd-ed04d4a3cce5"
],
"errors"=>0,
"deleted"=>0
}
Сервер должен вернуть объект без ошибок и с тремя вставленными документами. Мы не указывали первичные ключи (по умолчанию каждая таблица использует атрибут id для первичных ключей), поэтому RethinkDB сгенерировал их для нас. Сгенерированные ключи возвращаются через атрибут generated_keys.
Вот несколько моментов, которые следует отметить в этом запросе:
- Каждое соединение устанавливает базу данных по умолчанию для использования в течение всего его жизненного цикла (если вы не указываете её в
connect, база данных по умолчанию устанавливается вtest). Таким образом, мы можем опустить командуdb('test')в нашем запросе. Мы больше не будем явно указывать базу данных, но если вы хотите добавить командуdbв начало ваших запросов, это не повлияет на результат. - Команда
insertпринимает один документ или массив документов, если вы хотите выполнить пакетную вставку. В этом запросе мы используем массив вместо выполнения трёх отдельных командinsertдля каждого документа.
Извлечение документов
Теперь, когда мы вставили данные, давайте посмотрим, как мы можем запросить базу данных!
Все документы в таблице
Чтобы извлечь все документы из таблицы authors, мы можем просто выполнить запрос r.table('authors'):
cursor = r.table("authors").run
cursor.each{|document| p document}
Запрос возвращает три ранее вставленных документа, вместе со сгенерированными значениями id.
Поскольку таблица может содержать большое количество документов, база данных возвращает объект курсора. Когда вы итерируетесь по курсору, сервер будет отправлять документы клиенту порциями по мере запроса. Курсор — это итерируемый объект Ruby, поэтому вы можете пройтись по всем результатам с помощью простого цикла for.
Фильтрация документов по условию
Давайте попробуем извлечь документ, где атрибут name имеет значение William Adama. Мы можем использовать условие для фильтрации документов, добавив команду filter в конец запроса:
cursor = r.table("authors").filter{|author| author["name"].eq("William Adama") }.run
cursor.each{|document| p document}
Этот запрос возвращает курсор с одним документом — записью о Уильяме Адаме. Команда filter оценивает заданное условие для каждой строки в таблице и возвращает только соответствующие строки. Вот новые команды, которые мы использовали для построения условия выше:
-
authorотносится к текущему посещаемому документу. -
author['name']относится к значению поляnameпосещаемого документа. - Команда
eqвозвращаетtrueесли два значения равны (в данном случае полеnameи строкаWilliam Adama).
Давайте снова используем filter для извлечения всех авторов, у которых более двух публикаций:
cursor = r.table("authors").filter{|author| author["posts"].count > 2}.run
cursor.each{|document| p document}
В этом случае мы используем предикат, который возвращает true только если длина массива в поле posts больше двух. Этот предикат содержит две команды, которые мы еще не видели:
- Команда
countвозвращает размер массива. - Оператор
>перегружен драйвером RethinkDB для выполнения на сервере. Он возвращаетTrueесли значение больше определённого значения (в данном случае, если количество публикаций больше двух).
Извлечение документов по первичному ключу
Мы также можем эффективно извлекать документы по их первичному ключу с помощью команды get. Мы можем использовать один из идентификаторов, сгенерированных в предыдущем примере:
r.db('test').table('authors').get('7644aaf2-9928-4231-aa68-4e65e31bf219').run
Поскольку первичные ключи уникальны, команда get возвращает один документ. Таким образом, мы можем извлечь документ напрямую, не перебирая курсор.
Узнайте больше о том, как RethinkDB может эффективно извлекать документы с помощью вторичных индексов.
Потоки в реальном времени
Не стесняйтесь пропустить этот раздел, если пока не хотите изучать потоки в реальном времени. Вы всегда можете вернуться и начать поток позже.
RethinkDB меняет традиционную архитектуру базы данных, открывая новый интересный доступ — вместо опроса о изменениях, разработчик может указать RethinkDB на непрерывную отправку обновлённых результатов запроса в приложения в реальном времени.
Чтобы начать поток, откройте новый терминал и откройте новое соединение RethinkDB. Затем выполните следующий запрос:
cursor = r.table("authors").changes.run
cursor.each{|document| p document}
Теперь вернитесь в первый терминал. В следующих двух разделах мы будем обновлять и удалять некоторые документы. По мере выполнения этих команд поток будет отправлять уведомления в вашу программу. Приведенный выше код выведет следующие сообщения во второй терминал:
{
"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.
Обновление документов
Давайте обновим все документы в таблице authors и добавим поле type для обозначения того, что все авторы до сих пор вымышленные:
r.table("authors").update({"type"=>"fictional"}).run
Поскольку мы изменили три документа, результат должен выглядеть так:
{
"unchanged"=>0,
"skipped"=>0,
"replaced"=>3,
"inserted"=>0,
"errors"=>0,
"deleted"=>0
}
Обратите внимание, что мы сначала выбрали каждого автора в таблице, а затем добавили команду update в конец запроса. Мы также могли бы обновить подмножество документов, отфильтровав таблицу сначала. Давайте обновим запись Уильяма Адама, чтобы указать, что его звание адмирал:
r.table("authors").
filter{|author| author["name"].eq("William Adama")}.
update({"rank"=>"Admiral"}).run
Поскольку мы обновили только один документ, мы получим такой объект:
{
"unchanged"=>0,
"skipped"=>0,
"replaced"=>1,
"inserted"=>0,
"errors"=>0,
"deleted"=>0
}
Команда update позволяет изменять существующие поля в документе, а также значения внутри массивов. Предположим, археологи из Звёздного пути обнаружили новую речь Жана-Люка Пикара, которую мы хотели бы добавить к его публикациям:
r.table('authors').filter{|author| author["name"].eq("Jean-Luc Picard")}.
update{|author| {"posts"=>author["posts"].append({
"title"=>"Shakespeare",
"content"=>"What a piece of work is man..."})
}}.run
После обработки этого запроса RethinkDB добавит дополнительную публикацию в документ Жана-Люка Пикара.
Просмотрите справочник по API для получения многих других операций с массивами, доступных в RethinkDB.
Удаление документов
Предположим, мы хотим обрезать нашу базу данных и удалить каждый документ с менее чем тремя публикациями (извините, Лора и Жан-Люк):
r.table("authors").
filter{ |author| author["posts"].count < 3 }.
delete.run
Поскольку у нас есть два автора с менее чем двумя публикациями, результат выглядит так:
{
"unchanged"=>0,
"skipped"=>0,
"replaced"=>0,
"inserted"=>0,
"errors"=>0,
"deleted"=>2
}
Узнать больше
Хотите продолжить изучение? Погрузитесь в документацию:
- Прочитайте введение в RQL, чтобы глубже изучить концепции ReQL.
- Узнайте, как использовать map-reduce в RethinkDB.
- Узнайте, как использовать соединения таблиц в RethinkDB.
- Перейдите к справочнику и просмотрите десятки примеров общих запросов RethinkDB.
Примечание: Драйвер RethinkDB для Ruby поддерживает асинхронные подключения с использованием EventMachine. Прочитайте документацию по асинхронным подключениям для получения дополнительной информации.
© RethinkDB contributors
Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
https://rethinkdb.com/docs/guide/ruby/