gpt4 book ai didi

faunadb - 如何在 Fauna DB 上高效查询和过滤?

转载 作者:行者123 更新时间:2023-12-02 02:00:21 25 4
gpt4 key购买 nike

例如,假设我们有一个包含数十万份客户文档的集合,其中包含 3 个字段:name、monthly_salary 和 age。

如何查询monthly_salary大于2000,age大于30的文档?

在 SQL 中,这很简单,但对于 Fauna,我很难理解最佳方法,因为索引项仅适用于完全匹配。我在文档中看到我可以使用 Filter 函数,但我需要提前获取所有文档,所以它看起来有点违反直觉而且性能不佳。

下面是我如何实现它的示例,但不确定这是否是最佳方法,尤其是当它包含大量记录时。

Map(
Filter(
Paginate(Documents(Collection('clients'))),
Lambda(
'client',
And(
GT(Select(['data', 'monthly_salary'], Get(Var('client'))), 2000),
GT(Select(['data', 'age'], Get(Var('client'))), 30),
)
)
),
Lambda(
'filteredClients',
Get(Var('filteredClients'))
)

)


这是正确的还是我遗漏了一些关于动物群和 FQL 的基本概念?谁能帮忙?

提前致谢

最佳答案

使用索引执行高效搜索。您可以查看 search with Indexes 的文档, 和 there is a "cookbook"对于一些不同的搜索示例。

有两种使用索引进行搜索的方式,使用哪种方式取决于您搜索的是equality(完全匹配)还是inequality(大于或等于小于,例如)。

寻找平等

如果您需要完全匹配,请使用索引术语。这在文档中是最明确的,这也不是您最初的问题所在,因此我不会在这里过多赘述。但这里有一个简单的例子

给定具有这种形状的用户文档

{
ref: Ref(Collection("User"), "1234"),
ts: 16934907826026,
data: {
name: "John Doe",
email: "jdoe@example.com,
age: 50,
monthly_salary: 3000
}
}

和如下定义的索引

CreateIndex({
name: "users_by_email",
source: Collection("User"),
terms: [ { field: ["data", "email"] } ],
unique: true // user emails are unique
})

您可以搜索与...完全匹配的 Match function !

Get(
Match(Index("user_by_email"), "jdoe@example.com")
)

寻找不平等

寻找不等式更有趣也更复杂。它需要使用 Index valuesRange function .

根据上面的文档,我们可以创建一个新的索引

CreateIndex({
name: "users__sorted_by_monthly_salary",
source: Collection("User"),
values: [
{ field: ["data", "monthly_salary"] },
{ field: ["ref"] }
]
})

请注意,我没有在上面的索引中定义任何术语。对于不等式,重要的还是。我们还将 ref 作为一个值包含在内,因为我们稍后会需要它。

现在我们可以使用Range 来获取给定范围内的所有用户的薪水。此查询将获取薪水从 2000 开始及以上的所有用户。

Paginate(
Range(
Match(Index("users__sorted_by_monthly_salary")),
[2000],
[]
)
)

合并索引

对于“或”操作,使用 Union function .对于“AND”操作,使用 Intersection function .

MatchRange 等函数返回集合。其中一个非常重要的部分是确保当您将 Set 与 Intersection 等函数“组合”时,数据的形状是相同的。

对于没有的索引,使用相同形状的集合并不困难,它们默认为相同的单个引用值。

Paginate(
Intersection(
Match(Index("user_by_age"), 50), // type is Set<Ref>
Match(Index("user_by_monthly_salary, 3000) // type is Set<Ref>
)
)

当 Set 具有不同的形状时,它们需要修改,否则 Intersection 将永远不会返回结果

Paginate(
Intersection(
Range(
Match(Index("users__sorted_by_age")),
[30],
[]
), // type is Set<[age, Ref]>
Range(
Match(Index("users__sorted_by_monthly_salary")),
[2000],
[]
) // type is Set<[salary, Ref]>
)
)

{
data: [] // Intersection is empty
}

那么我们如何改变 Set 的形状使它们相交呢?我们可以使用 Join function , 以及 Singleton function .

Join 将对 Set 中的所有条目运行操作。我们将使用它来仅返回一个引用。

Join(
Range(Match(Index("users__sorted_by_age")), [30], []),
Lambda(["age", "ref"], Singleton(Var("ref")))
)

总而言之:

Paginate(
Intersection(
Join(
Range(Match(Index("users__sorted_by_age")), [30], []),
Lambda(["age", "ref"], Singleton(Var("ref")))
),
Join(
Range(Match(Index("users__sorted_by_monthly_salary")), [2000], []),
Lambda(["age", "ref"], Singleton(Var("ref")))
)
)
)

合并索引的技巧

当提供不同的术语时,您可以使用额外的逻辑来组合不同的索引,或者使用绑定(bind)搜索缺失的字段。您可以做很多很酷的事情。

请查看 cook bookFauna forums以及想法。

但是为什么!!!

这是个好问题!

考虑一下:由于 Fauna 是作为无服务器 API 提供的,因此您需要为文档和索引上的每个单独读取和写入以及执行查询的计算时间付费。 SQL 可以简单得多,但它是一种高级得多的语言。 SQL 的背后是一个查询规划器,它对如何获取数据做出假设。如果它不能有效地执行此操作,它可能会默认扫描您的整个数据表或以其他方式执行比您预期的成本高得多的操作。

有了 Fauna,您就是查询规划师。这意味着开始要复杂得多,但这也意味着您可以很好地控制数据库的性能,从而控制成本。

我们正在努力改进定义架构和您需要的索引的体验,但目前您必须在低级别定义这些查询。

关于faunadb - 如何在 Fauna DB 上高效查询和过滤?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69065039/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com