对带有不同操作数的graphql中的许多键进行可选过滤

时间:2019-07-19 22:48:22

标签: typescript graphql

我有一个字符类型,在这里我想基于指定的键属性和带有值的链接操作数进行一些可选过滤。我当前的问题是玩家应该能够过滤角色,以便他们找到最适合他们的角色。

我刚刚开始使用Graphql,并希望将这个问题用作研究以制作一些小型项目。目前,我正在尝试将一些简单的MySQL查询转换为Graphql并具有基本的功能,但是找不到适合我的用例的任何多重过滤选项。我希望对GraphQl有更多经验的人能对我的研究有所帮助。

现在在Typescript + MySQL中如何设置过滤条件如下:

async getFilteredData(filter: FilterObject): Promise<Charater[]> {

   let query = "SELECT * FROM Character ";
   if (filter.age && filter.age.value) {
      query += `WHERE age ${filter.age.operand} ${filter.age.value} `;
   }
   ... // And so on for every column in the Character table
   try {
      const filteredCharacters: Characters[] = await getConnection().query(query);
      return filteredCharacters;
   } catch(error) {
      console.log("ERROR_DURING_CHARACTER_FILTERING: ", error);
      return [];
   }
}

我已经应用了一些东西来防止SQL注入和其他东西。上面的示例仅是为了使您了解我到目前为止的情况。

现在,我尝试在GraphQl中进行翻译,并认为我不需要整个繁琐的方法。但是到目前为止,我一直在寻找示例,但似乎找不到与我一直在讨论的用例相近的示例。

在这里您可以看到我如何定义字符类型。

type Query {
  character: [Character]
}

type Character {
  id: ID
  name: String
  age: Int
  cashpile: Float
  bonus: Int
  account_created_on: Int 
  total_earned: Float
  total_spend: Float
  strength: Int
  defence: Int
  healthpoints: Int
  victories: Int
  defeats: Int
}

以下是查询正确字符时广泛使用的查询过滤器:

SELECT * FROM Character
WHERE age > 5
AND total_spend < 10000
AND defence > 10
AND healthpoints> 120
AND defeats < 100
AND victories > 200

SELECT * FROM Character
WHERE age < 10
AND total_spend > 10000
AND defence = 27
AND healthpoints > 180
AND strength > 120

或者只是简单的搜索,例如

SELECT * FROM Character
WHERE name LIKE "arg%"

我对Graphql的初步理解和过滤类似于以下示例

query {
   Character {
      id
      name
      defence: equal(27)
      strength: greaterThenOrEqual(120)
   }
}

我希望有这样的事情。需要其他人如何解决此问题的指导。

1 个答案:

答案 0 :(得分:0)

您尝试执行的操作不需要特殊的语法-只需将一个或多个参数与适当的输入类型一起使用就足够了。这是我在一个项目中处理它的方式:

type Query {
  characters(filter: CharacterFilter!): [Character!]!
}

input CharacterFilter {
  age_eq: Int
  age_not_eq: Int
  age_gt: Int
  age_gte: Int
  age_lt: Int
  age_lte: Int
  age_in: [Int!]
  age_not_in: [Int!]
  name_eq: String
  name_not_eq: String
  name_like: String
  name_not_like: String
  name_iLike: String
  name_not_iLike: String
  name_in: [String!]
  name_not_in: [String!]  
  # and so on for the remaining attributes
  and: [CharacterFilter!]
  or: [CharacterFilter!]
}

递归andor字段为我们在构造基础SQL时提供了很大的灵活性。例如,我们可以编写如下查询:

query {
  characters(filter: {
    name_like: "Bob",
    or: [
      strength_gt: 10,
      and: [
        defense_lte: 20,
        healthpoints_lt: 100
      ],
    ],
  }) {
    id
  }
}

这种模式(从Prisma借来)只是我的偏爱。例如,Hasura使用a different pattern 依赖更多的嵌套输入类型。还有许多其他替代模式,实际上并没有一个既定的惯例,这只是一个问题,对于您的后端以及将使用该API的客户端来说,什么才有意义。