最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - GraphQL unable to resolve nested object property - Stack Overflow

programmeradmin3浏览0评论

I am trying to return a graphQL query with some nested property objects in a list. Everything seems to check out, but am getting null values.

Expected datastructure response (more detail on structure here):

//Return a GraphQLList type of all objects :    
[
    {
        "subscription" : {

        },
        "customer" : {

        },
    },
]

the query: { subscriptions { subscription { id customer_id } } }

GraphQL Query Object:

var Query = new graphQL.GraphQLObjectType({
    name: 'Query',
    description: 'Root of the Schema',
    fields: {
        subscriptions: {
            type: new graphQL.GraphQLList(SubscriptionsList),
            args : {
                customer_name: { type: graphQL.GraphQLString },
                customer_id: { type: graphQL.GraphQLString }
            },
            resolve : function (source, args) {
                return getSubscriptions().then(function (res) {
                    // Shows that data is returned
                    console.log('Data: ', res.list);

                    return res.list;
                }).catch(function (err) {
                    return err;
                });
            }
        }
    }
});

Which expects to return type GraphQLList of SubscriptionsList:

var SubscriptionsList = new graphQL.GraphQLObjectType({
    name : 'SubscriptionObj',
    description : 'stuff',
    fields : function () {
        return {
            subscription : {
                type : Subscription,
                resolve : function (subscription) {
                    return  subscription;
                }
            }
        }
    }
});

Which should resolve the nested field property:

var Subscription = new graphQL.GraphQLObjectType({
    name : 'Subscription',
    description : 'stuff',
    fields : function () {
        return {
            id: {type: graphQL.GraphQLString},
            customer_id: {type: graphQL.GraphQLString}
        }
    }
});

Console.log(res.list) Output (from Query): I am definitely getting the data and structure I expect:

[ { subscription: 
     { id: 'cbdemo_lloyd-sub2',
       customer_id: 'cbdemo_lloyd',
       plan_id: 'cbdemo_nuts',
       addons: [Object],
       due_invoices_count: 0,
       shipping_address: [Object] },
    customer: {
       ...
    }
  },
  {...}
]

GraphQL Query Output:

{
  "data": {
    "subscriptions": [
      {
        "subscription": {
          "id": null,
          "customer_id": null
        }
      },
      {
        "subscription": {
          "id": null,
          "customer_id": null
        }
      },

EDIT Not really necessary, but here is the getSubscriptions() API call that returns a promise:

function getSubscriptions() {
    return new Promise(function (resolve, reject) {
        chargebee.subscription.list({
            limit : 5,
            "plan_id[is_not]" : "basic",
            "status[is]" : "active",
            "sort_by[asc]" : "created_at"
        }).request(function(error,result){
            if (error) return reject(error);
            return resolve(result);
        });
    });
}

I am trying to return a graphQL query with some nested property objects in a list. Everything seems to check out, but am getting null values.

Expected datastructure response (more detail on structure here):

//Return a GraphQLList type of all objects :    
[
    {
        "subscription" : {

        },
        "customer" : {

        },
    },
]

the query: { subscriptions { subscription { id customer_id } } }

GraphQL Query Object:

var Query = new graphQL.GraphQLObjectType({
    name: 'Query',
    description: 'Root of the Schema',
    fields: {
        subscriptions: {
            type: new graphQL.GraphQLList(SubscriptionsList),
            args : {
                customer_name: { type: graphQL.GraphQLString },
                customer_id: { type: graphQL.GraphQLString }
            },
            resolve : function (source, args) {
                return getSubscriptions().then(function (res) {
                    // Shows that data is returned
                    console.log('Data: ', res.list);

                    return res.list;
                }).catch(function (err) {
                    return err;
                });
            }
        }
    }
});

Which expects to return type GraphQLList of SubscriptionsList:

var SubscriptionsList = new graphQL.GraphQLObjectType({
    name : 'SubscriptionObj',
    description : 'stuff',
    fields : function () {
        return {
            subscription : {
                type : Subscription,
                resolve : function (subscription) {
                    return  subscription;
                }
            }
        }
    }
});

Which should resolve the nested field property:

var Subscription = new graphQL.GraphQLObjectType({
    name : 'Subscription',
    description : 'stuff',
    fields : function () {
        return {
            id: {type: graphQL.GraphQLString},
            customer_id: {type: graphQL.GraphQLString}
        }
    }
});

Console.log(res.list) Output (from Query): I am definitely getting the data and structure I expect:

[ { subscription: 
     { id: 'cbdemo_lloyd-sub2',
       customer_id: 'cbdemo_lloyd',
       plan_id: 'cbdemo_nuts',
       addons: [Object],
       due_invoices_count: 0,
       shipping_address: [Object] },
    customer: {
       ...
    }
  },
  {...}
]

GraphQL Query Output:

{
  "data": {
    "subscriptions": [
      {
        "subscription": {
          "id": null,
          "customer_id": null
        }
      },
      {
        "subscription": {
          "id": null,
          "customer_id": null
        }
      },

EDIT Not really necessary, but here is the getSubscriptions() API call that returns a promise:

function getSubscriptions() {
    return new Promise(function (resolve, reject) {
        chargebee.subscription.list({
            limit : 5,
            "plan_id[is_not]" : "basic",
            "status[is]" : "active",
            "sort_by[asc]" : "created_at"
        }).request(function(error,result){
            if (error) return reject(error);
            return resolve(result);
        });
    });
}
Share Improve this question asked Aug 30, 2016 at 22:20 user3871user3871 12.7k36 gold badges140 silver badges282 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 3

Looks like you are getting abit confused, Basiclly, when you set

new graphQL.GraphQLList(SubscriptionsList),

this is already a list. which means what you really meant is

new graphQL.GraphQLList(Subscription),

Next, your subscription object does not contain any resolve logic, so i would expect it to be something like this:

var Subscription = new graphQL.GraphQLObjectType({
    name : 'Subscription',
    description : 'stuff',
    fields : function () {
        return {
            id: {
                   type: graphQL.GraphQLString,
                   resolve: function(subscription) {
                       return subscription.subscription.id;
                   }
            },
            customer_id: {
                   type: graphQL.GraphQLString,
                   resolve: function(subscription) {
                       return subscription.subscription.customer_id;
                   }
            },
        }
    }
});

What basically happens under the hood, is that GraphQL will resolve each javascript object in the list provided, using the Subscription object. each resolver there will get the javascript object as the first value, and return the basic value from it.

I think the resolver in your SubscriptionsList has to return subscription.subscription. I would consider changing the name of subscriptionsList, because it's quite confusing.

The way I see it, you should just have a GraphQLList(Subscription) and remove that extra level of nesting. Either that, or call the thing that contains a subscription and a customer something else.

According to your post, res.list shows the following:

// listing #1
[
  { 
    subscription: {
      id: 'cbdemo_lloyd-sub2',
      customer_id: 'cbdemo_lloyd',
      plan_id: 'cbdemo_nuts',
      addons: [Object],
      due_invoices_count: 0,
      shipping_address: [Object] },
      customer: {
        ...
      }
  },
  {...}
]

Now, the above result corresponds to subscriptions field in your Query, which is a list of SubscriptionsList. Therefore, value of a SubscriptionsList will be item from the above listing #1:

// listing #2
{
  subscription: {
    id: 'cbdemo_lloyd-sub2',
    customer_id: 'cbdemo_lloyd',
    plan_id: 'cbdemo_nuts',
    addons: [Object],
    due_invoices_count: 0,
    shipping_address: [Object] },
    customer: {
      ...
    }
  }
}

In SubscriptionsList type, you have a field subscription. Its resolve function returns whatever it gets. So the field subscription remains the same as listing #2.

While resolving subscription field (type Subscription), it looks for id and customer_id properties in object shown in listing #2. But that object has only subscription property. Therefore, id and customer_id fields receive null values.

Thus, the problem is in the resolve function of subscription field. Its input is object in listing #2 and its output should be the object in the following listing #3:

// listing #3
{
  id: 'cbdemo_lloyd-sub2',
  customer_id: 'cbdemo_lloyd',
  plan_id: 'cbdemo_nuts',
  addons: [Object],
  due_invoices_count: 0,
  shipping_address: [Object] },
  customer: {
    ...
  }
}

To get the object in listing #3, change in your SubscriptionsList type:

subscription : {
    type : Subscription,
    resolve : function (item) { // item is listing #2
        return  item.subscription; // item.subscription is listing #3
    }
}

On a different note, the GraphQL object type SubscriptionsList is actually unnecessary here and made the whole thing plicated. The whole design will bee a lot simpler without it.

发布评论

评论列表(0)

  1. 暂无评论