Руководство за десять минут с RethinkDB и Python
Перед началом:
- Убедитесь, что вы установили RethinkDB — это займёт всего минуту!
- Убедитесь также, что вы установили драйвер Python.
- Прочитайте краткое руководство за тридцать секунд.
Начиная с версии 1.14, драйвер Python для RethinkDB поддерживает Python 2 и 3. Версии 1.13 и более ранние поддерживают только Python 2.

Запустить сервер
Для более подробного ознакомления, обязательно прочитайте краткое руководство.
Linux и OS X
Запустите сервер из терминала.
$ rethinkdb
Windows
Запустите сервер из командной строки Windows.
C:\Users\Slava\RethinkDB\>rethinkdb.exe
Импортировать драйвер
Сначала запустите оболочку Python:
$ python
Затем импортируйте драйвер RethinkDB и создайте объект RethinkDB:
from rethinkdb import RethinkDB
r = RethinkDB()
Теперь вы можете получить доступ к командам RethinkDB через объект r.
Открыть соединение
При первом запуске RethinkDB сервер открывает порт для клиентских драйверов (28015 по умолчанию). Давайте откроем соединение:
r.connect( "localhost", 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": [
"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 = r.table("authors").run()
for document in cursor:
print(document)
Запрос возвращает три ранее вставленных документа вместе с сгенерированными значениями id.
Поскольку таблица может содержать большое количество документов, база данных возвращает объект курсора. По мере итерации по курсору сервер будет отправлять документы клиенту партиями по мере запроса. Курсор — это итерируемый объект Python, поэтому вы можете пройти через все результаты с помощью простого цикла for.
Фильтр документов по условию
Давайте попробуем получить документ, где атрибут name установлен в значение William Adama. Мы можем использовать условие для фильтрации документов, прицепляя команду filter к концу запроса:
cursor = r.table("authors").filter(r.row["name"] == "William Adama").run()
for document in cursor:
print(document)
Этот запрос возвращает курсор с одним документом — записью для Уильяма Адама. Команда filter вычисляет заданное условие для каждой строки в таблице и возвращает только соответствующие строки. Вот новые команды, которые мы использовали для построения условия выше:
-
r.rowотносится к текущему посещаемому документу. -
r.row['name']относится к значению поляnameпосещаемого документа. - Оператор
==перегружен драйвером RethinkDB для выполнения на сервере. Он возвращаетTrue, если два значения равны (в данном случае, полеnameи строкаWilliam Adama).
Давайте снова воспользуемся filter для получения всех авторов, у которых более двух публикаций:
cursor = r.table("authors").filter(r.row["posts"].count() > 2).run()
for document in cursor:
print(document)
В этом случае мы используем предикат, который возвращает True только в том случае, если длина массива в поле posts больше двух. Этот предикат содержит две команды, которые мы ещё не видели:
- Команда
countвозвращает размер массива. - Оператор
>перегружен драйвером RethinkDB для выполнения на сервере. Он возвращаетTrue, если значение больше определённого значения (в этом случае, если количество публикаций больше двух).
Получить документы по первичному ключу
Мы также можем эффективно получать документы по их первичному ключу, используя команду get. Мы можем использовать один из id, сгенерированных в предыдущем примере:
r.db('test').table('authors').get('7644aaf2-9928-4231-aa68-4e65e31bf219').run()
Поскольку первичные ключи уникальны, команда get возвращает единственный документ. Таким образом, мы можем получить документ напрямую, не проходя итерацию по курсору.
Узнайте больше о том, как RethinkDB может эффективно получать документы с помощью вторичных индексов.
Потоки в реальном времени
Не стесняйтесь пропустить этот раздел, если пока не хотите изучать потоки в реальном времени. Вы всегда можете вернуться и начать поток позже.
RethinkDB изменяет традиционную архитектуру баз данных, открывая новый и интересный доступный способ — вместо опроса о изменениях, разработчик может указать RethinkDB непрерывно отправлять обновлённые результаты запроса в приложения в реальном времени.
Чтобы начать поток, откройте новый терминал и откройте новое соединение RethinkDB. Затем выполните следующий запрос:
cursor = r.table("authors").changes().run()
for document in cursor:
print(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(r.row['name'] == "William Adama").
update({"rank": "Admiral"}).run()
Поскольку мы обновили только один документ, мы получаем этот объект:
{
"unchanged": 0,
"skipped": 0,
"replaced": 1,
"inserted": 0,
"errors": 0,
"deleted": 0
}
Команда update позволяет изменять существующие поля в документе, а также значения внутри массивов. Допустим, археологи из «Звёздного пути» обнаружили новую речь Жана-Люка Пикара, которую мы хотели бы добавить в его публикации:
r.table('authors').filter(r.row["name"] == "Jean-Luc Picard").
update({"posts": r.row["posts"].append({
"title": "Shakespeare",
"content": "What a piece of work is man..."})
}).run()
После обработки этого запроса RethinkDB добавит дополнительную публикацию к документу Жана-Люка Пикара.
Просмотрите справочник API для получения многих других операций с массивами, доступных в RethinkDB.
Удалить документы
Предположим, мы хотим обрезать нашу базу данных и удалить каждый документ с менее чем тремя постами (извини, Лора и Жан-Люк):
r.table("authors").
filter( r.row["posts"].count() < 3 ).
delete().run()
Поскольку у нас есть два автора с менее чем двумя постами, результат:
{
"unchanged": 0,
"skipped": 0,
"replaced": 0,
"inserted": 0,
"errors": 0,
"deleted": 2
}
Узнать больше
Хотите продолжить обучение? Погрузитесь в документацию:
- Прочитайте введение в RQL, чтобы углубиться в понятия ReQL.
- Узнайте, как использовать map-reduce в RethinkDB.
- Узнайте, как использовать соединения таблиц в RethinkDB.
- Перейдите к сборнику рецептов и просмотрите десятки примеров общих запросов RethinkDB.
Примечание: В настоящее время драйвер Python не является потокобезопасным. Каждый поток или процесс multiprocessing должен получить собственный объект подключения.
Драйвер RethinkDB для Python поддерживает асинхронные подключения с использованием Tornado и Twisted. Подробнее читайте в документации по асинхронным подключениям.
© RethinkDB contributors
Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
https://rethinkdb.com/docs/guide/python/