Spec-Zone.ru › RethinkDB java

Поваренная книга для Java

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

Не нашли нужный рецепт? Запросите или добавьте рецепт, создав вопрос на GitHub.

  • Основные команды
  • Фильтрация
  • Работа с документами
  • Пагинация
  • Преобразования
  • Разное

<img class="api_command_illustration" src="data:image/png;base64,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

Основные команды

Создание базы данных

Вы можете использовать команду dbCreate следующим образом:

r.dbCreate("blog").run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Другой способ создания базы данных — через веб-интерфейс. Вы можете перейти к веб-интерфейсу по адресу http://HOST:8080. Нажмите на вкладку Таблицы вверху и затем кнопку Добавить базу данных.

Переименование базы данных

Самый простой способ переименовать базу данных — использовать команду config для доступа к таблице db_config системных таблиц, а затем просто использовать команду update.

r.db("old_db_name").config().update({name: "new_db_name"}).run(conn,
    function(err, result) {
        if (err) throw err;
        console.log(result);
    }
);

Создание таблицы

Вы можете выбрать базу данных, в которой вы хотите создать таблицу, с помощью команды db и использовать команду tableCreate следующим образом:

r.db("blog").tableCreate("posts").run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Обратите внимание, что вы можете опустить команду db, если создаёте таблицу в базе данных по умолчанию для вашего подключения (по умолчанию установлено test, если не указано в connect).

Другой способ создать новую таблицу — использовать веб-интерфейс. Вы можете перейти к веб-интерфейсу по адресу http://HOST:8080. Нажмите на вкладку Таблицы в верхней части страницы, а затем используйте кнопку Добавить таблицу.

Вставка документов

Вы можете вставлять документы, вызвав команду insert для соответствующей таблицы:

r.table("user").insert({
    name: "Michel",
    age: 26
}).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Вы можете вставлять несколько документов одновременно, передав массив документов в insert следующим образом:

r.table("user").insert([
    {
        name: "Michel",
        age: 26
    },
    {
        name: "Slava",
        age: 30
    }
]).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Удаление документов

Для удаления документов выберите документы, которые вы хотите удалить, и используйте команду delete. Например, давайте удалим все записи с автором «Michel»:

r.table("posts").filter(r.row("author").eq("Michel")).delete().run(conn,
    function(err, result) {
        if (err) throw err;
        console.log(result);
    }
);

Или давайте попробуем удалить одного пользователя:

r.table("posts").get("7644aaf2-9928-4231-aa68-4e65e31bf219").delete().run(conn,
    function(err, result) {
        if (err) throw err;
        console.log(result);
    }
);

Вот как мы удалим все документы в таблице:

r.table("posts").delete().run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Получение документов

Чтобы получить все документы в таблице, просто используйте команду table:

r.table("posts").run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Команда table возвращает курсор; используйте команду next или each для итерации по результатам или toArray для получения набора как массива.

Чтобы получить конкретный документ по идентификатору, используйте get:

r.table("posts").get(1).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Чтобы получить документы по значению определённого поля, используйте filter:

r.table("posts").filter({author: "Michel"}).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Чтобы получить документы по значению определённого индекса, используйте getAll:

r.table("posts").getAll("review", {index: "category"}).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

(Для более сложных фильтров, читайте дальше.)

Фильтрование

Фильтрование по нескольким полям

Предположим, вам нужно выбрать все статьи, где имя автора «Michel», а категория «Geek». Вы можете сделать это следующим образом:

r.table("posts").filter({
    author: "Michel",
    category: "Geek",
}).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

В качестве альтернативы, вы можете создать предикат с помощью команды and и передать его в filter:

r.table("posts").filter(
    r.row("author").eq("Michel").and(r.row("category").eq("Geek"))
).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Вы также можете использовать префиксную нотацию (передавая все аргументы в r.and), если это предпочтительнее:

r.table("posts").filter(
    r.and(r.row("author").eq("Michel"), r.row("category").eq("Geek"))
).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Аналогично, вы можете использовать команду r.or для фильтрации по одному из нескольких условий.

Фильтрование по наличию значения в массиве

Предположим, у нас есть таблица users с документами следующего формата:

{
    name: "William Adama"
    emails: ["bill@bsg.com", "william@bsg.com"],
    ship: "Galactica"
}

Если мы хотим получить всех пользователей с адресом электронной почты user@email.com, мы можем написать:

r.table("user").filter(r.row("emails").contains("user@email.com"))
 .run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Если мы хотим получить всех пользователей на Galactica и Pegasus, мы можем написать:

r.table("user").filter(function (user) {
    r(["Galactica", "Pegasus"]).contains(user("ship"))
}).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Фильтрование по вложенным полям

В JavaScript вы можете использовать оператор () для получения значения поля. Этот оператор можно использовать для получения значений из вложенных полей.

Предположим, у нас есть таблица users с документами следующего формата:

{
    name: "William Adama"
    contact: {
        phone: "555-5555"
        email: "bill@bsg.com"
    }
}

Давайте отфильтруем по вложенному полю email:

r.table("user").filter(
    r.row("contact")("email").eq("user@email.com")
).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Для многих команд ReQL также можно использовать синтаксис вложенного JSON, который позволяет значительно больше гибкости. Подробнее об этом читайте в статье «Доступ к вложенным полям».

Эффективное получение нескольких документов по первичному ключу

Если вы хотите получить все статьи с первичными ключами 1, 2, или 3, вы можете использовать команду getAll:

r.table("posts").getAll(1, 2, 3).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Эффективное получение нескольких документов по вторичному индексу

Предположим, у нас есть таблица posts, которая связывает статьи с авторами через поле author_id. Если мы создали вторичный индекс на author_id и хотим получить все статьи, где author_id имеет значения 1, 2, или 3, мы можем использовать команду getAll следующим образом:

r.table("posts").getAll(1, 2, 3, {index: 'author_id'})
 .run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Подробнее об создании вторичных индексов в RethinkDB.

Получение всех объектов в потоке (курсоре) как массива

Если вы используете команду, возвращающую поток, и хотите получить все её результаты сразу в массиве, а не итерируясь через объект курсора, вы можете преобразовать его в массив с помощью команды toArray.

r.table('posts').run(conn, function(err, cursor) {
    if (err) throw err;
    cursor.toArray(function(result) {
        console.log(result);
    });
});

См. документацию по типам данных для получения дополнительной информации о потоках.

Возвращение определённых полей документа

Если вам нужно получить только несколько определённых полей из ваших документов, вы можете использовать команду pluck. Например, вот как вы вернёте только поля name и age из каждой строки в таблице users:

r.table("users").pluck("name", "age").run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Это эквивалентно вызову SELECT name, age FROM users в SQL.

Команда pluck также поддерживает выбор вложенных полей в документе. Например, предположим, что мы хотим выбрать поля phone и email из следующего документа:

{
    name: "William Adama"
    contact: {
        phone: "555-5555"
        email: "bill@bsg.com"
    }
}

Мы можем использовать следующий синтаксис:

r.table("users").pluck(
    {contact: {phone: true, email: true}}
).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Фильтрование по диапазону дат

Предположим, вы хотите получить все статьи, дата которых находится между 1 января 2012 года (включительно) и 1 января 2013 года (исключительно). Вы могли бы сделать это так:

r.table("posts").filter(function(post) {
    return post("date").during(r.time(2012, 1, 1, 'Z'), r.time(2013, 1, 1, 'Z'));
}).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Вы также можете вручную сравнивать даты:

r.table("posts").filter(function(post) {
    return post("date").ge(r.time(2012, 1, 1, 'Z')).and(
        post("date").lt(r.time(2013, 1, 1, 'Z')));
}).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Фильтрование с помощью регулярных выражений

Если вы хотите получить всех пользователей, чья фамилия начинается с «Ma», вы можете использовать r.match следующим образом:

// Will return Martin, Martinez, Marshall etc.
r.table("users").filter(function(user) {
    return user("lastName").match("^Ma");
}).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Если вы хотите получить всех пользователей, чья фамилия заканчивается на «s», вы можете использовать r.match следующим образом:

// Will return Williams, Jones, Davis etc.
r.table("users").filter(function(user) {
    return user("lastName").match("s$");
}).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Если вы хотите получить всех пользователей, чья фамилия содержит «ll», вы можете использовать r.match следующим образом:

// Will return Williams, Miller, Allen etc.
r.table("users").filter(function(user) {
    return user("lastName").match("ll");
}).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Регистронезависимый фильтр

Получите всех пользователей, чьё имя «William» (регистронезависимо).

// Will return william, William, WILLIAM, wiLLiam etc.
r.table("users").filter(function(user) {
    return user("name").match("(?i)^william$");
}).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Выполнение нескольких агрегаций одновременно

Если вы хотите выполнить запрос, возвращающий агрегации по разным полям вместе, это стандартный случай использования map-reduce.

Предположим набор данных, перечисляющий лучшие фильмы, ранжированные по голосам пользователей. Вы хотите получить суммарные голоса и средний возраст 25 лучших фильмов: avg() столбца year и sum() столбца votes, отсортированные по столбцу rank для получения диапазона 1-25.

Для этого map первых 25 фильмов в новый набор результатов, добавив столбец count, затем reduce каждую строку нарисованного набора результатов в общее значение для каждого поля (votes, year и column). Затем используйте do для возврата набора результатов с суммой голосов и средним годом, вычисленным путём деления суммы годов на их количество.

r.table('movies').orderBy('rank').limit(25).map(function (doc) {
    return { totalVotes: doc('votes'), totalYear: doc('year'), count: 1 };
}).reduce(function (left, right) {
    return {
        totalVotes: left('totalVotes').add(right('totalVotes')),
        totalYear: left('totalYear').add(right('totalYear')),
        count: left('count').add(right('count'))
    };
}).do(function (res) {
    return {
        totalVotes: res('totalVotes'),
        averageYear: res('totalYear').div(res('count'))
    };
}).run(conn, callback);
END_OF_DOCUMENT_MARKER

Мы работаем над более простым синтаксисом для выполнения нескольких агрегаций после команд group. Следите за прогрессом в проблеме issue 1725.

Изменение документов

Добавление/перезапись поля в документе

Для добавления или перезаписи поля можно использовать команду update. Например, если вы хотите добавить поле author со значением «Michel» для всех документов в таблице posts, используйте:

r.table("posts").update({ author: "Michel" }).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Удаление поля из документа

Команда update позволяет перезаписывать поля, но не удалять их. Если вы хотите удалить поле, используйте команду replace. Команда replace заменяет весь ваш документ новым документом, переданным в качестве аргумента. Например, если вы хотите удалить поле author из записи блога с id 1, используйте:

r.table("posts").get("1").replace(r.row.without('author'))
 .run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Атомарное обновление документа на основе условия

Все изменения, сделанные с помощью команд update и replace, всегда атомны относительно одного документа. Например, предположим, что мы хотим атомарно обновить счётчик просмотров страницы, если поле countable установлено в true, и получить старые и новые результаты в одном запросе. Мы можем выполнить эту операцию следующим образом:

r.table("pages").update(function(page) {
    return r.branch(page("countable").eq(true),  // if the page is countable
        { views: page("views").add(1) },         // increment the view count
        {}                                       // else do nothing
    );
}, {returnChanges: true}).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Условное добавление или замена

Используя аналогичный подход к предыдущему примеру, мы можем использовать branch и replace для поддержания полей updated_at и created_at документа, добавляя новый документ или обновляя существующий в зависимости от того, существует ли документ с указанным ID.

r.table('users').get(id).replace(function (doc) {
    return r.branch(
        doc.eq(null),
        r.expr(userObject).merge({id: id, created_at: r.now()}),
        doc.merge(userObject).merge({updated_at: r.now()})
    )
}).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Хранение временных меток и строк JSON-дат как типов данных Time

Можно использовать команды epochTime и ISO8601 для преобразования временных меток Unix (в секундах) и строк JSON-датирования (в формате ISO 8601) в тип времени ReQL. Драйвер ReQL также преобразует объекты JavaScript Date в время ReQL.

var theDate = new Date();
var timestamp = theDate.getTime();
var JSONDate = theDate.toJSON();
r.table("dates").insert({
    from_object: theDate,
    from_epoch: r.epochTime(timestamp/1000.0),
    from_iso: r.ISO8601(JSONDate)
}).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Используйте команды toEpochTime и toISO8601 для обратного преобразования.

Инкрементирование значения поля

Можно инкрементировать значение поля в документе (например, счётчик) за один шаг на сервере.

r.table('aggregated').get(id).update(
    { count: r.row('count').default(0).add(1) }
).run(conn, callback);

Используйте default для добавления поля count, если оно не существует в документе, а не для того, чтобы add генерировало ошибку.

Пагинация

Ограничение количества возвращаемых документов

Можно ограничить количество документов, возвращаемых запросами, с помощью команды limit. Получим только первые 10 записей блогов:

r.table("posts").orderBy("date").limit(10).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Реализация пагинации

Существует несколько способов реализации пагинации результатов в RethinkDB. Самый простой способ — использование skip и limit (подобно работе OFFSET и LIMIT в SQL), но это наименее эффективно. Более эффективно использовать slice, а ещё более эффективно использовать between со вторичным индексом.

Команда slice возвращает диапазон значений от указанного начального до указанного конечного, но не включая конечное значение. Это упрощает использование в качестве замены skip/limit: начальное значение — это первый элемент для извлечения, а конечное значение — это первый элемент плюс предел. Чтобы извлечь записи 11-20 из базы данных с использованием slice, используйте:

r.table("posts").orderBy("date").slice(11,21).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Если у вас есть вторичный индекс, вы можете использовать команду between в сочетании с orderBy и limit. Это наиболее эффективный способ пагинации, но требует поиска значений в поле вторичного индекса, чтобы найти первую запись каждой страницы.

Предположим, вы хотите перелистывать набор пользователей по 25 на страницу. Вы можете эффективно получить первые 25 записей с помощью limit.

r.table("users").orderBy({index: "name"}).limit(25).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Для каждой последующей страницы начинайте с последнего имени на предыдущей странице.

r.table("users").between(lastName, r.maxval, {leftBound: "open", index: "name"})
 .orderBy({index: "name"}).limit(25).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Мы передаём lastName (сохранённое с предыдущего набора) в between в качестве индекса начала. В качестве конечного индекса мы передаём null, чтобы вернуть документы от индекса начала до конца таблицы. Параметр leftBound сообщает between, что первая запись не должна включаться, поскольку она уже была возвращена на предыдущей странице.

Преобразования

Подсчёт количества документов в таблице

Вы можете подсчитать количество документов с помощью команды count:

r.table("posts").count().run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Вычисление среднего значения поля

Вы можете вычислить среднее значение поля с помощью команды avg.

r.table("posts").avg("num_comments").run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Использование подзапросов для возвращения дополнительных полей

Предположим, что мы хотим получить все записи в таблице post и также вернуть дополнительное поле comments, которое представляет собой массив всех комментариев к соответствующей записи, извлечённых из таблицы comments. Это можно сделать с помощью подзапроса:

r.table("posts").merge(function(post) {
    return {
        comments: r.table("comments").filter(function(comment) {
            return comment("id_post").eq(post("id"))
        }).coerceTo("ARRAY")
    }
}).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Выполнение операции поворота

Предположим, что таблица marks хранит оценки каждого студента по каждому курсу:

[
    {
        "name": "William Adama",
        "mark": 90,
        "id": 1,
        "course": "English"
    },
    {
        "name": "William Adama",
        "mark": 70,
        "id": 2,
        "course": "Mathematics"
    },
    {
        "name": "Laura Roslin",
        "mark": 80,
        "id": 3,
        "course": "English"
    },
    {
        "name": "Laura Roslin",
        "mark": 80,
        "id": 4,
        "course": "Mathematics"
    }
]

Возможно, вас интересует получение результатов в таком формате:

[
    {
        "name": "Laura Roslin",
        "Mathematics": 80,
        "English": 80
    },
    {
        "name": "William Adama",
        "Mathematics": 70,
        "English": 90
    }
]

В этом случае вы можете выполнить операцию поворота с помощью команд group и coerceTo.

r.db('test').table('marks').group('name').map(function (row) {
    return [row('course'), row('mark')];
}).ungroup().map(function (res) {
    return r.expr({name: res('group')}).merge(res('reduction').coerceTo('object'));
}).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Примечание: В дальнейшем будет добавлен более удобный синтаксис. Следите за прогрессом в проблеме Github issue 838.

Выполнение операции развертывания

Для выполнения операции развертывания, чтобы «отменить» операцию поворота, можно использовать команды concatMap, map и keys:

r.table("pivotedMarks").concatMap(function (doc) {
    return doc.without("id", "name").keys().map(function (course) {
        return {
            name: doc("name"),
            course: course,
            mark: doc(course)
        };
    });
}).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Примечание: В дальнейшем будет добавлен более удобный синтаксис. Следите за прогрессом в проблеме Github issue 838.

Переименование поля при извлечении документов

Предположим, мы хотим переименовать поле id в idUser при извлечении документов из таблицы users. В подзапросе мы можем использовать merge для добавления нового поля со значением существующего поля, а затем without для удаления старого поля:

r.table("users").map(
    r.row.merge({ idUser: r.row("id") }).without("id")
).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Группировка результатов запроса по временным периодам

ReQL имеет команды для извлечения частей дат и времени, включая year, month, day, dayOfWeek и другие. Вы можете использовать их с group, чтобы сгруппировать по различным интервалам. Предположим, у вас есть таблица сведений об счетах и вы хотите получить их в группах, отсортированных по году и месяцу:

r.table("invoices")
    .group([r.row("date").year(), r.row("date").month()])
    .ungroup()
    .merge({invoices: r.row('reduction'), month: r.row('group')})
    .without('reduction', 'group')
    .orderBy('month')
.run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

(Мы также используем технику переименования поля, описанную выше, чтобы преобразовать названия «reduction» и «group» в более информативные «invoices» и «month».) Вы можете использовать любые комбинации команд ReQL для работы с интервалами дат/времени в группировке или работать с датой/временем как с родным объектом.

В настоящее время ReQL имеет ограничение по умолчанию в 100 000 элементов в массиве, а реализация group требует, чтобы общее количество сгруппированных документов входило в эти пределы, поэтому вы ограничены 100 000 счетами. Однако это можно изменить, передав опцию arrayLimit к run. (Также обратите внимание, что ungroup всегда возвращает массив, хотя это может измениться в будущей версии. Следите за прогрессом в проблеме #2719).

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

r.table('invoices').indexCreate(
    'byDay', [r.row('date').year(), r.row('date').month(), r.row('date').day()]
).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Затем вы можете использовать этот индекс в функции group. Этот запрос вернёт счёт с наибольшим значением для каждого дня.

r.table("invoices")
    .group({index: 'byDay'})
    .max('price')
.run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Разное

Генерация монотонно возрастающих значений первичного ключа

Эффективная генерация монотонно возрастающих идентификаторов в распределённой системе — удивительно сложная задача. Если вставляемый документ не имеет первичного ключа, RethinkDB в настоящее время генерирует случайный UUID. В будущем мы будем поддерживать дополнительные схемы автогенерации (см. https://github.com/rethinkdb/rethinkdb/issues/117), но в настоящее время вы можете использовать одну из доступных библиотек с открытым исходным кодом для генерации распределённых идентификаторов (например, twitter snowflake).

Обработка ответа RethinkDB на запрос записи

При выполнении запроса записи (insert, delete, update, или replace), RethinkDB возвращает объект-резюме, который выглядит так:

{deleted:0, replaced:0, unchanged:0, errors:0, skipped:0, inserted:1}

Наиболее важный поле этого объекта — errors. Как правило, если не происходит исключений и errors равно 0, значит запись выполнена успешно. (RethinkDB выбрасывает исключение, если не может получить доступ к таблице; если доступ к таблице есть, но при записи возникает ошибка, устанавливается поле errors. Эта соглашение существует для того, чтобы пакетные записи не прерывались на полпути при возникновении ошибки.)

Следующие поля всегда присутствуют в этом объекте:

  • inserted – Количество новых документов, добавленных в базу данных.
  • deleted – Количество документов, удаленных из базы данных.
  • replaced – Количество документов, которые были изменены.
  • unchanged – Количество документов, которые должны были быть изменены, но новое значение оказалось таким же, как и старое.
  • skipped – Количество документов, которые остались неизменёнными в операции записи, потому что документ недоступен для удаления или обновления. Документ мог быть удалён другой операцией, выполняющейся одновременно, или, в случае операции get, ключ может отсутствовать.
  • errors – Количество документов, которые остались неизменными из-за ошибки.

Кроме того, следующие два поля устанавливаются в зависимости от обстоятельств:

  • generated_keys – Если вы выполняете запрос вставки, где некоторые или все строки лишены первичных ключей, сервер сгенерирует для вас первичные ключи и вернёт массив этих ключей в этом поле. (Порядок в этом массиве будет соответствовать порядку строк в вашем запросе вставки.)
  • first_error – Если errors имеет положительное значение, текст первого сообщения об ошибке, которое было встречено, будет в этом поле. Это очень полезный инструмент отладки. (Мы не возвращаем все ошибки, потому что одна опечатка может привести к миллионам ошибок при работе с большой базой данных.)

Использование динамических ключей в командах ReQL

Иногда вам может потребоваться записать документ ReQL с динамическим ключом — имя поля хранится в переменной. Вы можете сделать это с помощью команды object, которая принимает список ключей и значений ((key, value, key, value ...)) и возвращает из них объект.

r.table('users').get(1).update(r.object(propertyName, value)).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Имя поля также может быть определено полностью на сервере. Например, чтобы обновить поле, чьё имя взято из значения другого поля:

r.table('users').forEach(function (doc) {
  return r.table('users').get(doc('id')).update(r.object(doc('field'), newValue));
}).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

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

[
    {
        "name": "John",
        "mark": 70,
        "id": 1,
        "course": "Mathematics"
    },
    {
        "name": "John",
        "mark": 90,
        "id": 2,
        "course": "English"
    }
]

Но вы хотели бы получить документ, более похожий на «отчётную карточку»:

{
    "Mathematics": 70,
    "English": 90
}

Это можно выполнить с помощью object и сводки.

r.table("marks").filter({student: "John"}).map(function(mark) {
    return r.object(mark("course"), mark("mark"));
}).reduce(function(left, right) {
    return left.merge(right);
}).run(conn, function(err, result) {
    if (err) throw err;
    console.log(result);
});

Возвращение запроса ReQL в виде строки

Для целей тестирования или ведения журнала вам может потребоваться захватить созданный запрос ReQL в виде строки. (Вы можете увидеть пример этого в сообщениях об ошибках ReQL.) Хотя нет команды ReQL для этого, вы можете просто использовать метод toString() в конце цепочки запросов, а не run():

r.table('users').filter(r.row('groups').contains('operators')).toString()

Создание запросов ReQL на нескольких строках

В некоторых интерфейсах запросов часто используется шаблон «построения» запросов программно, создавая объект запроса, вызывая его несколько раз последовательно для добавления команд запроса, а затем вызывая команду выполнения. Это позволяет динамически изменять запрос на основе условий во время выполнения. Можно ожидать, что это будет работать в ReQL так:

var query = r.table('posts');
if (request.filter !== undefined) {
    query.filter(request.filter);
}
query.orderBy('date');
query.run(conn, callback);

Однако это не сработает! Причина в том, что объект запроса не хранит состояние. Каждая из команд после первой просто выполняется над исходным значением query (в данном случае таблицей posts). Вы можете решить эту проблему, явно присваивая результат каждой новой команды переменной query:

var query = r.table('posts');
if (request.filter !== undefined) {
    query = query.filter(request.filter);
}
query = query.orderBy('date');
query.run(conn, callback);

Объединение нескольких changefeed в один

Вам может понадобиться создать «объединённый» changefeed для наблюдения за несколькими таблицами или запросами в одном потоке. Поскольку команда union работает с changes, ReQL делает это довольно просто. Чтобы отслеживать две таблицы одновременно:

r.table('table1').union(r.table('table2')).changes().run(conn, callback);

Вы можете пометить таблицы, чтобы было ясно, какие изменения относятся к какой таблице.

r.table('table1').merge({table: 'table1'})
 .union(r.table('table2').merge({table: 'table2'})
 .changes().run(conn, callback);

Также можно использовать changes с каждым запросом, а не после всего запроса.

r.table('table1').filter({flag: 'blue'}).changes()
 .union(r.table('table2').filter({flag: 'red'}).changes())
 .run(conn, callback);

© RethinkDB contributors
Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
https://rethinkdb.com/docs/cookbook/java/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API