title: How to handle multiple optional arguments in Absinthe GraphQL resolver while constructing a query in a DSL?
body: <p>Imagine a GraphQL query like this:</p>
  
  <pre><code>Query {
    projects(platforms: [String], languages: [String])
  }
  </code></pre>
  
  <p>And a Neo4j graph containing nodes labeled <code>Project</code>, <code>Platform</code> and <code>Language</code>.</p>
  
  <p>When none of the optional arguments are passed, the resolver should return the list of all projects in the graph with no filtering (possibly with pagination in future). When either or all arguments are passed, those should be applied in the underlying query; i.e. we should get projects that are implemented in given languages or for given platforms.</p>
  
  <p>I am using Bolt.Sips driver for Neo4j in my Elixir backend, and this driver offers minimal functionality as for wrapping the Cypher query language, so for the most part I need to write queries on my own. So far I have this implementation of the resolver, since I have yet to implement the second argument:</p>
  
  <pre><code>def get_projects!(_parent, %{languages: _} = args, _resolution) do
    """
    match (node:Project)&lt;-[:LANGUAGE_FOR]-(l:Language)
    where l.name in {props}.languages
    return node
    """
    |&gt; generic_query!(%{props: args})
  end
  
  def get_projects!(_parent, _args, _resolution) do
    get_all_entities_of_type!("Project")
  end
  </code></pre>
  
  <p>where <code>generic_query!/2</code> and <code>get_all_entities_of_type!/1</code> are just wrappers for Bolt.Sips query execution.</p>
  
  <p>My question is: what's the best way to construct a Cypher query in this case? Should I just write a bunch of functions that will construct a query string before execution? Maybe it's just my general lack of GraphQL experience and query schemas like this are to be constructed differently? Any tips would be appreciated.</p>