RethinkDB: как выполнить рекурсивное объединение трех таблиц?

Я разрабатываю платформу с JSON API, используя Python Flask. В некоторых случаях мне нужно присоединиться к трем таблицам. Как соединить таблицы с массивом идентификаторов дал мне некоторые рекомендации, но мне нужно решение за его пределами.

Предположим, у нас есть три таблицы для приложения для обмена сообщениями.

  1. Счета
  2. Разговоры
  3. Сообщения
  4. Читатели сообщений

Фрагмент таблицы учетных записей

{
    "id": "account111",
    "name": "John Doe",
},

Фрагмент таблицы бесед

{
    "id": "conversation111",
    "to": ["account111", "account222", "account333"], // accounts who are participating the conversation
    "subject": "RethinkDB",
}

Фрагмент таблицы сообщений

{
    "id": "message111",
    "text": "I love how RethinkDB does joins.",
    "from": "account111", // accounts who is the author of the message
    "conversation": "conversation111"
}

Фрагмент таблицы для чтения сообщений

{
    "id": "messagereader111",
    "message": "message111",
    "reader": "account111",
}

Мой вопрос: «Какой волшебный запрос для получения документа ниже, когда я получаю запрос на получение документа учетной записи с id = «account111»?»

{
    "id": "account111",
    "name": John Doe,
    "conversations": [            // 2) Join account table with conversations
        {
           "id": "conversation111",
           "name": "RethinkDB",
           "to": [                     // 3) Join conversations table with accounts
               {
                    "id": "account111",
                    "name": "John Doe",
               },
               {
                    "id": "account222",
                    "name": "Bobby Zoya",
               },
               {
                    "id": "account333",
                    "name": "Maya Bee",
               },
           ]
           "messages": [        // 4) Join conversations with messages
               {
                   "id": "message111",
                   "text": "I love how RethinkDB does joins.",
                   "from": {        // 5) Join messages with accounts
                        "id": "account111",
                        "name": "John Doe",
                   },
                   "message_readers": [
                       {
                           "name": "John Doe",
                           "id": "account111",
                       }
                   ],
               },
           ],
        },
    ],
}

Любое руководство или совет были бы фантастическими. Код JavaScript или Python был бы потрясающим.


person Dogukan Tufekci    schedule 15.02.2014    source источник


Ответы (1)


Мне было трудно понять, что вы хотите (у вас есть несколько документов с идентификатором 111), но я думаю, что это именно тот запрос, который вы ищете.

Запрос Python:

r.table("accounts").map(lambda account: 
    account.merge({
        "conversations": r.table("conversations").filter(lambda conversation: 
            conversation["to"].contains(account["id"])).coerce_to("array").map(lambda conversation:
            conversation.merge({
                "to": conversation["to"].map(lambda account: 
                    r.table("accounts").get(account)).pluck(["id", "name",]).coerce_to("array"),
                "messages": r.table("messages").filter(lambda message:
                    message["conversation"] == conversation["id"]).coerce_to("array").map(lambda message:
                    message.merge({
                        "from": r.table("accounts").get(message["from"]).pluck(["id", "name",]),
                        "readers": r.table("message_readers").filter(lambda message_reader:
                            message["id"] == message_reader["message"]).coerce_to("array").order_by(r.desc("created_on")),
                    })).order_by(r.desc("created_on"))
            })).order_by(r.desc("modified_on"))
    })).order_by("id").run(db_connection)
person neumino    schedule 15.02.2014
comment
Я изменил значения идентификатора, чтобы было легче понять вопрос. Можете ли вы подтвердить, что решение соответствует вопросу? - person Dogukan Tufekci; 15.02.2014
comment
Я думаю, это должно быть то, что вы ищете. - person neumino; 15.02.2014
comment
Можете ли вы объяснить функцию индекса? А почему таблица называется сниппетами? - person Dogukan Tufekci; 15.02.2014
comment
Кстати, запрос выглядит очень легко следовать. Я протестирую его и посмотрю, работает ли он. - person Dogukan Tufekci; 15.02.2014
comment
Плохо, я думал, что последняя таблица была фрагментом вместо сообщений. Я только что обновил запрос. Об индексе вы можете прочитать об индексах здесь: rethinkdb.com/docs/secondary-indexes -- я также отказываюсь от использования индекса. - person neumino; 15.02.2014
comment
Ваш ответ был просто идеальным; ну и с некоторыми багами :) Поэтому отлаживал. Я заметил две проблемы с текущим ответом: 1) таблица сообщений гибкая, и в ней может не быть поля от. Когда объект сообщения отсутствует в поле, я получаю эту ошибку: RqlRuntimeError: Нет атрибута from в объекте. 2) Как превратить поле читателей в массив только идентификаторов учетных записей, также известных как идентификаторы читателей? В настоящее время он возвращает список объектов учетной записи/читателя. - person Dogukan Tufekci; 17.02.2014