Wrong Results when filtering on aliased edges

Version: Slash v20.07.1-rc1-29-g43c04cff

Present on Master: unknown

Expectations: I expect to be able to call an edge multiple times with unique aliases and apply different filters on those edges to return a different result on each aliased edge.

Actual Results: That is not the case, as the results still return the same node that matches the filter on the first aliased edge.

Why That Was Not Great: because the data does not match the filter as requested giving false results.

How To Duplicate:

Schema:

type Place {
    id: String! @id
    name: String!
    tags: [Tag] @hasInverse(field: places)
}
type Tag {
    id: String! @id
    slug: String!
    places: [Place]
}

Queries/Mutations:

# add example data
mutation addData {
  addPlace(input: [{
    id: "1"
    name: "Place A"
    tags: [
      { id: "1", slug: "tag-z" }
      { id: "3", slug: "tag-x" }
      { id: "5", slug: "tag-v" }
    ]
  }{
    id: "2"
    name: "Place B"
    tags: [{ id: "3", slug: "tag-x" }]
  }{
    id: "3"
    name: "Place C"
    tags: [
      { id: "1", slug: "tag-z" }
      { id: "2", slug: "tag-y" }
      { id: "3", slug: "tag-x" }
      { id: "4", slug: "tag-w" }
      { id: "5", slug: "tag-v" }
    ]
  }{
    id: "4"
    name: "Place D"
    tags: [
      { id: "2", slug: "tag-y" }
      { id: "4", slug: "tag-w" }
    ]
  }{
    id: "5"
    name: "Place E"
  }]) {
    numUids
  }
}

# see the example data exists correctly as expected
query placesAndTags {
  queryPlace {
    id
    name
    tags {
      id
      slug
    }
  }
  queryTag {
    id
    slug
    places {
      id
      name
    }
  }
}

# as expected
query placesTaggedZ {
  getTag(id:"1") {
    id
    slug
    places {
      id
      name
    }
  }
}

# as expected
query placesTaggedZorY {
  queryPlace @cascade {
    id
    name
    tags(filter:{
      id:{ eq:"1" }
      or:{ id:{ eq:"2" } }
    }) {
      id
      slug
    }
  }
}

# NOT as expected!!
query placesTaggedZandY {
  queryPlace @cascade {
    id
    name
    Z: tags(filter: { id:{ eq: "1" } }) {
      id
      slug
    }
    Y: tags(filter: { id: { eq: "2" } }) {
      id
      slug
    }
  }
}
mutation deleteAll {
  deleteTag(filter: {}) { numUids }
  deletePlace(filter: {}) { numUids }
}

Results from placesTaggedZandY query:

{
  "data": {
    "queryPlace": [
      {
        "id": "1",
        "name": "Place A",
        "Z": [
          {
            "id": "1",
            "slug": "tag-z"
          }
        ],
        "Y": [
          {
            "id": "1",
            "slug": "tag-z"
          }
        ]
      },
      {
        "id": "3",
        "name": "Place C",
        "Z": [
          {
            "id": "1",
            "slug": "tag-z"
          }
        ],
        "Y": [
          {
            "id": "1",
            "slug": "tag-z"
          }
        ]
      }
    ]
  },
  "extensions": {...}
}

I am not sure if this is only particular to the @id directive, but I don’t believe so. I think it is more particular to the query rewriting pertaining to aliases and responding to the correct aliased edge. What is interesting is that the places are filtered correctly to only those with tags Z and Y, it just doesn’t display back the correct subgraph for Y.

Interestingly enough, if you reverse the order of the aliased fileds, you get the error in reverse. Both aliased edges will have tag-y on this query:

query placesTaggedZandYReversed {
  queryPlace @cascade {
    id
    name
    Y: tags(filter: { id:{ eq: "2" } }) {
      id
      slug
    }
    Z: tags(filter: { id: { eq: "1" } }) {
      id
      slug
    }
  }
}

Overly thankful that my queries no longer look like this monster SQL query I had to have help with 3 years ago to do what is done so easily above (regardless of this bug).

Thanks for reporting this issue. I could reproduce this on master. I am accepting this as a bug. It is not just particular to the @id directive.
The reason this appears is because at the time of converting GraphQL query to DQL, to avoid writing the same queried fields twice, we remove the repeated fields. Although, the removal of fields works for scalar fields, it is problematic for object fields, as they may have different filters and other directives making the removal unnecessary.

1 Like