Filter doesn't work

Hi,

I don’t know what I am doing wrong but something is went wrong when I tried to filter some objects.
My types are:

type User {
  username: String! @search(by: [hash, regexp]) @id
  name: String
  email: String! @search(by: [hash, regexp])
  hasCredentials: [Credentials!] @hasInverse(field: forUser)
}
type Credentials @secret(field: "secretKey"){
  accessKey: String! @search(by: [hash]) @id
  description: String! @search(by: [term, hash])
  forUser: User!
}

my query is:

query MyQuery {
  queryCredentials {
    accessKey
    forUser(filter: {username: {eq: "orch"}}) {
      username
    }
  }
}

The result of the query is:

"errors": [
    {
      "message": "Non-nullable field 'forUser' (type User!) was not present in result from Dgraph.  GraphQL error propagation triggered.",
      "locations": [
        {
          "line": 4,
          "column": 5
        }
      ],
      "path": [
        "queryCredentials",
        2,
        "forUser"
      ]
    }
  ],
  "data": {
    "queryCredentials": [
      {
        "accessKey": "****",
        "forUser": {
          "username": "orch"
        }
      },
      {
        "accessKey": "****",
        "forUser": {
          "username": "orch"
        }
      },
      null
    ]
  }

The data in the DB contains one more credential for another user.
I don’t know why it returns as null or at all, and why I get an error

Hi @spinelsun,

Dgraph GraphQL stores data inside Dgraph database. Every GraphQL query is converted into DQL query, executed on the database and the result is returned back after converting to GraphQL response.

The error states that for one of the nodes of type Credentials, the forUser field does not exist. As forUser field is non-nullable, this is returned as an error.

Possible Reasons could be:

  1. The Data for the node has been changed using DQL mutation.
  2. There already exists some data in Dgraph with missing forUser field for type Credentials and GraphQL Schema is applied on it.

The error should not occur if data has been inserted and updated using only GraphQL.How was data inserted in the Dgraph instance ? If the data was inserted using DQL, can you check if there is any node of type Credentials with missing forUser field.

Good explanation @rajas.

And to add this use case to your list of reasons:

  1. You are filtering an edge that removes all results from a required edge.

I think the reason is better explained:

You most likely have Credentials for other Users. In your query in the top level you are getting all Credentials and then on the edge forUser you you getting a filtered set only for one User.

This throws an error because the forUser is a required edge !. You could easily resolve this by removing the ! on the line forUser: User!, but I don’t think that is exactly what you want as that would allow Credentials to be added that were not for any User. Also I think what you really want is not “All Credentials including the forUser if it is for ‘orch’”, but rather “All of the Credentials for a specific User”

So the remedy to get the data wanted without the error message is to flip the query upside down. It will get the same data. “All of the Credentials for a specific User”

{
  getUser(username: "orch") {
    username
    hasCredentials {
      accessKey
    }
  }
}

I have a feature request floating around here somewhere for this same error that would allow DGraph to remove the node throwing the error and return the data minus the error row. Essentially using @cascade(fields: ["forUser"]) (or whatever the syntax should be.)

2 Likes

So for the query:

query MyQuery {
  queryCredentials {
    accessKey
    forUser {
      username
    }
  }
}

The result is:

"data": {
    "queryCredentials": [
      {
        "accessKey": "****",
        "forUser": {
          "username": "orch"
        }
      },
      {
        "accessKey": "****",
        "forUser": {
          "username": "orch"
        }
      },
      {
        "accessKey": "****",
        "forUser": {
          "username": "michal"
        }
      }
    ]
  }

No data was inserted with DQL, I used only slash API Explorer to run mutations

I agree that beginning at the topmost type and then go down and filter is better in that case.
I thought it will be possible to query in both direction.

Thanks,
Or