graphqlsangria

clean way to get same field by different key


Here is the problem. I can get member by ID and my query looks like below:

{
  member(memberId:[1,2]) {
    firstName
    lastName
    contacts {
    }
  }
}

Now I need to add few more query to get member by name and email like below

   {
      member(email:["abc@xy.com","adc@xy.com"]) {
        firstName
        lastName
        contacts {
        }
      }
    }

   {
      member(name:["abc","adc"]) {
        firstName
        lastName
        contacts {
        }
      }
    }

How do I design my graphQL query and schema? Should my query have just 1 field with multiple optional arguments? like below

Field("member", ListType(Member),
        arguments = ids :: email :: name,
        resolve = (ctx) => {
          val id : Seq[Int] = ctx.arg("memberId")
          ctx.ctx.getMemberDetails(id)
        })

Or should I have multiple query with different field under a schema. like below

  Field("memberById", ListType(Member),
    arguments = Id :: Nil,
    resolve = (ctx) => {
      val id : Seq[Int] = ctx.arg("memberId")
      ctx.ctx.getMemberDetails(id)
    })
  Field("memberByEmail", ListType(Member),
    arguments = email :: Nil,
    resolve = (ctx) => {
      val id : Seq[Int] = ctx.arg("memberId")
      ctx.ctx.getMemberDetails(id)
    })
  Field("memberByName", ListType(Member),
    arguments = name :: Nil,
    resolve = (ctx) => {
      val id : Seq[Int] = ctx.arg("memberId")
      ctx.ctx.getMemberDetails(id)
    })

Thank you in advance. let me know in case you need more details.


Solution

  • You should think about advantanges and disadvantages of both solutions. If you will prepare separate fields, you will get a lot of boilerplate.

    On the other hand you can set all possible inputs as OptionalInputType, it makes schema field only. Disadvantage of this solutions is that Sangria cannot validate a field that at least one argument should be required, so you have to cover this case with proper response or whatever.

    The third option is to make generic solution at Schema level. You can create a query with two arguments filterName and filterValues, first would be EnumType for Id, Email, Name, the second would be a list of strings.

    Such solution avoid disadvantages of both previous solutions, it has required fields and it doesn't need spreading fields in schema for every filter. Additionally if you want to add any additional function you have only edit FilterName enum and a resolver function to cover this.

    Finally you schema will looks like this:

    enum FilterName {
      ID
      EMAIL
      NAME
    }
    
    type Query {
      member(filterName: FilterName!, filterValues: [String]!): Member!
    }