Spec-Zone.ru › RethinkDB ruby

Поваренная книга по Ruby

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

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

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

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

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

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

r.db_create("blog").run

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

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

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

r.db("old_db_name").config().update({:name => "new_db_name"}).run

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

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

r.db("blog").table_create("posts").run

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

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

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

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

r.table("user").insert({
    "name" => "Michel",
    "age" => 26
}).run

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

r.table("user").insert([
    {
        "name" => "Michel",
        "age" => 26
    },
    {
        "name" => "Slava",
        "age" => 30
    }
]).run

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

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

r.table("posts").filter{|post| post["author"].eq("Michel")}.delete.run

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

r.table("posts").get("7644aaf2-9928-4231-aa68-4e65e31bf219").delete.run

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

r.table("posts").delete.run

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

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

r.table("posts").run()

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

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

r.table("posts").get(1).run()

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

r.table("posts").filter({:author => "Michel"}).run()

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

r.table("posts").get_all("review", {:index => "category"}).run()

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

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

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

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

r.table("posts").filter({
    "author" => "Michel",
    "category" => "Geek",
}).run

В качестве альтернативы вы можете использовать перегруженный оператор & для построения предиката и передачи его в filter:

r.table("posts").filter{|post|
    (post["author"].eq("Michel")) & (post["category"].eq("Geek"))
}.run

Примечание: RethinkDB перегружает &, поскольку Ruby не позволяет перегружать оператор and. Так как & имеет высокий приоритет, убедитесь, что обернули условия в скобки.

Вы также можете использовать команду r.and, если предпочитаете не использовать перегруженный оператор &:

r.table("posts").filter{|post|
    r.and(post["author"].eq("Michel"),
          post["category"].eq("Geek"))}.run

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

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

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

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

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

r.table("user").filter{|user| user["emails"].contains("user@email.com")}.run

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

r.table("user").filter{ |user|
    r.expr(["Galactica", "Pegasus"]).contains(user["ship"])
}.run()

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

В Ruby вы можете использовать оператор [] для получения значения поля. Этот оператор может быть соединён для получения значений из вложенных полей.

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

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

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

r.table("user").filter{|user|
    user["contact"]["email"].eq("user@email.com")
}.run

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

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

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

r.table("posts").get_all(1, 2, 3).run

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

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

r.table("posts").get_all(1, 2, 3, :index=>'author_id').run

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

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

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

posts = r.table('posts').run(conn).to_a

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

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

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

r.table("posts").pluck("name", "age").run

Это эквивалентно вызову 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

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

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

r.table("posts").filter{ |post|
    post.during(r.time(2012, 1, 1, 'Z'), r.time(2013, 1, 1, 'Z'))
}.run(conn)

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

r.table("posts").filter{ |post|
    (post["date"] >= r.time(2012, 1, 1, 'Z')) &
    (post["date"] < r.time(2013, 1, 1, 'Z'))
}.run(conn)

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

Если вы хотите получить всех пользователей, чья фамилия начинается с «Ma», вы можете сделать это так:

# Will return Martin, Martinez, Marshall etc.
r.table("users").filter{ |user|
    user["lastName"].match("^Ma")
}.run(conn)

Если вы хотите получить всех пользователей, чья фамилия оканчивается на «s», вы можете сделать это так:

# Will return Williams, Jones, Davis etc.
r.table("users").filter{ |user|
    user["lastName"].match("s$")
}.run(conn)

Если вы хотите получить всех пользователей, чья фамилия содержит «ll», вы можете сделать это так:

# Will return Williams, Miller, Allen etc.
r.table("users").filter{ |user|
    user["lastName"].match("ll")
}.run(conn)

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

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

# Will return william, William, WILLIAM, wiLLiam etc.
r.table("users").filter{ |user|
    user["lastName"].match("(?i)^william$")
}.run(conn)

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

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

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

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

r.table('movies').order_by('rank').limit(25).map{ |doc|
    { :total_votes => doc['votes'], :total_year => doc['year'], :count => 1 }
}.reduce{ |left, right|
    :total_votes => (left['total_votes'] + right['total_votes']),
    :total_year => (left['total_year'] + right['total_year']),
    :count => (left['count'] + right['count'])
}.do{ |res|
    :total_votes => res['total_votes'],
    :average_year => (res['total_year'] / res['count'])
}.run(conn)

Обработка документов

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

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

r.table("posts").update({ "author" => "Michel" }).run

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

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

r.table("posts").get("1").replace{|doc| doc.without('author')}.run

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

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

r.table("pages").update{|page|
    r.branch(page["countable"].eq(true),         // if the page is countable
             { "views"=>page["views"] + 1 },     // increment the view count
             {}                                  // else do nothing
    )}, {"return_changes"=>true}).run()

Выполнение условной вставки или замены

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

def update_with_date(id, user_object)
    r.table('users').get(id).replace{ |doc| r.branch(
        (doc == nil),
        r.expr(user_object).merge({:id => id, :created_at => r.now()}),
        doc.merge(user_object).merge({:updated_at => r.now()})
    ).run()
end

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

Вы можете использовать команды epoch_time и iso8601 для преобразования временных меток Unix (в секундах) и строк дат и времени JSON (в формате ISO 8601) в тип времени ReQL. Драйвер ReQL также преобразует объекты Ruby Time в ReQL Time, но не будет автоматически преобразовывать объекты Date или DateTime.

the_date = Time.now
timestamp = the_date.to_i
json_date = the_date.iso8601
r.table("dates").insert({
    :from_object => the_date,
    :from_epoch => r.epoch_time(timestamp),
    :from_iso => r.iso8601(json_date)
}).run(conn)

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

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

r.table('aggregated').get(id).update{ |doc|
    { :count => (doc['count'].default(0)+1) }
}.run(conn)

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

Пагинация

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

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

r.table("posts").order_by("date")
    .limit(10)
    .run

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

Существует несколько способов пагинации результатов в RethinkDB. Наиболее простой способ — использование skip и limit (аналогично работе OFFSET и LIMIT в SQL), но это наименее эффективный способ. Более эффективно использовать slice, а ещё более эффективно — between с дополнительным индексом. Команда slice возвращает диапазон от заданного начального значения до, но не включая, заданного конечного значения. Это делает её удобной заменой для skip/limit: начальное значение — это первый элемент для извлечения, а конечное — это первый элемент плюс предел. Чтобы получить записи с 11 по 20 из базы данных, используя slice,

r.table("posts").order_by("date").slice(11,21).run(conn)

Наконец, если у вас есть дополнительный индекс, вы можете использовать команду between в сочетании с order_by и limit. Это чрезвычайно эффективно, но требует поиска записи по фактическому значению индекса в каждом запросе. То есть вместо получения 11-й записи по номеру 15, вам нужно получить её по значению в индексированном поле.

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

r.table("users").order_by(:index => "name"}).limit(25).run(conn)

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

r.table("users").between(last_name, r.maxval, {:left_bound => "open",
    :index => "name"}).order_by({:index => "name"}).limit(25).run(conn)

Мы передаём сохранённое значение last_name с предыдущего набора в between в качестве начального индекса. В качестве конечного индекса мы передаём nil, чтобы вернуть документы от начального индекса до конца таблицы. Параметр left_bound указывает between, чтобы не включать первую запись, так как она уже была возвращена в предыдущей странице.

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

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

Для подсчёта количества документов можно использовать команду count:

r.table("posts").count.run

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

Для вычисления среднего значения поля можно использовать команду avg.

r.table("posts").avg("num_comments").run

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

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

r.table("posts").merge{ |post|
    {
        "comments" => r.table("comments").filter{ |comment|
            comment["id_post"].eq(post["id"])
        }.coerce_to("ARRAY")
    }
}.run

Выполнение операции сворачивания

Предположим, что таблица 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 и coerce_to.

r.db('test').table('marks').group('name').map { |row|
    [row['course'], row['mark']]
}.ungroup().map { |res|
    r.expr({name: res['group']}).merge(res['reduction'].coerce_to('object'))
}.run(conn)

Примечание: В будущем будет добавлена более удобная синтаксическая конструкция. Следите за прогрессом на Github issue 838.

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

Для выполнения операции разворачивания (обратной сворачивания) можно использовать команды concat_map, map и keys:

r.table("pivoted_marks").concat_map { |doc|
    doc.without("id", "name").keys().map { |course|
    	{
            :name => doc["name"],
            :course => course,
            :mark => doc[course]
        }
    }
)

Примечание: В будущем будет добавлена более удобная синтаксическая конструкция. Следите за прогрессом на Github issue 838.

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

Предположим, что нужно переименовать поле id в id_user при получении документов из таблицы users. Можно сделать так:

r.table("users").map{ |user|
    # Add the field id_user that is equal to the id one
    user.merge({
        "id_user" => user["id"]
    })
    .without("id") # Remove the field id
}

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

ReQL имеет команды для извлечения частей дат и времени, включая год, месяц, день, день недели и др. Их можно использовать с 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').order_by('month').run(conn)

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

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

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

r.table('invoices').index_create('by_day') { |doc|
    [doc['date'].year(), doc['date'].month(), doc['date'].day()]
}.run(conn)

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

r.table('invoices').group({:index => 'by_day'}).max('price').run(conn)

Разное

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

Эффективная генерация монотонно возрастающих идентификаторов в распределённой системе — это удивительно сложная задача. Если вставляемому документу не задан первичный ключ, 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 – Если вы выполняете запрос вставки, где некоторые или все строки не имеют первичных ключей, сервер сгенерирует для вас первичные ключи и вернёт массив этих ключей в этом поле. (Порядок этого массива будет соответствовать порядку строк в вашем запросе вставки.)
  • generated_keys – Если errors положительно, текст первого сообщения об ошибке, встреченной, будет в этом поле. Это очень полезный инструмент отладки. (Мы не возвращаем все ошибки, потому что одна опечатка может привести к миллионам ошибок при работе с большой базой данных.)

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

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

r.table('users').get(1).update(r.object(property_name, value)).run(conn)

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

r.table('users').for_each{ |doc|
    r.table('users').get(doc['id']).update(r.object(doc['field'], new_value))
}.run(conn)

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

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

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

{
    "Mathematics" => 70,
    "English" => 90
}

Вы можете добиться этого с помощью object и pivot.

r.table('marks').filter({:student => 'John'}).map{ |mark|
    r.object(mark['course'], mark['mark'])
}.reduce{ |left, right| left.merge(right) }.run(conn)

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

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

r.table('users').filter{ |user| user['groups'].contains('operators')}.inspect()

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

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

query = r.table('posts')
query.filter(request.filter) if request.filter
query.order_by('date')
query.run(conn)

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

query = r.table('posts')
query = query.filter(request.filter) if request.filter
query = query.order_by('date')
query = query.run(conn)

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

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

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

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

r.table("table1").merge({:table => "table1"}).union(
    r.table("table2").merge({:table => "table2"}).changes().run(conn)

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

r.table("table1").filter({:flag => "blue"}).changes().union(
    r.table("table2").filter({:flag => "red"}).changes()
).run(conn)

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

Spec-Zone.ru

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