ember-graphql-adapter
ember-graphql-adapter copied to clipboard
Full object graph always requested?
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!
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.
Yes, that's exactly the scenario.
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 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?
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
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
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!
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 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 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.
No worries. I like what you done with ember-apollo-client!
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 Functions to fetch collections have this options that you mentioned, but functions like find don't.
@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