Which syntax for filtering queries in Graphiql?

kranz picture kranz · Jan 19, 2018 · Viewed 14.3k times · Source

New to graphql and started playing with graphiql. I have a Product data type

  type Product {
    _id: String
    name: String
    price: Float
  }

I have mongodb populated with some products

{ "_id" : ObjectId("5a61b31e009c0bef5d724a47"), "name" : "GROUND COFFEE", "price" : 3.06 }
{ "_id" : ObjectId("5a61b31e009c0bef5d724a48"), "name" : "PORK SAUSAGES 500g",  "price" : 4.39 }
{ "_id" : ObjectId("5a61b31e009c0bef5d724a49"), "name" : "MILK UHT 1LT", "price" : 1.29 }
{ "_id" : ObjectId("5a61b31e009c0bef5d724a4a"), "name" : "HEINEKEN PREMIUM LIGHT 33CL", "price" : 1.61 }

In graphiql I can execute a query like this

query {
  products{
     name,
    price
  }
}

Query result is

{
  "data": {
    "products": [
      { "name" : "GROUND COFFEE", "price" : 3.06 },
      { "name" : "PORK SAUSAGES 500g",  "price" : 4.39  },
      { "name" : "MILK UHT 1LT", "price" : 1.29 },
      { "name" : "HEINEKEN PREMIUM LIGHT 33CL", "price" : 1.61 }
    ]
  }
}

Wow, that's fine. So next step is: now I want only products with price greater than 2.0 And I face two problems I do not know how to solve

1) Which is the correct syntax to implement filtering?
2) How comparison operators have to be specified? And how this specification maps to mongodb comparison operators?

I tried with

query {
  products(filter:{price: {gt:2.0} }){
     name,
    price
  }
}

but I get an error for "filter":

Unknown argument "filter" on field "products" of type "Query". I find no way to do this ...

UPDATE @diego

const typeDefs = [`
  type Query {
    product(_id: String): Product
    products: [Product]
  }

  type Product {
    _id: String
    name: String
    price: Float
  }

  type Mutation {
    createProduct(name: String, price: Float): Product
  }

  schema {
    query: Query
    mutation: Mutation
  }
`];

const resolvers = {
  Query: {
    product: async (root, {_id}) => {
      return prepare(await Products.findOne(ObjectId(_id)))
    },
    products: async () => {
      return (await Products.find({}).toArray()).map(prepare)
    },
  },
  Mutation: {
    createProduct: async (root, args, context, info) => {
      const res = await Products.insert(args)
      return prepare(await Products.findOne({_id: res.insertedIds[1]}))
    },
  },
}

Answer

Diego picture Diego · Jan 19, 2018

First you would need to change the Query type definition

products(filter: String): [Product]

Now it accepts a string filter and you can use it in the resolver

products: async (_, {filter}) => {
  const query = JSON.parse(filter)
  return (await Products.find(query).toArray()).map(prepare)
}

Then you can call your query like:

query {
  products(filter: "{\"price\": {\"gt\":2.0} }") {
    name,
    price
  }
}

I do not know if there is a way to do this without changing the query itself.