微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何从 faunadb 中的两个集合中获取数据 重要提示:贷款和用户集合是一对多的关系,一个用户可以申请多笔贷款

如何解决如何从 faunadb 中的两个集合中获取数据 重要提示:贷款和用户集合是一对多的关系,一个用户可以申请多笔贷款

我是 faunadb 的新手。我在从两个集合中查询数据时遇到问题。 我有一个包含以下数据的用户集合。


    {
       "ref": Ref(Collection("users"),"286520131377445052"),"ts": 1609505740440000,"data": {
          "userId": "f35fdc8d-6197-4d19-bf27-256bd41b3751","name": "PRANTA Dutta","email": "pranta@email.com","role": "borrower","password": "somepassword"
       }
    }

然后我有一个带有以下数据的贷款收集


    {
       "ref": Ref(Collection("loans"),"287038065061397005"),"ts": 1609999680495000,"data": {
          "monthlyInstallment": 473.33,"loanDuration": 6,"interestRate": 7,"amount": 2000,"modifiedMonthlyInstallment": 513.33,"mode": "processing","userId": "f35fdc8d-6197-4d19-bf27-256bd41b3751"
      }
}

重要提示:贷款和用户集合是一对多的关系,一个用户可以申请多笔贷款。

现在我想编写一个查询来立即获取具有匹配 userId 的贷款数据,以便我可以完全显示所有数据。

我想要的数据如下:

   "data": {
       "monthlyInstallment": 473.33,"userId": "f35fdc8d-6197-4d19-bf27-256bd41b3751",{
          "data": {
             "userId": "f35fdc8d-6197-4d19-bf27-256bd41b3751","password": "somepassword"
          }
       }
   }

我如何使用 FQL 做到这一点,提前致谢。

解决方法

与直觉相反,Join 不是您所需要的:

我们有一个 Join FQL 功能,但它可能不是您所期望的。联接是从一组引用(例如一组用户引用)通过索引到另一组引用(例如贷款)的遍历。我将其称为“遍历”,因为它本质上将用贷款参考替换用户参考,因此您没有根据需要将数据放在一起。只是想在您浪费时间试图弄清楚如何使用 Join 来做到这一点之前澄清这一点。

相反,结合使用 MapGet 方法

在动物群中,您的想法必须略有不同。想一想您将如何使用常规的程序编程语言执行此操作:“获取所有贷款,映射贷款,针对每笔贷款,获取用户”。

在 FQL 术语中,该描述为:

  • 使用 Paginate(Match(....))
  • 获取文档的初始页面(例如贷款)
  • 使用 Map()Lambda()
  • 循环这些(在 FQL 中,而不是在宿主语言中,它仍然是 ACID)
  • 在 lambda 中:
    • 如果该文档包含对您需要的其他文档的引用 (例如用户),只需使用 Get() 来获取该引用。
    • 如果链接的文档包含引用或者它包含在另一个集合中(例如多对多的对象化关系),则使用索引(例如 Match(Index(... some value ... ))来检索链接的文档. 因为在这种情况下你会收到多个结果。如果它是你期望的一个值,则在该索引上使用 Get 或者如果你期望多个值(你可以在多个级别上进行分页)在索引上分页

可以在此处找到获取嵌套文档和代码的完整说明:

这里已经写出了一个关于如何获取嵌套文档的例子:

How to get nested documents in FaunaDB?

应用于您的示例:

想象一下,你会直接存储用户引用,它会是这样的:

// Disclaimer,didn't test code,sorry if I missed a bracket. 
Map(
  // get loan references
  Paginate(Documents(Collection('loans'))),// map over pages of loan references
  Lambda('loanRef',Let({
        loan: Get(Var('loanRef')),user: Get(Select(['data','userRef'],Var('loan'))),},// And now we can then return whtatever we want (or could have 
      // omitted the let and directly return an object)
      {
        loan: Var('loan'),user: Var('user')
      }
    )
  )
)

由于您已选择使用用户定义的 ID(这很好),因此需要一个额外的步骤。

Map(
  // get loan references
  Paginate(Documents(Collection('loans'))),userId: Select(['data','userId'],Var('loan')),// get on a match assumes the userId exists
        // and that there is only one result (in your case,many-to-one.. 
        // that's fine). It also assumes you have defined that index.
        user: Get(Match(Index("users_by_userid"),Var('userId')))
      },user: Var('user')
      }
    )
  )
)

Map/Get的优势

有点推理为什么它会这样工作。在 Fauna 中,您有对 Sets 进行操作的操作,这些操作是对数据外观的描述,然后您对 Set 进行分页以实际获取数据页。

  • Join: 想象一下,我们将有一个类似 SQL 的连接,然后对该结果集调用 Paginate。第一个页面可能只包含一个用户和 10000 笔贷款(好吧.. 在这个特定场景中不太可能,但想象一下您与用户和推文打交道的例子)。这可能不是您想要的,而且(我假设)还有性能/复杂性的原因没有提供这样的功能(类 SQL 的连接特别难以扩展)。

  • Map/Get 另一方面,强制分页的 map/get 方式更具可扩展性,从用户的角度来看也非常漂亮。它使您可以控制多个级别的分页。在这种情况下,您将获得一个包含 100 个用户的页面(假设我们的 pagesize = 100),然后(假设我们的第二个 pagesize = 10,我们可以单独决定)每个用户 10 笔贷款。如果有超过 100 个用户,您会得到一个后光标以继续(或者您可以将页面大小增加到 100000)。如果某个用户有更多贷款,您将为每个用户获得一个后游标,并且可以单独控制从哪个用户获取更多数据。这可确保您作为用户拥有灵活性,同时确保性能并避免必须获取大量数据,以防您的联接具有导致结果集爆炸的高基数关系。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。