首页 > 解决方案 > 如何在 FaunaDB 中获取嵌套文档?

问题描述

要在 Fauna 中获取单个文档,我们会:

q.Get(q.Ref(q.Collection('posts'), '192903209792046592'))

我们得到类似的东西:

{
  data: {
    title: 'Lorem ipsum',
    authorId: '892943607792046595'
  }
}

是否可以在同一个查询中获取帖子和作者?

像这样的东西:

{
  data: {
    title: 'Lorem ipsum',
    author: {
      name: 'John Doe'
    }
  }
}

标签: faunadb

解决方案


由于这是一个常见问题,我将对其进行扩展,并为您提供入门所需的所有信息。我最近写了一个例子,很快也会详细说明这一点。

我将逐步构建查询以尽可能地进行教育假设..我们编写了一个类似推特的应用程序并想要检索推文。我们要做的第一件事就是获取推文列表。

首先.. 获取参考

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'),
      }
    )
  )
)

当然.. 如果我们想要获取的东西不是存储的引用但我们想要加入一个属性怎么办?那么想象一下,我们想要获取一条推文上有多个评论?这就是索引的用武之地!

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 中您几乎不能做 :)


推荐阅读