Вы, вероятно, слышали о множестве баз данных 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:8080
r.dbCreate('testdb')
Отсюда вы можете посмотреть текущее состояние «кластера» (который в настоящее время состоит из одного сервера). Мы также можем запустить несколько запросов, перейдя на вкладку «Проводник данных» .
r.db('testdb').tableCreate('test_table')
Редактор запросов действительно удобен; попробуйте ввести:
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. Но есть огромное количество вещей, которые все еще остаются нетронутыми, например, объединения таблиц, уменьшение карт и т. Д. В будущих статьях мы рассмотрим все эти интересные темы.
Оставьте любые вопросы в комментариях ниже.