Статьи

RethinkDB в рубине

rethinkdb

Вы, вероятно, слышали о множестве баз данных NoSQL: Redis, MongoDB, Cassandra и т. Д., Которые предлагают множество различных преимуществ и имеют ряд недостатков. Если вы создаете новое приложение, очень важно выбрать базу данных, которая соответствует вашим потребностям. В этой статье мы рассмотрим RethinkDB, рассмотрим, как настроить RethinkDB, как он вписывается в ландшафт NoSQL и как его использовать в Ruby.

Почему RethinkDB?

RethinkDB — это хранилище документов JSON. Это означает, что он позволяет вам хранить кучу документов JSON и затем запрашивать их. Оказывается, RethinkDB — не единственное доступное хранилище документов. Даже не близко. Даже когда проект RethinkDB был запущен, уже было множество вариантов для тех, кто ищет базу данных NoSQL. Итак, какой смысл изучать еще одну базу данных? Проще говоря, RethinkDB сочетает в себе некоторые из лучших возможностей своих конкурентов и предоставляет довольно убедительный набор преимуществ.

Один из его ближайших родственников — MongoDB. Mongo быстро завоевала популярность благодаря своей ориентации на продуктивность разработчиков: в Mongo невероятно легко начать создавать документы и запрашивать их. К сожалению, у Mongo были довольно серьезные проблемы с масштабированием . Конечно, некоторые из этих проблем возникают из-за плохой практики развертывания, но не все поднятые проблемы являются необоснованными. Но Mongo определенно прибавил продуктивности разработчиков. С другой стороны, у нас есть базы данных, такие как Riak, для которых не так весело писать код, но в целом они довольно хорошо масштабируются без огромных усилий со стороны команды Dev Ops. RethinkDB пытается посередине этого «компромисса» (кажется, нет реальной причины для того, чтобы это было компромиссом): он пытается обеспечить простоту использования в стиле монго, сохраняя при этом людей Dev Ops счастливый.

Начиная

Хорошо, давайте на самом деле получим себе копию RethinkDB, чтобы мы могли начать ее использовать. К счастью, у них есть хорошая страница установки, которая фактически говорит нам, что делать. Обратите внимание, что Windows в настоящее время официально не поддерживается; требуется * nix-подобная система (Mac OS X в порядке). Если вы используете OS X, Homebrew — это то, что вам нужно:

brew update && brew install rethinkdb

Для популярных серверных дистрибутивов Linux (например, Ubuntu, CentOS, Debian) RethinkDB предоставляет хорошие двоичные файлы. Если вы не попадаете ни в одну из обычных групп, то вы можете собрать из исходного кода, который вы можете получить копию:

 wget http://download.rethinkdb.com/dist/rethinkdb-1.16.2-1.tgz

Чтобы проверить, правильно ли установлен rethinkdb, и запустите его:

 rethinkdb

Чтобы увидеть (действительно приятный на вид) административный интерфейс, 127.0.0.1:8080r.dbCreate('testdb')
r.db('testdb').tableCreate('test_table')
Отсюда вы можете посмотреть текущее состояние «кластера» (который в настоящее время состоит из одного сервера). Мы также можем запустить несколько запросов, перейдя на вкладку «Проводник данных» .

data_explorer

Редактор запросов действительно удобен; попробуйте ввести:

 gem install rethinkdb

Это создает базу данных с именем ‘testdb’ и таблицу с именем ‘test table’ в пределах ‘test db’. ReQL, язык запросов RethinkDB, на самом деле не является особым языком, который вы должны изучать, или особым набором объектов JSON, которые вы должны соединить. Вместо этого он состоит из вызовов функций на выбранном вами языке. В настоящее время существуют официальные драйверы для Ruby, Python и Node. Давайте посмотрим, как использовать драйвер Ruby.

Ruby Driver

Прежде всего, нам нужно получить драгоценный камень:

 require 'rethinkdb'
include RethinkDB::Shortcuts

conn = r.connect(:host => "localhost", :port => 28015)
r.db("testdb").table_create("people").run(conn)

Давайте создадим еще одну таблицу внутри базы данных «testdb», которую мы создали ранее:

 include RethinkDB::Shortcuts

Запуск этого должен создать таблицу, которую мы хотим. Давайте разберем некоторые важные строки:

 r

Эта строка позволяет использовать r = RQL.new Просто делает немного приятнее написание кода запроса. Если вы не хотите использовать ярлыки, вы можете создать собственную ссылку на RethinkDB:

 r.connect

Далее мы устанавливаем соединение с помощью вызова conn = r.connect(:host => "localhost", :port => 28015)

 r.db("testdb").table_create("people").run(conn)

Здесь идет фактический запрос:

 .db("testdb")

Эта строка представляет довольно важную часть DSL запроса RethinkDB. Как правило, вызовы могут быть объединены в цепочку, поскольку все они возвращают объекты RQL (если у вас есть некоторый опыт работы с Javascript, вам, вероятно, понравится эта идея). С помощью .table_create("people") .run(conn)pry Но на самом деле ничего этого не происходит, пока мы не irb

Итак, давайте предположим, что вы выполнили этот запрос и таблица была создана. Как мы можем это проверить? Мы не хотим создавать другой файл, чтобы просто перечислить таблицы в базе данных, поэтому мы будем использовать Ruby REPL ( r.connect(:host => "localhost", :port => 28015).repl.repl Сначала мы хотим установить соединение:

 r.db('testdb').table_list.run

Обратите внимание на ["people", "test_table"] Это делает так, что RQL будет предполагать, что вы будете использовать это соединение по умолчанию. Это значительно облегчает работу с REPL. Давайте проверим запрос, который даст нам список таблиц внутри «testdb»:

 require 'rethinkdb'
include RethinkDB::Shortcuts

table = "people"
db = "testdb"

begin
    conn = r.connect(:host => "localhost", :port => 28015)
rescue Exception => err
    puts "Cannot connect to RethinkDB at localhost:28015"
end

begin
    r.db(db).table_create(table).run(conn)
rescue RethinkDB::RqlRuntimeError => err
    puts "Error occurred in creating #{table} table within #{db}"
    puts err
end

begin
    puts "Tables inside #{db}: ", r.db(db).table_list().run(conn)
rescue RethinkDB::RqlRuntimeError => err
    puts err
ensure
    conn.close
end

Это должно вернуть что-то вроде:

 ensure

Хорошо круто Но ждать. В примере, который мы только что выполнили, многое отсутствует. Что, если что-то пойдет не так?

Обработка исключений

Материал работает неправильно при работе с базой данных все время. Мы всегда хотим быть уверены, что наш код может противостоять или, по крайней мере, реагировать на проблемы, возникающие при работе с RethinkDB. Давайте перепишем наш предыдущий пример немного по-другому:

 people

По сути, мы обернули все в исключения, а также добавили условие sure, чтобы мы могли закрыть соединение с RethinkDB. Вы можете думать об исключениях RethinkDB как о любом другом исключении, за исключением того, что они, как правило, действительно важны. Поэтому, если вы решите игнорировать (то есть не спасать) данное исключение, полностью понимайте его последствия.

документы

Хорошо, как мы на самом деле положить вещи в наш стол? Как вы помните, RethinkDB — это хранилище документов, а это означает, что он хранит объекты JSON. Давайте поместим человека в нашу таблицу сотрудников (я представлю форму REPL, но для ее перемещения в код просто необходимо передать объект подключения для run

 res = r.db("testdb").table("people").insert({:name => "Dhaivat"}).run

Это должно было вернуть что-то вроде:

 {"deleted"=>0, "errors"=>0, "generated_keys"=>["417b5b3e-c107-4577-acfc-cd11a76f9174"], "inserted"=>1, "replaced"=>0, "skipped"=>0, "unchanged"=>0}

Обратите внимание, что это хеш Ruby, поэтому довольно ясно, как мы получим значения из этой структуры (например, res['generated_keys'] Есть несколько важных частей структуры. Прежде всего, generated_keys Во-вторых, положительное значение для inserted Чтобы вставить несколько документов одним запросом, просто вставьте их в список и передайте их в .insert Одним из наиболее важных моментов здесь является то, что RethinkDB не должно волновать, какова структура ваших документов. В отличие от MySQL (и других RDMBS), где вы указываете структуру таблицы, RethinkDB позволяет вам просто делать это каждый раз, когда вы помещаете вещи в свою базу данных. Это означает, что либо ваш взаимодействующий с БД код должен быть очень осторожным, либо вы должны следить за тем, чтобы старые структуры не задерживались слишком долго. В качестве упражнения добавьте документы для «Джона», «Джейн» и «Джорджа».

Вставить документы довольно легко. Как насчет их возвращения снова? Мы можем получить итератор, указывающий на определенную точку в таблице. Если мы хотим перебрать все объекты в таблице:

 itr = r.db('testdb').table('people').run
itr.each do |document|
    p document
end

Что, если мы хотим фильтровать в соответствии с некоторыми ограничениями? Все, что нам нужно сделать, это создать запрос, который определяет фильтр:

 itr = r.db('testdb').table('people').filter {|person| person['name'].eq("John")}.run
itr.each do |document|
    p document
end

Здесь мы используем filter {|person| person['name'].eq("John")} .eq Обратите внимание, что мы проводим сравнение на равенство с ==r.db('testdb').table('people').
filter {|person| person['name'].eq("John")}.
delete.run
По сути, любое логическое условие, которое мы можем приготовить, может использоваться как часть фильтра. Мы можем удалить документы аналогичным образом:

 id

Мы можем легко запросить на основе itr = r.db('testdb').table('people')
itr.get(id)

 itr.update({name: "Dhaivat Pandya"}).run

Обновление работает аналогично:

 itr

Какие бы документы ни повторялись с помощью "Dhaivat Pandya"

Примечание о RQL

Если вы привыкли к SQL, вам может быть интересно, в чем смысл фильтрации, если мы уже сначала откатили всю таблицу. Ну, у нас нет. Все, что предшествует .run Короче говоря, все запросы выполняются на сервере. Мой опыт работы с RQL был довольно приятным; цепочка запросов, простота фильтрации и т. д. делают использование RQL приятным.

Завершение

Эта статья должна послужить довольно быстрым введением в RethinkDB. Но есть огромное количество вещей, которые все еще остаются нетронутыми, например, объединения таблиц, уменьшение карт и т. Д. В будущих статьях мы рассмотрим все эти интересные темы.

Оставьте любые вопросы в комментариях ниже.