ember-graphql-adapter icon indicating copy to clipboard operation
ember-graphql-adapter copied to clipboard

Full object graph always requested?

Open jc00ke opened this issue 9 years ago • 14 comments

We're seeing that all of the relationships are passed through, which doesn't seem like it jives with GraphQL as a "only what the client needs" query language.

Is there a way I'm not seeing, or plans to be able, to specify which fields should be returned?

Thanks!

jc00ke avatar Aug 10 '16 18:08 jc00ke

Hey @jc00ke thanks for reporting this. Just to be sure we're talking about the same thing, is your use case regarding partial field selections?

For example, a blog post has an author and your page only needs the name of the author, so there's no need to load any of the other fields?

Currently the adapter doesn't support this, it always loads the full model. Will be looking into this but I have no idea how hard this is at this point.

daemonsy avatar Aug 12 '16 13:08 daemonsy

Yes, that's exactly the scenario.

jc00ke avatar Aug 12 '16 16:08 jc00ke

My guess is that this will be an ember-data limitation more than with this adapter. Last time I checked, ED does not handle partial record loading well.

I've been toying with the idea of using a separate store, like redux, for data loaded with GraphQL.

dustinfarris avatar Sep 08 '16 16:09 dustinfarris

@dustinfarris I'm not familiar with how Ember Data works, but are you saying that if a Post has an Author that the Author will always be requested? Or that it'll be fetched when you post.author?

jc00ke avatar Oct 10 '16 22:10 jc00ke

Hey @jc00ke I'm guessing what @dustinfarris mean was more like if the view uses author.name and author.email only, ember data normally fetches all attributes for the author model above the name and email attribute

daemonsy avatar Oct 10 '16 23:10 daemonsy

Yes, what @daemonsy said. ED is sort of "all or nothing" when it comes to loading a model. There is an addon that tries to work around this, ember-data-partial-model, but I'm not a big fan of the API

I am working on a new addon to leverage GraphQL (via cashay) using redux as the store, instead of Ember Data. See my thoughts here: https://github.com/mattkrick/cashay/issues/120

dustinfarris avatar Oct 12 '16 02:10 dustinfarris

Cool, OK. I get that ED will load a complete model, but how does it handle associations? I'm assuming it won't start traversing the tree.

Thanks for the clarification!

jc00ke avatar Oct 12 '16 17:10 jc00ke

I was giving this addon a try on a new app I'm proofing out. The data is modeled as 3 types with hasMany relationships:

Zone -> Device -> Sensor

Zones have many devices, and device have many sensors.

When loading the top-level route for a Device, my GraphQL adapter sent the following query (prettified):

query device {
  device(id: "7ecbefe0-dd8c-4345-bdd9-34b85cb65515") {
    id
    name
    zone {
      id
      name
      devices {
        id
        name
        sensors {
          id
          kind
          description
        }
      }
    }
  }
}

So on a page that's just rendering some data about the device, the adapter asked for data about the device's parent zone (good) as well as all of that zone's associated devices (bad) as well as all those devices' sensors.

Unfortunately that makes the addon practically unusable with any real amount of data for this common scenario of 3 related types.

What I actually want is this query:

query device {
  device(id: "7ecbefe0-dd8c-4345-bdd9-34b85cb65515") {
    id
    name
    sensors {
      id
      kind
      description
    }
    zone {
      id
      name
    }
  }
}

I realize a lot of the limitations are a result of ember-data, but I'm thinking there must still be a better option. With a JSON API, Ember-data uses a promise for unresolved relationships that come in as links in the serialized response. Maybe this addon can do something similar where hasMany relationships aren't resolved until they're requested (or only IDs are requested in the query)?

I tried using async: true on one of these hasMany relationships which didn't work because it messed up the name of the ID field. Here's a query for a zone that shows sensorIds instead of what should be sensors { id }:

query zone {
  zone(id: "f312fa4c-5328-4145-b210-0a0df18dd827") {
    id
    name
    devices {
      id
      name
      sensorIds
    }
  }
}

I guess that's a different bug though.

bgentry avatar Oct 22 '16 03:10 bgentry

@bgentry the adapter currently doesn't do anything to figure out what structure you want. I just interprets the model structure you've defined via Ember Data.

For example with this structure:

// app/models/zone.js
export default DS.Model.extend({
  name: DS.attr('string'),
  devices: DS.hasMany('device'),
});

// app/models/device.js
export default DS.Model.extend({
  name: DS.attr('string'),
  zone: DS.belongsTo('zone'),
  sensors: DS.hasMany('sensor'),
});

// app/models/sensor.js
export default DS.Model.extend({
  kind: DS.attr('string'),
  description: DS.attr('string'),
  device: DS.belongsTo('device'),
});

There is currently no way for the adapter to know that it should ask for name and not devices when zone is being retrieved as a selection set of device, but ask for both when zone is the top level node. At least not without the introduction of some extra DSL. We've worked around this by using async: true like you've tried.

Regarding sensorIds vs. sensors { id }, the problem here is that Ember Data only wants to deal with JSON API data. So when a model's relationship is async it expects a relationship_id attribute in the payload.

delkopiso avatar Feb 01 '17 19:02 delkopiso

@delkopiso thanks for the reply. I've come to the conclusion that graphql and ember-data aren't a very good fit for each other due to mismatched expectations. I settled on using Apollo Client with ember-apollo-client, and some are using @dustinfarris' ember-cachay.

Thanks for your work building out this addon nonetheless! It helped inspire me to make the jump into GraphQL.

bgentry avatar Feb 01 '17 20:02 bgentry

No worries. I like what you done with ember-apollo-client!

delkopiso avatar Feb 01 '17 20:02 delkopiso

Hey! I've started using ember-graphql-adapter recently and I have to say, I like it a lot. During some reading, I came across this part of the Ember Data docs, which seems to offer a way of accomplishing the goal of this issue by specifying what relationships to include via the adapter:

import Ember from 'ember';

export default Ember.Route.extend({
  model: function() {
   return this.store.findAll('post', {include: 'comments'});
  }
});

Just wanted to drop that information here.

steffansluis avatar Mar 11 '17 22:03 steffansluis

@steffansluis Functions to fetch collections have this options that you mentioned, but functions like find don't.

viniciussbs avatar Mar 17 '17 19:03 viniciussbs

@viniciussbs In Ember Data 2.5, findRecord does have this option (although to be fair, I didn't know that either until I looked it up just now).

Edit: Still seems to be the case for Ember Data 2.11

steffansluis avatar Mar 17 '17 19:03 steffansluis