如何加入 Fauna DB 中的两个集合

How to join two collections in Fauna DB

我是 FaunaDb FQL 的新手,我试图通过索引从 2 个集合中查询数据,但我就是不明白。我从 FaunaDB GUI 创建了索引:

索引 #1 (users_waitlist)(无条款):

索引 #2(产品)(无条款)

在用户集合中,当用户订阅产品的候补名单时,我们将 waitlist_meta 更改为产品参考,因此,我创建了 users_waitlist 索引。

如果我这样查询:

Paginate(Match(Index('users_waitlist')))

它的工作原理是给我 users_waitlist 索引中的所有文档

但是我怎样才能同时检索 users_waitlist 中引用的产品索引中的文档?

我希望我的问题是有道理的,我真的很感谢你提前

对于这个答案,我创建了一些与您所概述的相似的示例数据:

> CreateCollection({ name: "users" })
{
  ref: Collection("users"),
  ts: 1642027810090000,
  history_days: 30,
  name: 'users'
}

> CreateCollection({ name: "products" })
{
  ref: Collection("products"),
  ts: 1642027821280000,
  history_days: 30,
  name: 'products'
}

> Create(
  Collection("products"),
  {
    data: {
      name: "grapple grommets",
      dateStart: Now(),
      dateEnd: TimeAdd(Now(), 30, "days"),
    }
  }
)
{
  ref: Ref(Collection("products"), "320622240400933376"),
  ts: 1642028045960000,
  data: {
    name: 'grapple grommets',
    dateStart: Time("2022-01-12T22:54:05.933Z"),
    dateEnd: Time("2022-02-11T22:54:05.933Z")
  }
}

> Create(
  Collection("users"),
  {
    data: {
      first_name: "Test",
      last_name: "User",
      email: "test@test.test",
      mobile_number: "+1 (123) 456-7890",
      product: Ref(Collection("products"), "320622240400933376")
    }
  }
)

{
  ref: Index("users_waitlist"),
  ts: 1642029519070000,
  active: true,
  serialized: true,
  name: 'users_waitlist',
  source: Collection("users"),
  values: [
    { field: [ 'data', 'product' ] },
    { field: [ 'data', 'first_name' ] },
    { field: [ 'data', 'last_name' ] },
    { field: [ 'data', 'email' ] },
    { field: [ 'data', 'mobile_number' ] },
    { field: [ 'ref' ] }
  ],
  partitions: 8
}
{
  ref: Index("users_waitlist"),
  ts: 1642028625760000,
  active: true,
  serialized: true,
  name: 'users_waitlist',
  source: Collection("users"),
  values: [
    { field: [ 'data', 'product' ] },
    { field: [ 'data', 'first_name' ] },
    { field: [ 'data', 'last_name' ] },
    { field: [ 'data', 'email' ] },
    { field: [ 'data', 'mobile_number' ] },
 
  ],
  partitions: 8
}

有了它,您的示例查询将按预期工作:

> Paginate(Match(Index("users_waitlist")))
{
  data: [
    [
      Ref(Collection("products"), "320622240400933376"),
      'Test',
      'User',
      'test@test.test',
      '+1 (123) 456-7890'
    ]
  ]
}

我们需要修改查询以同时检索关联的产品。这应该如何反映在结果中?由于可能会有多个用户,每个用户都有一个关联的产品,一种解决方案是 return 一个包含关联产品文档的对象。

为此,我们需要使用 Map 遍历所有分页结果,然后使用 Let 对产品文档执行 Get 并为结果组成一个对象。像这样:

Map(
  Paginate(Match(Index("users_waitlist"))),
  Lambda(
    [ "product_ref", "first", "last", "email", "mobile", "ref" ],
    Let(
      {
        product: Get(Var("product_ref")),
      },
      {
        product: Var("product"),
        first_name: Var("first"),
        last_name: Var("last"),
        email: Var("email"),
        mobile_number: Var("mobile"),
        ref: Var("ref"),
      }
    )
  )
)
{
  data: [
    {
      product: {
        ref: Ref(Collection("products"), "320622240400933376"),
        ts: 1642028045960000,
        data: {
          name: 'grapple grommets',
          dateStart: Time("2022-01-12T22:54:05.933Z"),
          dateEnd: Time("2022-02-11T22:54:05.933Z")
        }
      },
      first_name: 'Test',
      last_name: 'User',
      email: 'test@test.test',
      mobile_number: '+1 (123) 456-7890',
      ref: Ref(Collection("users"), "320622637091914240")
    }
  ]
}

尽管 FQL 相当冗长和复杂,但它具有强大的功能来以您需要的任何方式组合结果。

更新:如果文档没有引用集,盲目尝试获取文档会导致错误。您可以通过首先检查存储引用的字段是否实际具有引用以及该引用是否存在来防止出现这种情况。

为此,请替换查询中的这一行:

        product: Get(Var("product_ref")),

与:

        product: If(
          IsRef(Var("product_ref")),
          If(
            Exists(Var("product_ref")),
            Get(Var("product_ref")),
            {}
          ),
          {},
        ),

如果 product 不是引用,或者引用不存在,则值 returned 是一个空对象。