如何创建可以在不同字段上搜索的 graphql 模式?
Posted
技术标签:
【中文标题】如何创建可以在不同字段上搜索的 graphql 模式?【英文标题】:How to create a graphql schema that can be searched on different fields? 【发布时间】:2015-11-17 06:09:07 【问题描述】:我正在测试 sangria 来构建一个 graphql/relay 服务器。我有一个非常简单的 User 类:
case class User(
id: Int,
username: String,
gender: Gender.Value)
我想允许通过 ID 或用户名进行查询。我已经创建了一个允许这样做的架构,但字段有不同的名称:
val Query = ObjectType(
"Query", fields[UserRepo, Unit](
Field("user", OptionType(User),
arguments = ID :: Nil,
resolve = ctx => ctx.ctx.getUser(ctx arg ID)),
Field("userByUsername", OptionType(User),
arguments = Username :: Nil,
resolve = ctx => ctx.ctx.getUserByUsername(ctx arg Username))
))
不幸的是,我需要使用不同的字段名称来查询这些,user
和 userByUsername
,例如:
curl -G localhost:8080/graphql
--data-urlencode 'query=userByUsername(username: "Leia Skywalker") id, username, gender'
或
curl -G localhost:8080/graph
--data-urlencode "query=user(id: 1025) id, username, gender"
如何创建一个架构,允许在 ID 或用户名上查询名为 user
的单个字段?例如。以下两个都应该返回相同的用户对象:
curl -G localhost:8080/graphql
--data-urlencode 'query=user(username: "Leia Skywalker") id, username, gender'
或
curl -G localhost:8080/graph
--data-urlencode "query=user(id: 1025) id, username, gender"
【问题讨论】:
【参考方案1】:我终于解决了:
val ID = Argument("id", OptionInputType(IntType), description = "id of the user")
val Username = Argument("username", OptionInputType(StringType), description = "username of the user")
val Query = ObjectType(
"Query", fields[UserRepo, Unit](
Field("user", OptionType(User),
arguments = List(ID, Username),
resolve = ctx => ctx.ctx.getUser(ctx.argOpt(ID), ctx.argOpt(Username)))
))
而getUser
看起来像:
def getUser(id: Option[Int], username: Option[String]): Option[User] =
if (id.isEmpty && username.isEmpty)
None
else
id.flatMap(i => users.find(_.id == i))
.orElse(username.flatMap(u => users.find(_.username == u)))
【讨论】:
值得注意的是,现在,如果给定这样的模式,中继将失败并出现验证错误。见github.com/facebook/relay/issues/112以上是关于如何创建可以在不同字段上搜索的 graphql 模式?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 GraphQL 通过 slug 进行搜索? - 字段“文章”上的“未知参数”
如何在 graphql 上正确创建 Id 字段以符合中继标准?