Graphback: No result from database...can't override resolvers in resolvers object

Created on 9 Aug 2020  路  20Comments  路  Source: aerogear/graphback

I need the ability to override resolvers of model objects. I believe I was able to do this in previous versions of graphback during the alpha, and I did this with Prisma. It isn't working anymore. For example:

"""@model"""
type Companies {
  id: ID!
  test: Int!
}

test is not in the database, I am going to write a resolver for it. In the past I would overwrite that field in my resolvers object:

    const { 
        typeDefs,
        resolvers,
        contextCreator
    } = buildGraphbackAPI(model, {
        dataProviderCreator: createKnexDbProvider(knexDB)
    });

  const newResolvers = {
     ...resolvers,
     Companies: {
       ...resolvers.Companies,
       test: () => 5
     }
  };

I would then take newResolvers and give it to Apollo Server. This doesn't work for some reason, and I keep getting the following error: "No result from database: Cannot find a result for companies with filter: {\"id\":\"1\"}"

bug

All 20 comments

Automatically generated comment to notify maintainers
/cc @craicoverflow, @machi1990, @wtrocki

The error we see is not related to resolver it is more than a database cannot be queried with provided id.

https://github.com/aerogear/graphback/blob/f8ab9f3cf4a8fe58379a0eac1655f0e9c825d82b/packages/graphback-runtime-knex/src/KnexDBDataProvider.ts#L72

Looking at your snippet I do not see anything alarming so indeed, this is what @wtrocki says it is. Let us know how if this works when changing the requested id to something else.

The company that I am querying indeed exists in the database. For example, this query works:

query {
  getCompanies(id: 1) {
    id
  }
}

and returns the following:

{
  "data": {
    "getCompanies": {
      "id": "1"
    }
  }
}

But when I add the test field that has a custom resolver hooked up like I showed in previous comments:

query {
  getCompanies(id: 1) {
    id
    test
  }
}

This does not work, and I get the following result:

{
  "errors": [
    {
      "message": "No result from database: Cannot find a result for companies with filter: {\"id\":\"1\"}",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "getCompanies"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "exception": {
          "stacktrace": [
            "Error: No result from database: Cannot find a result for companies with filter: {\"id\":\"1\"}",
            "    at KnexDBDataProvider.<anonymous> (/home/lastmjs/development/jill/jills-office-node/node_modules/@graphback/runtime-knex/src/KnexDBDataProvider.ts:75:13)",
            "    at Generator.throw (<anonymous>)",
            "    at rejected (/home/lastmjs/development/jill/jills-office-node/node_modules/tslib/tslib.js:113:69)",
            "    at processTicksAndRejections (internal/process/task_queues.js:85:5)"
          ]
        }
      }
    }
  ],
  "data": {
    "getCompanies": null
  }
}

Thanks for checking @lastmjs, I fully understand now, previous I was thinking that the field test is in the database also. But now I understand. It might be a bug since from the ResolversInfo we'll issue a query like

select id, test from companies where id = xxx

Which fails with a missing column error.

I am thinking maybe we can introduce a way to ignore some fields from database selection? I know we have @db(skip: true) that's ignores a field only when running migrations.

/cc @craicoverflow @wtrocki

The issue seems to run even deeper, and based on my limited knowledge of Graphback's internals, I would say this has to do with how the dataloader attempts to resolve relations (probably similar to what you're saying @machi1990). I have a custom query that looks like this:

Query {
  fetchLiveQueue: [Incoming_queue_items!]!
}

""" @model """
type Incoming_queue_items {
    id: ID!

    """
    @oneToOne(key: 'call_id')
    """
    call: Calls!
    created_at: DateTime!
    handled_at: DateTime
    incoming_call_type: INCOMING_CALL_TYPE!

    """
    @oneToOne(key: 'pod_id')
    """
    pod: Pods!
    updated_at: DateTime!
    user_call_sid: String!
}

When I execute the following query:

query {
  fetchLiveQueue {
    pod {
      id
    }
  }
}

I get the following error:

{
  "errors": [
    {
      "message": "No result from database: Cannot find a result for pods with filter: {}",
      "locations": [
        {
          "line": 3,
          "column": 5
        }
      ],
      "path": [
        "fetchLiveQueue",
        0,
        "pod"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "exception": {
          "stacktrace": [
            "Error: No result from database: Cannot find a result for pods with filter: {}",
            "    at KnexDBDataProvider.<anonymous> (/var/task/node_modules/@graphback/runtime-knex/dist/KnexDBDataProvider.js:73:23)",
            "    at Generator.throw (<anonymous>)",
            "    at rejected (/var/task/node_modules/tslib/tslib.js:113:69)",
            "    at processTicksAndRejections (internal/process/task_queues.js:97:5)"
          ]
        }
      }
    }
  ],
  "data": null
}

fetchLiveQueue has a completely custom resolver, and thus should be completely outside of the scope of Graphback's resolvers and dataloader pattern. I have found a workaround for this, but it requires me to create custom types outside of the the types I already have marked with @model

Thank you @lastmjs for digging deeper.

Glad that you have found a workaround for now, do you mind posting a code snippet here in the issuse so that it could be useful for others users while the team is further triaging this issue? Thank you.

Sure, the workaround is simple. Just make a custom type without a @model annotation.

Query {
  fetchLiveQueue: [FetchLiveQueueIncomingQueueItems!]!
}

# Simplified example, but just add the fields that you need
type FetchLiveQueueIncomingQueueItems {
  id: ID!
  created_at: DateTime!
  pod: FetchLiveQueueIncomingQueuePods!
}

type FetchLiveQueueIncomingQueuePods {
  id: ID!
}

""" @model """
type Incoming_queue_items {
    id: ID!

    """
    @oneToOne(key: 'call_id')
    """
    call: Calls!
    created_at: DateTime!
    handled_at: DateTime
    incoming_call_type: INCOMING_CALL_TYPE!

    """
    @oneToOne(key: 'pod_id')
    """
    pod: Pods!
    updated_at: DateTime!
    user_call_sid: String!
}

I am thinking maybe we can introduce a way to ignore some fields from database selection? I know we have @db(skip: true) that's ignores a field only when running migrations.

@machi1990 yes that would make sense. I touched on this in https://github.com/aerogear/graphback/issues/1023 - if there was an @ignore annotation this could be used for both cases - ignore a field not in the database and ignore a field in the database table.

@craicoverflow cool, @ignore makes sense. Let me add a comment in that issue.

I'm not sure @ignore would solve the problem I'm having, unless you put @ignore on the custom query fetchLiveQueue. In my example above, Incoming_queue_items is in the database, and the Graphback-generated queries should use the database and do batching and dataloader things. But, for my custom queries I am just using Incoming_queue_items as a type, and fetching the data myself. I shouldn't have to use @ignore anywhere on Incoming_queue_items in this case, just in fetchLiveQueue. Seems @ignore is not an elegant solution to this.

@lastmjs the @ignore annotation will be placed directly on the fields that should not be loaded from the database.

"""@model"""
type Companies {
  id: ID!
  test: Int!
}

test is not in the database, I am going to write a resolver for it. In the past I would overwrite that field in my resolvers object:

For example, you could use it in the model above as:

graphql """@model""" type Companies { id: ID! """ @ignore """ test: Int! }

and it will:

  • ignore the test field from the query issued in database, thus avoid a missing column error which resulted in the issue you were seeing.

    • not generate the mutation inputs, since the test field is not in the database. This will avoid similar errors during create/update/delete

    • the test field will be omitted from the generate CompaniesFilterInput, again for the same reason.

    • moreever, if you are using GraphQLMigrations, this field will be skipped and not generated.

All these points above are due to the fact that test is a transient field and Graphback should not attempt to manage it in either way.

Going to this https://github.com/aerogear/graphback/issues/1843#issuecomment-671503126, maybe the @ignore field will not be appropriate ( I am yet to find out why you are having this issue). Do you mind sharing in a sample code the query sent to the database? There are two possibilities:


    1. There is actually no data for this particular case


    1. There is an issue that's slightly different and not related to the one that I finally grasped (a missing column in the database).

Having a small code snippet in how the query is issued will be helpfully in understanding this second issue. Thank you.

Hey, is the example here good enough? https://github.com/aerogear/graphback/issues/1843#issuecomment-671503126

This is the query:

query {
  fetchLiveQueue {
    pod {
      id
    }
  }
}

The example schema is in that comment

Thank you @lastmjs I'll try to setup something similar in an attempt to reproduce the issue.

Hey, thanks for fixing part of the issue, but a large part of my issue as explained in multiple comments above will not be fixed by this. I think this issue should be reopened or perhaps the remaining part of the issue should be moved to a new issue

Hey, thanks for fixing part of the issue, but a large part of my issue as explained in multiple comments above will not be fixed by this. I think this issue should be reopened or perhaps the remaining part of the issue should be moved to a new issue

Hi @lastmjs this indeed fix the issue where you have a field that is not in database.

but a large part of my issue as explained in multiple comments above will not be fixed by this. I think this issue should be reopened or perhaps the remaining part of the issue should be moved to a new issue

As for this issue, I believe you are talking about this https://github.com/aerogear/graphback/issues/1843#issuecomment-671503126 quoted below:

The issue seems to run even deeper, and based on my limited knowledge of Graphback's internals, I would say this has to do with how the dataloader attempts to resolve relations (probably similar to what you're saying @machi1990). I have a custom query that looks like this:

Query {
  fetchLiveQueue: [Incoming_queue_items!]!
}

""" @model """
type Incoming_queue_items {
    id: ID!

    """
    @oneToOne(key: 'call_id')
    """
    call: Calls!
    created_at: DateTime!
    handled_at: DateTime
    incoming_call_type: INCOMING_CALL_TYPE!

    """
    @oneToOne(key: 'pod_id')
    """
    pod: Pods!
    updated_at: DateTime!
    user_call_sid: String!
}

When I execute the following query:

query {
  fetchLiveQueue {
    pod {
      id
    }
  }
}

I get the following error:

{
  "errors": [
    {
      "message": "No result from database: Cannot find a result for pods with filter: {}",
      "locations": [
        {
          "line": 3,
          "column": 5
        }
      ],
      "path": [
        "fetchLiveQueue",
        0,
        "pod"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "exception": {
          "stacktrace": [
            "Error: No result from database: Cannot find a result for pods with filter: {}",
            "    at KnexDBDataProvider.<anonymous> (/var/task/node_modules/@graphback/runtime-knex/dist/KnexDBDataProvider.js:73:23)",
            "    at Generator.throw (<anonymous>)",
            "    at rejected (/var/task/node_modules/tslib/tslib.js:113:69)",
            "    at processTicksAndRejections (internal/process/task_queues.js:97:5)"
          ]
        }
      }
    }
  ],
  "data": null
}

fetchLiveQueue has a completely custom resolver, and thus should be completely outside of the scope of Graphback's resolvers and dataloader pattern. I have found a workaround for this, but it requires me to create custom types outside of the the types I already have marked with @model

From my understanding, you have a custom resolver fetchLiveQueue loading a list of Incoming_queue_items using a graphback service.

  1. From looking at the error message, its seems to me that you are attempting to load pods using a services.Pods.findOne({}) is this correct ? If so, can you share with me the rest of your typescript snippets ( resolver code ) so that I can debug it further.

  2. Out of curiosity, does the Pods type contain a field that's not in the database?

Thanks.

Also, I am re-opening this, for further investigation.

fetchLiveQueue has a completely custom resolver, and thus should be completely outside of the scope of Graphback's resolvers and dataloader pattern.

@lastmjs when you say that fetchLiveQueue has a complete custom resolver, since this resolver returns a Incoming_queue_items type, I've additional questons regarding your custom resolver:

  • Did you also override the generated Incoming_queue_items.pod resolver with your own?
  • If not, when you query for
query {
  fetchLiveQueue {
    pod {
      id
    }
  }
}

what result do you get in your custom resolver before the resolution of the oneToOne relationship between Incoming_queue_items and Pods via the generated Incoming_queue_items.pod?

If you do not mind, can you send me the actual error you are seeing from the database. To get it, add the catched error in this line: https://github.com/aerogear/graphback/blob/7d4f80c47cb5ff0c58da9dd493c424ffd0015fcb/packages/graphback-runtime-knex/src/KnexDBDataProvider.ts#L72 (you might have the transpiled file). Once that is done restart the server and and do the query again.

Thanks once again.

@lastmjs ping, I was thinking about this issue again and was wondering if you can take a look at https://github.com/aerogear/graphback/issues/1843#issuecomment-678524738 and https://github.com/aerogear/graphback/issues/1843#issuecomment-678554357, thanks :-)

Closing as this looks to be resolved, but reopen if I am wrong on that.

Was this page helpful?
0 / 5 - 0 ratings