Spec-Zone.ru › RethinkDB ruby

Десятиминутное руководство по работе с 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/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API