如何从 FaunaDB 的集合中获取所有文档?

Fel*_*Dev 9 node.js faunadb

我已经有了答案:

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) {
    // ...
  }
}
Run Code Online (Sandbox Code Playgroud)

但我发现它并不令人满意,因为我正在为似乎是最微不足道的数据库调用进行 2 次查询。这对我来说似乎效率低下且冗长。

因为我只是在学习 FaunaDB,所以这里可能有一些我不明白的地方。我的问题可以分为3个:

  • 我可以在一次调用中查询所有文档吗?
  • 如果没有,为什么不呢?这样的设计背后的逻辑是什么?
  • 我可以在没有索引的情况下进行这样的查询吗?

Bre*_*oms 15

FaunaDB 的 FQL 语言与 JavaScript 非常相似(如果您想做条件事务等,这会很有帮助)。

本质上,FaunaDB 也有一个 Map。鉴于您的索引仅包含一个作为参考的,您可以这样写:

q.Map(
  q.Paginate(q.Match(q.Index('skus'))),
  q.Lambda(x => q.Get(x))
)
Run Code Online (Sandbox Code Playgroud)

对于这种特定情况,您实际上不需要索引,因为每个集合都有一个内置的默认索引,可以通过“文档”功能进行全选。

q.Map(
  q.Paginate(Documents(Collection('<your collection>'))),
  q.Lambda(x => q.Get(x))
)
Run Code Online (Sandbox Code Playgroud)

现在,如果您使用的索引返回多个值(因为您希望对 'ref' 以外的其他内容进行排序),那么您需要向 Lambda 提供与在指数。假设我的索引有tsref值,因为我想按时对它们进行排序,然后获取所有值的查询变为:

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

值用于范围查询/排序,但也定义索引返回的内容

回到你的问题:

- 我可以在一次调用中查询所有文档吗?

当然,我会建议你这样做。请注意,您将获得的文档会自动分页。您可以通过提供分页参数来设置页面大小,如果页面更大,将返回“之后”或“之前”属性。之后或之前可以再次作为参数呈现给 Paginate 函数以获取下一页或上一页:https : //docs.fauna.com/fauna/current/api/fql/functions/paginate

- 我可以在没有索引的情况下进行这样的查询吗?

不,但您可以使用上述内置索引。FaunaDB 保护用户免于在没有索引的情况下进行查询。由于它是一个可扩展的数据库,可以包含大量数据并且是现收现付的,因此防止用户用脚射击自己是个好主意:)。分页和强制索引有助于做到这一点。

至于为什么 FQL 不同。FQL 是一种不像许多查询语言那样声明性的语言。相反,它是程序性的,你写的究竟如何你获取数据。这有以下优点:

  1. 通过编写如何检索数据,您可以准确预测查询的行为方式,这在现收现付系统中非常有用。
  2. 相同的语言可用于安全规则或复杂的条件事务(根据特定条件更新某些实体或跨越不同集合的许多实体)。在 Fauna 中,编写一个在一个事务中做很多事情的查询是很常见的。
  3. 我们称为用户定义函数的“存储过程”风格只是用 FQL 而不是另一种语言编写的。

本教程还讨论了查询,该教程随附在 GitHub 存储库中的代码,这可能会给您提供更完整的图片:https : //css-tricks.com/rethinking-twitter-as-a-serverless-app/


esk*_*yrd 6

我可以在一次调用中查询所有文档吗?

是的,如果您的收藏很小。该Paginate函数默认为每页获取 64 个文档。您最多可以将页面大小调整为 100,000 个文档。如果您的集合有超过 100,000 个文档,那么您必须执行多个查询,使用游标来获取后续文档。

有关详细信息,请参阅分页教程:https : //docs.fauna.com/fauna/current/tutorials/indexes/pagination

如果没有,为什么不呢?这样的设计背后的逻辑是什么?

对于 SQL 数据库,SELECT * FROM table它既方便又可能是资源噩梦。如果该表包含数十亿行,则尝试为该查询提供结果可能会消耗服务器和/或客户端上的可用资源。

Fauna 是一个共享的数据库资源。我们希望查询对使用任何数据库的任何用户都能很好地执行,这要求我们对任何单个事务中涉及的文档数量设置合理的限制。

我可以在没有索引的情况下进行这样的查询吗?

不,是的。

从 Fauna 检索多个结果需要一个索引,除非您独立跟踪文档的参考。但是,通过该Documents函数,Fauna 维护了一个内部索引,因此您无需创建自己的索引来访问集合中的所有文档。

有关详细信息,请参阅文档参考页面: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")))
  )
)
Run Code Online (Sandbox Code Playgroud)

您对 FQL 冗长的观察是正确的。许多函数式语言都表现出这种冗长。优点是任何接受表达式的函数都可以随意组合。我们的电子商务教程中介绍了可组合性以及如何管理文档间引用的最佳示例之一,特别是描述该submit_order功能的部分:https : //docs.fauna.com/fauna/current/tutorials/电子商务#功能