От переводчика: Совсем недавно узнал про эту довольно интересную базу данных и как раз наткнулся на свежую статью. На Хабре нет почти ни слова о RethinkDB, в связи с чем было решено сделать этот перевод. Добро пожаловать под кат!

image

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

RethinkDB — это open source база данных для real-time приложений. Она располагает встроенной системой уведомления об изменениях, которая беспрерывно транслирует обновления для вашего приложения. Вместо постоянного запрашивания новых данных, позвольте базе данных самой отправлять вам последние изменения. Возможность «подписываться» на потоковые обновления может сильно упростить архитектуру вашего приложения и работу с клиентами, поддерживающими постоянный коннект к вашей серверной части.

RethinkDB является безсхемным хранилищем JSON документов, но также поддерживает и некоторые особенности реляционных БД. RethinkDB также поддерживает кластеризацию, что делает её очень удобной в расширении. Вы можете настроить шардинг и копирование через встроенный веб-интерфейс. Последняя версия RethinkDB также включает в себя автоматический «fail-over» для кластеров с тремя и более серверами. (прим. переводчика: подразумевается возможность продолжения работы с БД в случае падения одного из серверов.)

Язык запросов в RethinkDB, который называется ReQL, нативно встраивается в код на том языке, на которым вы пишите своё приложение. Если, например, вы кодите на Python, то при написании запросов к БД будете использовать обычный для Python синтаксис. Каждый запрос составляется из функций, который разработчик собирает в цепочку, чтобы точно описать необходимую операцию.

Несколько слов о ReQL
RethinkDB содержит в себе таблицы, в которых хранятся традиционные JSON документы. Структура самих JSON объектов может иметь глубокую вложенность. Каждый документ в RethinkDB имеет свой основной ключ (primary key) — свойство «id» с уникальным для таблицы-родителя значением. Ссылаясь на primary key в своём запросе вы можете получить конкретный документ.

Написание ReQL запросов в приложении довольно похоже на использование API конструктора SQL запросов. Ниже, на языке JavaScript, представлен простой пример ReQL запроса для определения количества уникальных фамилий в таблице users:

r.table("users").pluck("last_name").distinct().count()

В ReQL запросе каждая функция цепочки работает с данными, полученными из предыдущей функции. Если быть точным, то порядок выполнения данного запроса таков:

  • table запрашивает определнную таблицу в базе данных
  • pluck достаёт определенное свойство (или несколько свойств) из каждой записи
  • disctinct убирает повторяющиеся значения, оставляя только по одному уникальному
  • count подсчитывает и возвращает количество полученных элементов

Традиционные CRUD операции также просты. ReQL включает в себя функцию insert, которую можно использовать для добавления новых JSON документов в таблицу:

r.table("fellowship").insert([
   { name: "Frodo", species: "hobbit" },
   { name: "Sam", species: "hobbit" },
   { name: "Merry", species: "hobbit" },
   { name: "Pippin", species: "hobbit" },
   { name: "Gandalf", species: "istar" },
   { name: "Legolas", species: "elf" },
   { name: "Gimili", species: "dwarf" },
   { name: "Aragorn", species: "human" },
   { name: "Boromir", species: "human" }
])

Функция filter достаёт документы, которые соответствуют определённым параметрам:

r.table("fellowship").filter({species: "hobbit"})

Вы можете добавлять в цепочку такие функции как update или delete, чтобы выполнить определенные операции над документами, возвращенными из filter:

r.table("fellowship").filter({species: "hobbit"}).update({species: "halfling"})

ReQL включает более 100 функций, которые можно комбинировать для достижения необходимого результата. Есть функции для управления потоками, изменения документов, агрегации, записи и т.д. Также существуют функции, «заточенные» под выполнение стандартных операций со строками, числами, метками времени и геопространственными координатами.

Существует даже команда http, которую можно использовать для получения данных из сторонних Web API. В следующем примере показано как можно использовать http для получения постов с Reddit:

r.http("http://www.reddit.com/r/aww.json")("data")("children")("data").orderBy(r.desc("score")).limit(5).pluck("score", "title", "url")

После того как посты получены, они сортируются по очкам и затем отображаются определённые свойства лучшей пятёрки постов. Используя ReQL «на полную мощность», разработчики могут выполнять действительно сложные манипуляции с данными.

Как работает ReQL

RethinkDB client libraries (далее «драйвера») отвечают за интеграцию ReQL в тот язык программирования, на котором ведется разработка приложения. Драйвера внедряют функции для всевозможных запросов, поддерживаемых базой данных. ReQL выражения расцениваются как структурированные объекты, которые похожи на абстрактное синтаксическое дерево. Но для того чтобы выполнить запрос, драйвера переводят эти объекты запроса в специальный формат "RethinkDB's JSON wire protocol format", в котором затем передаются в базу данных.

Функция run, замыкающая цепочку, переводит запрос, выполняет его на сервере и возвращает результат. Как правило вы будете передавать в эту функцию соединение с сервером, чтобы она смогла выполнить операцию. В официальных драйверах работа с соединением выполняется в ручном режиме. Это значит что вам нужно создавать соединение и закрывать его после выполнения операции.

В следующем примере показано как выполнить запрос в RethinkDB из-под Node.js с установленным драйвером ReQL для JavaScript. Этот запрос достаёт всех хафлингов (halflings) из таблицы fellowship и отображает их в консоли:

var r = require("rethinkdb");

r.connect().then(function(conn) {
return r.table("fellowship")
         .filter({species: "halfling"}).run(conn)
   .finally(function() { conn.close(); });
})
.then(function(cursor) {
return cursor.toArray();
})
.then(function(output) {
console.log("Query output:", output);
})

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

Метод connect устанавливает соединение, который затем используется функцией run. для выполнения запроса. Сам по себе запрос возвращает курсор, который является чем-то вроде открытого окошка в содержимое базы. Курсоры поддерживают «ленивую выборку» (lazy fetching) и предлагают эффективные способы перебора больших объёмов данных. В примере выше я просто решил конвертировать содержимое курсора в массив, так как размер результата относительно мал.

Несмотря на то, что ReQL запросы пишутся в вашем приложении как обычный код, они выполняются на сервере БД и возвращают полученные результаты. Интеграция настолько бесшовна, что новички часто путаются в каком месте кода граница между их приложением и работой с БД.

ReQL цепочки и интеграция в различные языки значительно увеличивают возможность повторного использования кода и отделения частых операций. Так как запросы написаны на языке приложения, инкапсуляция подвыражений запроса в переменные и функции становится очень простой и удобной. Например, данная JavaScript функция обобщает пагинацию, возвращая ReQL выражение, которое уже будет содержать указанные значения:

function paginate(table, index, limit, last) {
   return (!last ? table : table
      .between(last, null, {leftBound: "open", index: index}))
   .orderBy({index: index}).limit(limit)
}

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

Многие более продвинутые особенности ReQL, такие как вторичные индексы, соединение таблиц и использование анонимных функций, остаются за пределами этой статьи. Тем не менее, при желании вы можете ознакомиться с ними на странице документации ReQL API.

Создание real-time веб-приложений с помощью changefeeds

RethinkDB обладает встроенной системой уведомления об изменениях, которая значительно упрощает разработку приложений, работающих в режиме реального времени. Если вы вставите функцию changes в конец цепочки, то в качестве результата запроса будет запущен беспрерывный поток, отражающий все происходящие изменения. Такие потоки называются changefeeds (далее «ченджфид»).

Привычные нам запросы к БД хорошо подходят к традиционной веб-модели «запрос/ответ». Однако, постоянное опрашивание сервера не практично для real-time приложений, использующих постоянное подключение к серверу или потоковую передачу данных. Ченджфиды предоставляют альтернативу обычному опрашиванию, а именно возможность постоянной подачи обновленных результатов в приложение.

Вы можете прикрепить ченджфид прямо к таблице, чтобы отслеживать любые изменения её содержимого. Вы также можете использовать ченджфиды с более сложными запросами, чтобы получать обновления только необходимых вам данных. Например, можно прикрепить ченджфид к запросу, в котором используются функции orderBy и limit, чтобы создать динамическую таблицу рекордов для многопользовательской игры:

r.table("players").orderBy({index: r.desc("score")}).limit(5).changes()

Игроки сортируются по очкам и затем выводится первая пятёрка. Как только появятся какие-то изменения в этой пятёрке лидеров, ченджфид отправит вам обновлённые данные. Даже если игрок, который изначально не был в ТОП-5, наберёт достаточно очков и вытеснит другого игрока из пятёрки — ченджфид сообщит об этом и передаст все необходимые данные для обновления списка.

Ченджфид отправляет не только новое значение записи, но и предыдущее, позволяя нам сравнивать результаты. Если какая-то из записей удаляется, то её новое значение будет равно null. Также как и для только появившейся, новой записи, старое значение будет равно null. Кстати, вы можете добавлять в цепочку другие операции после changes, если необходимы какие-то манипуляции с поступающими данными.

Когда вы выполняете запрос с командой changes, — будет возвращён курсор, который останется открытым навсегда (помните про окошко, да?). Курсор будет отображать новые изменения как только они становятся доступными. Ниже можно увидеть пример, показывающий как можно получать обновления из ченджфида в Node.js:

r.connect().then(function(conn) {
   return r.table("data").changes().run(conn);
})
.then(function(cursor) {
   cursor.each(function(err, item) {
         console.log(item);
   });
});

Работа курсора ченджфида выполняется в фоновом режиме, а значит ваше приложения не блокируется. В исконно асинхронных окружениях, таких как Node.js, вам вовсе не нужно принимать какие-то дополнительные меры для корректной работы. Если вы работаете с другими языками, то вероятно понадобится установка фреймворков для асинхронного кода, или же ручное внедрение потоков. Официальные RethinkDB драйвера для Python и Ruby поддерживают такие популярные и широко используемые фреймворки как Tornado и EventMachine.

На данный момент, команда changes работает с функциями get, between, filter, map, orderBy, min и max. Поддержка других видов запросов запланирована на будущее.

При создании real-time веб-приложения с помощью RethinkDB, можно использовать WebSockets для трансляции обновлений на front-end. А такие библиотеки как Socket.io удобны в использовании и упростят этот процесс.

Ченджфиды особенно полезны для приложений, рассчитанных на горизонтальное расширение. Когда вы распределяете нагрузку между несколькими экземплярами своего приложения, то обычно прибегаете к помощи дополнительных механизмов, таких как очереди сообщений или in-memory db, чтобы распространить обновления на все сервера. RethinkDB переносит этот функционал на уровень вашего приложения, уплощая его архитектуру и избавляя вас от необходимости использования дополнительной инфраструктуры. Каждый экземпляр приложения подключается непосредственно к БД для получения новых изменений. Как только обновления доступны, каждый сервер транслирует их соответствующим WebSocket клиентам.

В дополнение к real-time приложениям, ченджфиды могут значительно упростить внедрение мобильных push-уведомлений и другого подобного функционала. Ченджфиды представляют событийно-ориентированную модель взаимодействия с базой данных и эта модель во многих случаях оказывается полезной.

Масштабирование и управление кластером RethinkDB

RethinkDB является распределённой базой данных, нацеленной на кластеризацию и простое расширение. Чтобы добавить новый сервер к кластеру, достаточно просто запустить его из командной строки с опцией --join и указанием адреса уже существующего сервера. Если у вас в распоряжении кластер с несколькими серверами, вы можете настраивать шардинг и копирование индивидуально для каждой таблицы. Любые настройки и особенности, работающие на одном экземпляре БД будут работать в точности также и на кластере.

Сервер RethinkDB включает в себя также и веб-интерфейс администратора, открыть который вы можете прямо в браузере. С помощью этого интерфейса можно легко управлять и мониторить работу кластера. Вы даже можете настроить шардинг и копирование в несколько кликов.

RethinkDB позволяет применять ReQL-подход для конфигурации кластера, который идеально подходит для тонкой настройки и автоматизации. ReQL включается в себя простую функцию reconfigure, которую можно привязать к таблице для установки настроек шардинга. Также кластер предоставляет большую часть внутренней информации о своём состоянии и настройках через набор специальных таблиц в RethinkDB. Вы можете делать запросы к системным таблицам, чтобы изменять настройки или получать информацию для мониторинга. Практически весь функционал, предоставляемый через веб-интерфейс, построен на ReQL API.

Вы даже можете использовать ченджфиды в связке с ReQL monitoring API, чтобы получать поток данных о сервере. Например, можно было бы создать свой инструмент для мониторинга, который прикрепляет ченджфид к системной таблице со статистикой и в режиме реального времени передаёт данные для построения графика нагрузки чтения/записи.

RethinkDB 2.1, вышедшая недавно, имеет встроенную поддержку автоматического fail-over'a. Новый функционал улучшает доступность кластеров и уменьшает риск падения сервера БД. Если основной (primary) сервер неисправен, то остальные, вторичные рабочие сервера «выбирают» новый primary, который будет выполнять эту роль до тех пор, пока неисправный сервер заработает или будет удалён из кластера.
Поломки железа, или перебои в работе сети теперь не влияют на доступность данных до тех пор, пока большая часть серверов находится онлайн.

Установка RethinkDB

RethinkDB работает под Linux и MacOS X. Версия для Windows находится в активной разработке и еще не доступна для загрузки. В документации RethinkDB детально описан процесс установки. Мы подготовили APT и Yum репозитории для пользователей Linux, а также установщик для OS X. Вы также можете установить RethinkDB с помощью Docker или скомпилировать исходный код с Github. Чтобы в этом разобраться, вам поможет наша 10-минутная инструкция.

Оригинал: ссылка

Комментарии (36)


  1. Suvitruf
    05.09.2015 13:25
    +7

    Она располагает встроенной системой уведомления об изменениях, которая беспрерывно транслирует обновления для вашего приложения.
    Которая неполноценна. Если у вас что-то произошло с коннектом между клиентом и ресинком, то вы не сможете потом продолжить фид с того места, где закончили. Они обещали реализовать возможность продолжить получение изменений по id фида. Давненько уже жду этой возможности.
    Функция filter достаёт документы, которые соответствуют определённым параметрам.
    И которая никогда не должна использоваться в продакшене, если вы ищете не по secondary index'ам. Лучше использовать getAll по индексам, где это возможно.


    1. Suvitruf
      05.09.2015 14:11
      +4

      Кстати, в RethinkDB нету транзакций, что порой очень печалит.


    1. Alexeyco
      06.09.2015 02:26

      Вот, кстати, интересно еще, какие дела у нее с шардингом.


      1. Suvitruf
        06.09.2015 12:03

        Ну, шардинг есть. Что конкретно хотите узнать? )


  1. beduin01
    05.09.2015 13:29
    +1

    А можно узнать о преимуществах над ArangoDB?


    1. karudo
      05.09.2015 21:55
      +14

      Вполне возможно автор до вашего комментария и не знал, что в мире есть еще, оказывается, ArangoDB. Я вот не знал. Если он действительно не знал, то как он вам расскажет о преимуществах?
      Раз вас так интересует этот вопрос, почему бы вам в нем самому не разобраться и не запилить пост на хабру с обзором ArangoDB вообще и сравненем с RethinkDB в частности?


    1. Weageoo
      06.09.2015 00:53

      Может быть во встроенной системе уведомлений об изменениях?


  1. YChebotaev
    06.09.2015 03:41

    Отличная база данных, рекомендую. Больше всего, по сравнению с остальными NoSQL базами радует наличие традиционных джоинов, легкое масштабирование, язык запросов гораздо приятнее SQL, и простота в настройке и обслуживании.
    А вот рекламируемые в статье функции по уведомлению об изменениях, на мой взгляд, далеко не главное достоинство, скорее прилепили, чтобы было, а потом сделали на этой фиче маркетинговый акцент.


    1. Suvitruf
      06.09.2015 09:15

      Не главное, но довольно приятное. У нас для некоторых вещей поверх RethinkDB настроен Redis. Без этих подписок получать изменения и обновлять данные в Редисе было бы весьма проблематично )


      1. YChebotaev
        06.09.2015 18:19

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


    1. vird
      08.09.2015 11:33

      Масштабирования по insert'ам нет. Попробуйте выжать неё больше 1000-2000 insert/sec и вы сильно удивитесь.


      1. YChebotaev
        08.09.2015 12:20

        А какая настройка durability у вас? Если hard, то ничего удивительного, а вот если soft, то хотелось бы чуть подробнее узнать о вашей установке: вы пишете в один инстанс, или в разные?


        1. vird
          08.09.2015 12:25

          Мы игрались с durability soft, hard, ssd, hdd, tmpfs. Результат один 1400 insert/sec не больше. Ядра использовать не умеет, нужно ручками стартовать несколько и объединять. Тестили на одном instance, на двух instance, объединенных в кластер. Результат — печалька, т.е. мы не получили прироста производительности при двух instance'ах (есть еще вероятность, что мы что-то неправильно настроили или как-то странно проверяли. З.ы. Мы даже не читали, просто писали. З.ы. на update'ы ситуация у него по-лучше). По ходу, оно хорошо масштабируется по ходу только на чтения и на update'ы. Кстати, даже на github были вопросы по производительности. Они подпиливают уже 2 версии как, уже гораздо лучше, было вообще 120 insert/sec.


          1. YChebotaev
            08.09.2015 12:43

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


            1. vird
              08.09.2015 12:47

              В теории должно было увеличить. На практике у него есть какой-то лимит на скорость обработки insert'ов и не важно сколько нод в кластере, мы все-равно подключаемся к какому-то главному серверу и вот у него-то и затык.
              P.s. Если кто-то имеет другой опыт было бы очень интересно посмотреть т.к. как раз из-за того, что rethinkdb не выдержала нагрузку на insert'ы пришлось смотреть в сторону message broker'ов.


              1. YChebotaev
                08.09.2015 13:05

                Попробуйте описать вашу проблему более подробно в трекере, уверен, что команда проекта уделит этой проблеме внимание, мне было бы самому интересно узнать правильный ответ, почему так происходит.


  1. Sway
    06.09.2015 18:53
    +2

    А можете мне объяснить чем нотификации в PostgreSQL (http://www.postgresql.org/docs/9.4/static/libpq-notify.html) хуже нотификаций от NoSQL СУБД? Я когда-то работал с этим механизмом в связке nodejs + postgresql и не помню чтобы были с ним какие-то проблемы, поэтому меня и интересует заданный вопрос.


    1. alekciy
      07.09.2015 13:48

      А можно немного подробнее? Какой сценарий использования и в каких ситуациях эта нотификация может помочь? Т.е. хочется услышать фитбек практического использования.


      1. Sway
        07.09.2015 13:58
        +1

        Сценарий был такой: есть «система» (бд и менеджмент), есть кучка клиентов, которые могут работать с заказами «заказами». Клиенты 2х типов: «заказчик» и «исполнители». исполнители разделяются на несколько групп, выполняющих свои обязанности и передающие результат работы следующему исполнителю или заказчику. Если заказчик создает заказ, то исполнитель 1го этапа получает обновление, делает что-то и переводит заказ в следующее состояние. Тогда заказ появляется у исполнителя 2го этапа и т.д. пока заказ не будет выполнен и вернется к заказчику. Весь процесс при этом можно отслеживать из менеджмента «системы» в реальном времени. Примерно такая система работала вполне адекватно, но не тестировалось при больших нагрузках (пока я там работал)


        1. alekciy
          07.09.2015 14:14

          Посмотрел офдок, но возможно понял неправильно. Но я так понимаю, что у клиентов прямой коннект к РСУБД? В смысле, это какое десктоп приложение (Java? Qt?) которое может работать с базой?


          1. Sway
            07.09.2015 14:59
            +1

            Клиенты конектятся к nodejs через websocket. Nodejs получает обновления от postgresql и рассылает их тем, кто подписан. В postgresql стоят триггеры, которые срабатывают в определенных условиях и кидают NOTIFY.


            1. alekciy
              07.09.2015 16:10

              Т.е. веб клиенты? Получается, что Nodejs держит постоянные коннекты к базе? Или все может происходить в рамках одного соединения?


              1. Sway
                07.09.2015 16:18
                +1

                Насколько помню там было одно или несколько постоянных соединений в nodejs, подписанных на нужные нотификации. Т.е. клиенты не создают свое соединение.
                Это не точная информация т.к. не я реализовывал эту систему, только немного модифицировал, так что вглубь особо не залезал. Моя задача состояла в реализции веб-клиента.
                Клиенты были и веб и мобильные (andoid), там по сути не важно откуда к nodejs присоединяться.


    1. vird
      08.09.2015 11:36

      Объясню на пальцах. Есть два слушателя. Один слушает select * from table where price > 20. Другой слушает select * from table where price > 40.
      Как работает rethinkdb:
      Кто-то добавляет item с price 20 — никто не должен получить ничего.
      21 — получает только первый (он получает полностью весь item, а не уведомление, что в этой таблице что-то поменялось)
      41 — получают оба.
      В случае notification'ов ты не можешь фильтровать какие ты получаешь а какие нет. В случае Postgres это просто именованый broadcast pipe. В случае rethinkdb она еще фильтрует за тебя.


      1. Sway
        08.09.2015 11:57

        Вот оно что. Спасибо. Получается что для postgresql для вашего примера нужно будет слать notify в 2 канала, реализуя notify в самой СУБД, а для rethinkdb можно просто подписаться на запросы и все в шоколаде.
        В простых случаях для postgresql можно фильтрацию и на стороне получателя нотификации делать получая нужную информацию из payload.
        Что-то типа «NOTIFY virtual, id;», но тут мы не получим сам item.
        item можно получить используя row_to_json(record), но тут в случае необходимости фильтрации будет много лишней информации курсировать между БД и получателем. Может быть когда-нибудь и в postgresql улучшат нотификации =))


        1. vvoznesensky
          08.09.2015 15:29

          Я предпочту использовать олдскульный Постгрес. Даже если функциональности и экосистемы РесинкДБ сейчас достаточно, не известно, что понадобится через год.


          1. Sway
            08.09.2015 15:36

            Вот и я пока склоняюсь к использованию проверенных временем СУБД. В сложных системах они все-равно будут надежнее. К хорошему быстро привыкаешь, даже если оно периодически выбешивает =)


            1. vvoznesensky
              08.09.2015 15:52

              Меня не выбешивает, почему-то.

              Надёжнее — да, при чём в разных аспектах.


              1. Sway
                08.09.2015 16:04

                Меня до сих пор иногда бесит своими очень «подробными» ошибками или странными результатами выполнения некоторых функций. Недавно бодался с невозможностью добавить в jsonb массив новый элемент в конец. Т.е. по сути простейшая операция, но пока не вышел 9.5 — это можно сделать только через собственную функцию, в которой, кстати, тоже пришлось пострадать т.к. все функции работающие с json возвращают set jsonb, а не jsonb[] или что-то более удобоваримое. Вся надежда на 9.5


                1. vvoznesensky
                  08.09.2015 16:29

                  Насчёт set — это, как говорится, вкусовщина. Моё мнение — там, где не нужен порядок, он не должен быть.

                  Насчёт jsonb — есть у меня подозрение, что он у Вас в БД не потому, что нужны были именно какие-то свойства json вроде слабой структурированности данных, а потому, что когда начинали делать систему, многое было не понятно. У меня для такого случая рецепт иного уровня — не нанимать программистов, пока у аналитиков/бизнесологов не будет понимания, чего они хотят, жетательно формализованного в тексте.

                  Другой вариант — нужен был силос json-ов, вот и взяли PGSQL, т.к. json-ы и так бегают по системе, и обрабатываются в бэкендовом коде именно как JSON-ы. Тоже отношусь к такому решению с подозрением, т.к. если энти самые JSON-ы приходят из веб-браузерного кода, то можно огрести много открытий чудных по части безопасности. А если не приходят из браузерного кода, то есть подозрение, что они не очень-то и нужны, и можно обойтись более жёсткими и классическими решениями.


                  1. Sway
                    08.09.2015 16:49
                    +1

                    Бизнес-аналитики… знали бы вы как у нас всё это оценивается и разрабатывается…
                    Конкретно в этом случае я использовал json т.к. не нужно держать эти данные в отдельной таблице — они по сути неотделимы от объекта в котором хранятся и не используются никак иначе, но при этом имеют свою структуру. С text[] или varchar[] я не хотел заморачиваться т.к. их нужно было бы парсить, а так json decode и все готово. Решение оказалось очень удобным, кстати. jsonb же выбрал т.к. в нем есть полезные операции вхождения, которые в теории могут пригодиться, но очень надеюсь что до этого не дойдет (жизнь — боль, готовься к худшему)
                    Про безопасность знаю, уже сталкивался. Есть уже проверенный набор валидаторов входящих данных для фильтрации значительной части попыток взлома. Самая живучая проблема — дефектные utf8 символы. Все никак не могу их качественно побороть =(
                    JSON я стараюсь использовать только там где он реально необходим или, в крайнем случае — для хранения данных, структуру которых не могу сейчас предсказать (жизнь — боль).
                    PGSQL же использую с версии 9.1 т.к. лучшего бесплатного в мире не существует + уже привык к его плюшкам.


                    1. vvoznesensky
                      08.09.2015 16:59

                      Знаю, как оценивается и разрабатывается. Потому и не иду в начальники — один раз обжёгся.

                      Вы сами себе противоречите — данные не отделимы от объекта, при этом требуют дописывания в конец. «Рабинович, вы либо трусы оденьте, либо крестик снимите.» А подчинённую таблицу завести вера не позволяет?

                      На мой взгляд, если уж не выходит без json, то лучше каждый раз возвращаться к коду JSON<->SQL (это механическая работа), чем иметь непонятки с безопасностью и корректностью.

                      Структура данных должна следовать из постановки задачи. Да, я не очень удобный сотрудник: заставляю писать себе тикеты.


                      1. Sway
                        08.09.2015 17:06

                        Нужно сохранять порядок добавления этих под-объектов и всё. Только поэтому добавление идет в конец. Наиболее близкий пример — одноуровневые комментарии к статье.


                        1. vvoznesensky
                          08.09.2015 17:10

                          Боюсь, дорого Вашему работодателю может обойтись эта экономия на JSON-SQL преобразованиях. Честное слово.
                          Даже там, где нужны многоуровневые комментарии, PG предоставляет рекурсивный with.

                          Ну да, я олдскул. Обжёгшийся и ворчливый. :)


                          1. Sway
                            08.09.2015 17:13

                            А вот дороговизна — это уже не моя проблема =) Не от хорошей жизни я такое делаю =)


  1. afiskon
    07.09.2015 12:41
    +1

    Спасибо за перевод. Самая большая проблема RethinkDB на данный момент — это отсутствие драйверов. Официальные драйверы есть только для JS, Ruby и Python. То есть даже для JVM нет. А неофициальные драйверы, увы, в очень запущенном состоянии.