anchor.diff:  ; => {[:product/brand "Taylor"] #:product{:brand-id 44151}}
   ```
   
  -By using idents as the "attribute" of the join we are providing the initial context. An ident join on `[:product/id 1]`
  -will pre-fill the contextual entity with `{:product/id 1}`, and once that initial context is there the rest of the relational
  -resolvers can be tried to deal with the rest of the query!
  -
  -=== Batch resolvers
  -
  -The N+1 problem, you have it when you are processing a sequence, and each item of the sequence needs some data that
  -require a remote request. Let's see one example to illustrate the situation:
  +=== Multiple inputs
  +
  +The input to a resolver is a set, and as such you can require more than one thing as input to your resolvers.  When doing
  +so, of course, your resolver function will receive all of the inputs requested; however, this also means that the parsing
  +context needs to contain them, or there must exist other resolvers that can use what's in the context to fill them in.
  +
  +=== N+1 Queries and Batch resolvers
  +
  +When you have a to-many relation that is being resolved by a parser you will typically end up with a single query that
  +finds the "IDs", and then `N` more queries to fill in the details of each item in the sequence.  This is known as the
  +`N+1` problem, and can be a source of significant performance problems.
  +
  +The solution is relatively simple in Pathom: Add the `request-cache-plugin` to the parser and include a
  +`::pc/batch true` option in your resolver. Pathom then knows that it *can* send a sub-resolver a sequence of
  +inputs instead of a single one.  If your resolver
  +receives a sequence, then it is expected to return a *vector* of promised outputs instead of a single map.
  +
  +IMPORTANT: You must detect if the input is a sequence and also be ready to handle the case when it is not.
  +
  +Let's see one example to illustrate the situation:
  +
  +NOTE: This example is using Pathom async parsers.  The resolvers in async parsers can return channels that (eventually)
  +resolve to the result, which is why you see `go` blocks in the code.  See <<Async Parsing, AsyncParsing>> for more details.  We use them in this example so we can
  +"sleep" in a Javascript environment to mimic overhead in processing.
   
   [source,clojure]
   ----
  
positive.code: 
  As you can see, `Connect` will fire an error in case your query asks for something and it's not possible to get there.
  
  === Multiple inputs #TODO
  
  === Single input requirements
  
  At the moment we only know how to start a graph query from a "global" resolver.
  
  Another significant entry point for the graph are idents. Since an ident is really a lookup for a distinct entity, it is
  trivial to start a graph query at one. Examples are things like "product by id" and "user by email". It turns out that
  single-input resolvers automatically define how to start a graph query at an ident!
  
  For example we have a resolver to get the brand from the product id: so `:product/id` can be used to find that.
  Also the `:product/brand-id` can be realized from `:product/brand`. Thus, the following ident-join queries already work
  without having to define anything else:
  
  ```clojure
  (parser {} [{[:product/id 1] [:product/brand]}])
  
negative.code: a `:person/id`.  The `my-database` stuff is just made up for this example, and is intended to show you that your
  data source need not remotely match the schema of your graph query.
  
  Pathom will scan through the defined resolvers in order to try to satisfy all of the properties in a query.  So, technically
  you can split up your queries as much as makes sense into separate resolvers, and as long as the inputs are in the context
  Pathom will assemble things back together.
  
  Of course, it doesn't make sense in this case to do so, because each resolver would end up running a new query:
  
  ```
  (defresolver `person-age-resolver
    {::pc/input #{:person/id}
     ::pc/output [:person/age]}
    (fn [{:keys [database] :as env} {:keys [person/id]}]
      (let [person (my-database/get-person database id)]
        {:person/age (:age person)})))
  
  (defresolver `person-first-name-resolver
    {::pc/input #{:person/id}
     ::pc/output [:person/first-name]}
    (fn [{:keys [database] :as env} {:keys [person/id]}]
      (let [person (my-database/get-person database id)]
        {:person/first-name (:first-name person)})))
  
  ...
  ```
  
  The point is that a single-level query like `[:person/id :person/first-name :person/age]` can be satisfied and "folded together"
  by pathom over any number of resolvers.
  
  This fact is the basis of parser (de)composition and extensibility.  It can also come in handy for performance
  refinements when there are computed attributes.
  
  === Derived/Computed Attributes
  
  There are times when you'd like to provide an attribute that is computed in some fashion.  You can, of course, simply
  compute it within the resolver along with other properties like so:
  
  ```
  (defresolver `person-resolver
    {::pc/input #{:person/id}
     ::pc/output [:person/first-name :person/last-name :person/full-name :person/age]}
    (fn [{:keys [database] :as env} {:keys [person/id]}]
      (let [{:keys [age first-name last-name]} (my-database/get-person database id)]
        {:person/age age
         :person/first-name first-name
         :person/last-name last-name
         :person/full-name (str first-name " " last-name) ; COMPUTED
         ... })))
  ```
  
  but this means that you'll take the overhead of the computation when *any* query relate to person comes up.  You can
  instead spread such attributes out into other resolvers as we discussed previously, which will only be invoked if the
  query actually asks for those properties:
  
  ```
  (defresolver `person-resolver
    {::pc/input #{:person/id}
     ::pc/output [:person/first-name :person/last-name :person/age]}
    (fn [{:keys [database] :as env} {:keys [person/id]}]
      (let [{:keys [age first-name last-name]} (my-database/get-person database id)]
        {:person/age age
         :person/first-name first-name
         :person/last-name last-name })))
  
  (defresolver `person-name-resolver
    {::pc/input #{:person/id}
     ::pc/output [:person/full-name]}
    (fn [{:keys [database] :as env} {:keys [person/id]}]
      (let [{:keys [first-name last-name]} (my-database/get-person database id)]
        {:person/full-name (str first-name " " last-name)})))
  ```
  
  This combination of resolvers can still resolve all of the properties in `[:person/full-name :person/age]` (if
  `:person/id` is in the context), but a query for just `[:person/age]` won't invoke any of the logic for the
  `person-name-resolver`.
  
  === Single Inputs -- Establishing Context
  
  So far we have seen how to define a resolver that can work *as long as* the inputs are already in the environment.  You're
  almost certainly wondering how to do that.
  
  One way is to define <<GlobalResolvers,global resolvers>> and start the query from them, but very often you'd just
  like to be able to say "I'd like the first name of person with id 42."
  
  Om Next/Fulcro use "idents" to specify exactly that sort of query:
  
  ```
  [{[:person/id 42] [:person/first-name]}]
  ```
  
  The above is a join on an ident, and the expected result is a map with the ident as a key:
  
  ```
  {[:person/id 42] {:person/name "Joe"}}
  ```
  
  The query *itself* has everything you need to establish the *context* for running the `person-resolver`,
  and in fact that is how Pathom single-input resolvers work.
  
  If you use an ident in a query then Pathom is smart enough to know that it can use that ident to establish the context
  for finding resolvers.  In other words, in the query above the ident `[:person/id 42]` is turned
  into the *parsing context* `{:person/id 42}`, which satisfies the *input* of any resolver that needs
  `:person/id` to run.
  
  === Resolver Without Input -- Global Resolver [[GlobalResolvers]]
  
  A resolver that requires no input can output its results at any point in the graph, thus it is really a global resolver.
  Pay particular note to the qualfication: *any point in the graph*.  Not just root.  Thus, a resolver without inputs
  can "inject" its outputs into any level of the query graph result.
  
  We're going to start building a parser that can satisfy queries about a music store. So, we'll start with a global resolver
  that can resolve the "latest product".  The code below shows the entire code needed, boilerplate and all:
  
  