在 graphql 中按时间过滤(使用 faunaDB 服务)

noi*_*i.m 2 graphql faunadb

我的 graphQL 架构如下所示,

type Todo {
  name: String!
  created_at: Time
}

type Query {
  allTodos: [Todo!]!
  todosByCreatedAtFlag(created_at: Time!): [Todo!]!
}
Run Code Online (Sandbox Code Playgroud)

此查询有效。

query {  
  todosByCreatedAtFlag(created_at: "2017-02-08T16:10:33Z") {
    data {
      _id
      name
      created_at
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

谁能指出我如何在graphql(使用faunaDB)中创建大于(或小于)时间查询。

Bre*_*oms 7

不支持 GraphQL 范围查询(但……他们来了!)

FaunaDB 不提供开箱即用的GraphQL范围查询,我们正在研究这些功能。

.. 但有一个解决方法。

这并不意味着它不能进行范围查询,因为FQL支持范围查询,并且您始终可以通过编写用户定义函数 (UDF) 从 GraphQL 到 FQL 来实现更高级的查询。

.. 使用解析器

通过在架构中使用@resolver关键字,您可以通过在 FQL 中的 FaunaDB 中编写用户定义函数来自己实现 GraphQL 查询。文档中有一些基本的例子 bt 我想你可能需要一些帮助,所以我会给你写一个简单的例子。

我添加了您的架构并添加了两个文档: 在此处输入图片说明

首先,我们的架构将使用解析器进行扩展:

type Todo {
  name: String!
  created_at: Time
}

type Query {
  allTodos: [Todo!]!
  todosByCreatedAtFlag(created_at: Time!): [Todo!]!
  todosByCreatedRange(before: Time, after:Time): [Todo!]! @resolver
}
Run Code Online (Sandbox Code Playgroud)

所有这些只是添加一个函数供我们实现: 在此处输入图片说明

如果我们通过 GraphQL 调用,我们会得到我们之前在屏幕截图中看到的 Abort 消息,因为它尚未实现。但是我们可以看到,GraphQL 语句实际上调用了该函数。

在此处输入图片说明

.. UDF 实现

我们要做的第一件事是添加一个参数,它只是写一个名字作为 lambda 的第一个参数: 在此处输入图片说明

如果您需要传递多个参数(我在架构中定义的解析器中执行此操作),它还需要一个数组: 在此处输入图片说明

我们将添加一个索引来支持我们的查询。值用于范围(以及返回值和排序)。我们将添加 created_at 以覆盖它并添加ref ,因为我们需要返回值来获取索引后面的实际文档。 在此处输入图片说明

然后我们可以从编写一个简单的函数开始(现在还不能工作)

type Todo {
  name: String!
  created_at: Time
}

type Query {
  allTodos: [Todo!]!
  todosByCreatedAtFlag(created_at: Time!): [Todo!]!
  todosByCreatedRange(before: Time, after:Time): [Todo!]! @resolver
}
Run Code Online (Sandbox Code Playgroud)

并且可以通过 shell 手动调用该函数来测试这一点。

在此处输入图片说明

这确实返回了两个对象(范围包括在内)。当然,有一个问题与此,它并没有在GraphQL预期,所以我们会得到这些奇怪的错误结构返回数据: 在此处输入图片说明

我们现在可以做两件事,要么在我们的 Schema 中定义一个适合这些类型的类型和/或我们可以调整返回的数据。我们将做后者并将我们的结果调整为预期的 [Todo!]!结果给你看。

第一步,映射结果。我们在这里唯一介绍的是 Map 和 Lambda。我们还没有做任何特别的事情,我们只是返回引用而不是 ts 和引用作为示例。

Query(
      Lambda(
        ["before", "after"],
        Paginate(
          Range(Match(Index("todosByCreatedAtRange")), Var("before"), Var("after"))
        )
      )
    )
Run Code Online (Sandbox Code Playgroud)

调用它确实表明该函数现在只返回引用。 在此处输入图片说明

让我们得到实际的文件。我知道 FQL 很冗长(并且有充分的理由,尽管将来它应该变得不那么冗长)所以我开始添加注释以澄清事情

Query(
  Lambda(
    ["before", "after"],
    Map(
      Paginate(
        Range(
          Match(Index("todosByCreatedAtRange")),
          Var("before"),
          Var("after")
        )
      ),
      Lambda(["created_at", "ref"], Var("ref"))
    )
  )
)
Run Code Online (Sandbox Code Playgroud)

我们的函数现在返回数据.. woohoo! 在此处输入图片说明

我们仍然需要确保这些数据符合 GraphQL 的期望,并且从架构中我们可以看到它期望一个 [Todo!]!(参见文档选项卡)和一个 Todo 看起来像(参见架构选项卡):

Query(
  Lambda(
    ["before", "after"],
    Map(
      // This is just the query to get your range
      Paginate(
        Range(
          Match(Index("todosByCreatedAtRange")),
          Var("before"),
          Var("after")
        )
      ),
      
      // This is a function that will be executed on each result (with the help of Map)
      Lambda(["created_at", "ref"], 
        // We'll use Let to structure our queries ( allowing us to use varaibles )
        Let({ 
          todo: Get(Var("ref")) 
        }, 
        // And then we return something
        Var("todo")))
    )
  )
)
Run Code Online (Sandbox Code Playgroud)

您还可以从该文档选项卡中看到,“非解析器”查询会自动更改为返回 TodoPages。到目前为止我们编写的函数实际上是返回页面。

选项 1,更改架构并将其转换为分页解析器。

我们可以通过向解析器添加 paginated: true 选项来解决这个问题。你将不得不考虑对将被添加到解析器解释为额外的参数在这里。我自己还没有尝试过,所以我不能 100% 确定它会如何工作。分页解析的优点是您可以立即利用 GraphQL 端点中的合理分页。

选项2,把它变成非分页结果。

分页结果如下所示:{ data: [ document1, document2, .. ], before: ... after: .. }

结果不接受页面而是一个数组,所以我将更改它并检索数据字段:

在此处输入图片说明

我们有我们的结果。 在此处输入图片说明

完整的查询如下所示:

type Todo {
  _id: ID!
  _ts: Long!
  name: String!
  created_at: Time
}
Run Code Online (Sandbox Code Playgroud)

免责声明

一旦你自定义,分页也成为你的责任(例如传递一个额外的参数)。您不能再像通常那样通过请求 GraphQL 主体中的关系来立即获取关系。

关于 UDF 的好处和 GraphQL/FQL 混合的一些话

在您回避 FQL 之前(是的,我们确实必须添加范围查询并正在努力),这里有一些关于 UDF 方法的一般解释以及为什么无论如何考虑它是有意义的。

在某个时刻,您会遇到 GraphQL 中不可能发生的事情(复杂的条件事务,例如更新文档并仅在上次更新的结果为真时才更新其他文档)。使用其他 GraphQL 实现的用户通常通过编写无服务器函数来解决这个问题,以防您必须实现高级逻辑或事务。

FaunaDB 对此的回答是使用他们的用户定义函数 (UDF)。这不是无服务器功能,它是在 FQL 中实现的 FaunaDB 功能,乍一看似乎很麻烦,但重要的是要意识到它为您提供了相同的好处(多区域/强一致性/可扩展性/免费层/即付即用) You-go) 由 FaunaDB 提供。

  • @Danf,可能有多种原因,我的第一个猜测是有一个权限规则阻止您访问您尝试访问的内容(某些权限规则会过滤而不是抛出错误)。您也许可以在我们的论坛上找到有关权限规则如何与 GraphQL 结合使用的信息:https://forums.fauna.com/ (2认同)
  • 不客气,我很高兴有人发现答案有帮助,这才是最重要的:) (2认同)