如何在 FaunaDB 中获取嵌套文档?
Posted
技术标签:
【中文标题】如何在 FaunaDB 中获取嵌套文档?【英文标题】:How to get nested documents in FaunaDB? 【发布时间】:2020-07-21 02:46:42 【问题描述】:要在 Fauna 中获取单个文档,我们这样做:
q.Get(q.Ref(q.Collection('posts'), '192903209792046592'))
我们得到类似的东西:
data:
title: 'Lorem ipsum',
authorId: '892943607792046595'
是否可以在同一个查询中获取帖子和作者?
类似这样的:
data:
title: 'Lorem ipsum',
author:
name: 'John Doe'
【问题讨论】:
【参考方案1】:所以首先,最好将 refs 存储在文档中,而不是 ids。
在问题中存储示例帖子时,它应该是这样的(使用 JS 驱动程序):
title: 'Lorem ipsum',
authorRef: q.Ref(q.Collection("authors"), "1234556456858234")
然后要获得包含嵌套作者的帖子,您需要使用Let
创建自定义对象。
应该是这样的(再次使用 JS 驱动程序):
q.Let(
postDoc: q.Get(q.Ref(Collection('posts'), '192903209792046592')),
authorRef: q.Select(['data', 'authorRef'], q.Var('postDoc')),
authorDoc: q.Get(q.Var('authorRef')),
,
title: q.Select(['data', 'title'], q.Var('postDoc')),
author:
name: q.Select(['data', 'name'], q.Var('authorDoc')),
)
哪个会返回:
title: 'Lorem ipsum',
author:
name: 'John Doe'
另一种选择是简单地并排返回两个完整文档:
q.Let(
postDoc: q.Get(q.Ref(Collection('posts'), '192903209792046592')),
authorRef: q.Select(['data', 'authorRef'], q.Var('postDoc'))
,
postDoc: q.Var('postDoc'),
authorDoc: q.Get(q.Var('authorRef')),
)
【讨论】:
很好的答案,码头!【参考方案2】:由于这是一个常见问题,我将对其进行扩展,并为您提供入门所需的所有信息。我最近写了一个例子,很快也会详细说明这一点。
我将逐步构建查询以尽可能地具有教育意义 假设..我们编写了一个类似推特的应用程序并想要检索推文。 我们要做的第一件事就是获取推文列表。
首先.. 获取参考
Paginate(Documents(Collection('fweets')))
返回引用列表
...或索引值
Paginate(Documents(Index('some_index')))
它返回您在创建索引时选择的所有值,例如:[[value1, value2], ...]
这将返回一个参考页面,或者本质上是一个参考列表。
使用 Get 获取列表的实际文档
然后您按照您在问题中所做的操作,通过使用 Map 映射参考来获取参考(并且 Map 将成为您回答问题的主力,因为我们走得更远)
Map(
Paginate(Documents(Collection('fweets'))),
Lambda('ref', Var('ref'))
)
转换这些文档以获取其他数据(您的具体问题)
您可以使用与我们获取引用、映射文档完全相同的技术。只是现在我们会对指向其他集合的引用执行 Get。想象一下,我的每条推文中都有一个作者,让我们找到那个作者。我们将让用户 Let 构建我们的查询并逐步进行 让我们首先用 Let 重构我们的查询
Map(
Paginate(Documents(Collection('fweets'))),
// and in this function, the magic will happen, for now we just return the tweet.
Lambda('f',
Let(
fweet: Get(Var('f'))
,
Var('fweet')
)
)
)
我们现在将添加一行来获取作者。
Map(
Paginate(Documents(Collection('fweets'))),
// and in this function, the magic will happen
Lambda('f',
Let(
fweet: Get(Var('f')),
author: Get(Select(['data', 'author'], Var('fweet'))), // we get the author reference
,
// And now we return a nested doc
fweet: Var('fweet'),
author: Var('author')
)
)
)
这将返回:
[
"fweet":
< your tweet data >
,
"author":
< your author data >
, ... ]
现在我们有了这个结构,添加一些额外的东西很容易。想象一下,我们还有一条“资产”推文链接到我们在推文中存储引用的推文
Map(
Paginate(Documents(Collection('fweets'))),
Lambda('f',
Let(
fweet: Get(Var('f')),
author: Get(Select(['data', 'author'], Var('fweet'))),
asset: Get(Select(['data', 'asset'], Var('fweet')))
,
// And now we return a nested doc
fweet: Var('fweet'),
author: Var('author'),
asset: Var('asset'),
)
)
)
当然.. 如果我们想要获取的不是存储的引用,而是想要加入一个属性怎么办?那么想象一下,我们想要获取的推文上有多个 cmet 吗?这就是索引的用武之地!
Map(
Paginate(Documents(Collection('fweets'))),
Lambda('f',
Let(
fweet: Get(Var('f')),
author: Get(Select(['data', 'author'], Var('fweet'))),
asset: Get(Select(['data', 'asset'], Var('fweet'))),
comments: Map(
Paginate(Match(Index('comments_by_fweet_ordered'), Var('f'))),
Lambda(
// my index has two values, I only need the comment reference but adding the ts makes them appear in order!
['ts', 'commentref'],
Get(Var('commentref'))
)
)
,
// And now we return a nested doc
fweet: Var('fweet'),
author: Var('author'),
asset: Var('asset'),
comments: Var('comments')
)
)
)
就这样......您可以逐渐增加复杂性并执行非常复杂的查询。我的应用程序中的查询继续以获取诸如推文统计信息之类的内容,甚至是原始推文(如果它是转推) 实际上,在 FQL 中你不能做的事情很少:)
【讨论】:
你的回答比较好,我会把它标记为正确的。谢谢布莱希特! 顺便说一句,这里是新Documents
函数的文档:docs.fauna.com/fauna/current/api/fql/functions/documents
感谢 Pier,在每种情况下,感谢您花时间帮助社区;)
FQL 是最好的!以上是关于如何在 FaunaDB 中获取嵌套文档?的主要内容,如果未能解决你的问题,请参考以下文章
在 FaunaDB 中更新记录时,如何在不传入每个字段和子对象的情况下更新一个字段?