【问题标题】:How to get nested documents in FaunaDB?如何在 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'
    }
  }
}

【问题讨论】:

    标签: faunadb


    【解决方案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 是最好的!
    猜你喜欢
    • 2022-07-16
    • 2021-04-07
    • 1970-01-01
    • 2020-08-12
    • 2020-09-18
    • 2021-01-12
    • 1970-01-01
    • 2016-07-11
    • 1970-01-01
    相关资源
    最近更新 更多