Как получить все документы из коллекции в FaunaDB? - PullRequest
2 голосов
/ 28 апреля 2020

У меня уже есть ответ:

const faunadb = require('faunadb')
const q = faunadb.query

exports.handler = async (event, context) => {
  const client = new faunadb.Client({
    secret: process.env.FAUNADB_SERVER_SECRET
  }) 

  try {  
    // Getting the refs with a first query
    let refs = await client.query(q.Paginate(q.Match(q.Index('skus'))))
    // Forging a second query with the retrieved refs
    const bigQuery = refs.data.map((ref) => q.Get(ref))
    // Sending over that second query
    let allDocuments = await client.query(bigQuery)
    // All my documents are here!
    console.log('@allDocuments: ', allDocuments);
    //...
  } catch (err) {
    // ...
  }
}

Но я нахожу это неудовлетворительным, потому что я делаю 2 запроса на то, что кажется одним из самых тривиальных вызовов БД. Это кажется мне неэффективным и многословным.

Поскольку я только что узнал о FaunaDB, возможно, здесь есть что-то, чего я не хрю asp. Мой вопрос можно разделить на 3:

  • Могу ли я запросить все документы за один звонок?
  • Если нет, то почему? Что за логика c стоит за таким дизайном?
  • Могу ли я сделать такой запрос без индекса?

Ответы [ 2 ]

4 голосов
/ 28 апреля 2020

Язык FQL FaunaDB очень похож на JavaScript (что очень помогает, если вы хотите выполнять условные транзакции и т. Д. c).

По сути, FaunaDB также имеет Map. Учитывая, что ваш индекс содержит только одно значение , которое является ссылкой, вы можете написать это:

q.Map(
  q.Paginate(q.Match(q.Index('skus'))),
  q.Lambda(x => q.Get(x))
)

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

q.Map(
  q.Paginate(Documents(Collection('<your collection>'))),
  q.Lambda(x => q.Get(x))
)

Теперь, если используемый вами индекс возвращает несколько значений (потому что вы хотите отсортировать что-то другое чем 'ref'), то вам нужно предоставить столько же параметров для лямбды, сколько значений, которые были определены в индексе. Допустим, мой индекс имеет значения ts и ref , потому что я хочу отсортировать их по времени, а затем запрос для получения всех значений:

q.Map(
  q.Paginate(q.Match(q.Index('<your index with ts and ref values>'))),
  q.Lambda((ts, ref) => q.Get(ref))
)

Значения используются для запросов диапазона / сортировки, но также определяют, что возвращает индекс

Возвращаясь к вашим вопросам:

- Могу ли я запросить все документы за один вызов?

Безусловно, я бы посоветовал вам сделать это. Обратите внимание, что документы, которые вы получите, будут разбиты на страницы автоматически. Вы можете установить размер страницы, предоставив параметр для разбивки на страницы и вернув атрибут «после» или «до», если страница больше. То, что после или до, может быть снова представлено функции Paginate в качестве параметра для получения следующей или предыдущей страницы: https://docs.fauna.com/fauna/current/api/fql/functions/paginate

- Могу ли я сделать такой запрос без index?

Нет, но вы можете использовать встроенный индекс, как описано выше. FaunaDB защищает пользователей от запросов без индекса. Так как это масштабируемая база данных, которая может содержать большие объемы данных и оплачивается по мере выведения go, рекомендуется запретить пользователям стрелять себе в ноги :). Нумерация страниц и обязательные индексы помогают сделать это.

Что касается того, почему FQL отличается. FQL - это язык, который не является декларативным, как многие языки запросов. Вместо этого, вы пишете , как извлекаете данные. Это имеет свои преимущества:

  1. Путем написания того, как извлекаются данные, вы можете точно предсказать, как ведет себя запрос, который приятно иметь в системе с оплатой по факту go.
  2. Один и тот же язык может использоваться для правил безопасности или сложных условных транзакций (обновлять определенные объекты или множество объектов в разных коллекциях в зависимости от определенных условий). В Фауне довольно часто пишут запрос, который делает много вещей в одной транзакции.
  3. Наша разновидность «хранимых процедур», называемых пользовательскими функциями, просто написана на FQL, а не на другом языке.

Запросы также обсуждаются в этом руководстве, которое поставляется с кодом в GitHub. хранилище, которое может дать вам более полную картину: https://css-tricks.com/rethinking-twitter-as-a-serverless-app/

2 голосов
/ 28 апреля 2020

Могу ли я запросить все документы за один звонок?

Да, если ваша коллекция небольшая. Функция Paginate по умолчанию выбирает 64 документа на страницу. Вы можете настроить размер страницы до 100 000 документов. Если в вашей коллекции более 100 000 документов, вам нужно выполнить несколько запросов, используя курсоры для извлечения последующих документов.

Подробнее см. В учебнике по разбиению на страницы: https://docs.fauna.com/fauna/current/tutorials/indexes/pagination

Если нет, то почему бы и нет? Что такое логика c, стоящая за такой конструкцией?

Для базы данных SQL, SELECT * FROM table удобна и потенциально может стать кошмаром ресурсов. Если таблица содержит миллиарды строк, попытка обслужить результаты для этого запроса может потреблять доступные ресурсы на сервере и / или клиенте.

FaunaDB является ресурсом общей базы данных. Мы хотим, чтобы запросы работали хорошо для любого пользователя с любой базой данных, и для этого необходимо установить разумные ограничения на количество документов, участвующих в одной транзакции.

Могу ли я сделать такой запрос без индекса ?

Нет и да.

Для получения нескольких результатов из FaunaDB требуется индекс, если только вы не отслеживаете ссылки на документы независимо. Однако с недавно добавленной функцией Documents (которая в настоящее время находится в режиме предварительного просмотра, поэтому не рекомендуется для рабочих нагрузок.) Теперь мы поддерживаем внутренний индекс, так что вам больше не нужно создавать собственный индекс для доступа ко всем документам в коллекции.

Подробнее см. Справочную страницу «Документы»: https://docs.fauna.com/fauna/current/api/fql/functions/documents

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

let allDocuments = await client.query(
  q.Map(
    q.Paginate(q.Documents(q.Collection("skus"))),
    q.Lambda("X", q.Get(q.Var("X")))
  )
)

Ваше замечание, что FQL многословен, верно. Многие функциональные языки демонстрируют эту многословность. Преимущество состоит в том, что любые функции, которые принимают выражения, могут быть составлены по желанию. Один из лучших примеров компоновки и как управлять ссылками на документы, представлен в нашем руководстве по электронной торговле, в частности, в разделе, описывающем функцию submit_order: https://docs.fauna.com/fauna/current/tutorials/ecommerce#function

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