Skip to content
This repository has been archived by the owner on Sep 3, 2021. It is now read-only.

Complex nested filtering doesn't appear to work. #353

Closed
leefreemanxyz opened this issue Nov 25, 2019 · 9 comments
Closed

Complex nested filtering doesn't appear to work. #353

leefreemanxyz opened this issue Nov 25, 2019 · 9 comments

Comments

@leefreemanxyz
Copy link

Hello, I'm having some trouble with the neo4j-graphql-js package. We have a schema (stripped down for brevity) as follows:

const typeDefs = `
    type Product {
        partNumber: String
        Items: [Item] @relation(name: "HAS_ITEM", direction: "OUT")
    }

    type Item {
        shortDescription: String
        partNumber: String
        Features: [Feature] @relation(name: "HAS_FEATURE", direction: "OUT")
     }

    type Feature {
        name: String
        value: String
    }
`

And from a product page we would like to build filters based on the features of the items belonging to that product. E.g. we want to filter based on a match of the name and value of a feature (the names will always be unique for a feature, but the values can quite easily be the same for different feature names). Judging by the documentation, I would expect to be able to write a query like this:

{
  Product(filter: { partNumber: "PART_A" }) {
    shortDescription
    Items(
      filter: {
        Features_single: {
          AND: [{ name: "Color" }, { value: "Blue" }]
        }
      }
    ) {
      shortDescription
      Features {
        name
        value
      }
    }
  }
}

but the response is empty

{
  "data": {
    "Product": [
      {
        "shortDescription": "Product ABCDE",
        "Items": []
      }
    ]
  }
}

I used Features_single because I want to return Items where a single feature has both the name and value required (e.g. an item with Features: [{color: red}, {backgroundColor:blue}] should not be returned as an item, only {color:blue, backgroundColor: anything}). In the Neo4J Slack I was advised to try Features_some – when I use this, if one feature in all the items matches, then all items from the product are returned, and if there is no match in any of the items then none are returned at all.

Thanks in advance.

@johnymontana
Copy link
Contributor

johnymontana commented Nov 25, 2019

So if I'm understanding correctly that query would return items where exactly one connected feature matches the predicate of name: Color AND value: Blue. Instead I think you want:

{
  Product(filter: { partNumber: "PART_A" }) {
    shortDescription
    Items(
      filter: {
        Features: {
          AND: [{ name: "Color" }, { value: "Blue" }]
        }
      }
    ) {
      shortDescription
      Features {
        name
        value
      }
    }
  }
}

which should filter for any items that have connected features that match the predicate: AND: [{ name: "Color" }, { value: "Blue" }].

If that doesn't work, could you please also post the generated Cypher query?

@leefreemanxyz
Copy link
Author

Yes, so a product may have 10 items associated with it (imagine a style of sneaker (Product), and it comes in 10 different sizes (Items)). And maybe I'm looking to get the Sneakers where the Sizes come with a Feature: {name:"LaceColour", value:"Blue"}. So with the filter, rather than the 10 Sizes being returned, maybe I only receive 3 Sizes. At the moment, the different permutations of the Feature filters seem to return all or nothing (including the query above). Unfortunately in this case we're not talking about something fun like Sneakers, but about Ball Valves (and all the content is in Dutch).

I realised the initial filter on Product is unnecessary, so ran your query above like so:

  Product(partNumber: "PR_EC011343_0081") {
    shortDescription
    Items(
      filter: {
        Features: { AND: [{ name: "Druktrap artikel" }, { value: "PN 40" }] }
      }
    ) {
      shortDescription
      Features {
        name
        value
      }
    }
  }
}

yielding the result:

{
  "data": {
    "Product": {
      "shortDescription": "Kogelkraan fig. 7249 staal flens oude versie",
      "Items": []
    }
  }
}

and the resultant Cypher query is:

MATCH (`product`:`Product` {partNumber:$partNumber}) RETURN `product` { .shortDescription ,Items: [(`product`)-[:`HAS_ITEM`]->(`product_Items`:`Item`) WHERE (EXISTS((`product_Items`)-[:HAS_FEATURE]->(:Feature)) AND ALL(`feature` IN [(`item`)-[:HAS_FEATURE]->(`_feature`:Feature) | `_feature`] WHERE (ALL(_AND IN $1_filter.Features.AND WHERE (_AND.name IS NULL OR `feature`.name = _AND.name) AND (_AND.value IS NULL OR `feature`.value = _AND.value))))) | product_Items { .shortDescription ,Features: [(`product_Items`)-[:`HAS_FEATURE`]->(`product_Items_Features`:`Feature`) | product_Items_Features { .name , .value }] }] } AS `product`
{
  "offset": 0,
  "first": -1,
  "partNumber": "PR_EC011343_0081",
  "1_filter": {
    "Features": {
      "AND": [
        {
          "name": "Druktrap artikel"
        },
        {
          "value": "PN 40"
        }
      ]
    }
  }
}

@tbrixey
Copy link

tbrixey commented Jan 6, 2020

Chiming in here to say I am having similar problems. Here is a snippet example of a schema that's failing.

type TopLevel {
  id
  name
  secondLevel: [SecondLevel] @relation(name: "HAS_SECOND_LEVEL", direction: "OUT")
}

type SecondLevel {
  id
  name
  somethingThatRelates: SomethingThatRelates
      @relation(name: "ANOTHER_RELATION", direction: "IN")
}

type SomethingThatRelates {
  id
  name
}

Query I'm using that is returning nothing in the SecondLevel.

TopLevel(id: "1") {
  id
  name
  SecondLevel( filter: { somethingThatRelates: { id: "1234" } } ) {
    id
    somethingThatRelates {
      id
    }
  }
}

@johnymontana
Copy link
Contributor

Hey @tbrixey @leefreemanxyz -

I've pushed a fix for this. Could you try with the lastest release v2.11.3 and let me know if this resolves the issue?

@jonasdumas
Copy link

jonasdumas commented Jan 7, 2020

Hi @johnymontana
It doesn't work for us. We still have the problem with:

type  Post {
   ttuid: ID!,
   title: String!,
   comments: [Comment] @relation(direction:"OUT", name: "HAS"),
   published_at: DateTime,
   created_at: DateTime,
   updated_at: DateTime,
   deleted_at: DateTime,
}

type Comment {
   ttuid: ID!,
   body: String!,
   author: User @relation(direction:"OUT", name:"POSTED_BY"),
   post: Post @relation(direction:"IN", name:"HAS"),
   comments: [Comment] @relation(direction:"OUT", name: "HAS"),
   created_at: DateTime,
   deleted_at: DateTime,
   updated_at: DateTime
}

The following GraphqL query doens't change the order of the comments whatever we fill in orderBy: created_at_asc, created_at_desc, body_asc, body_desc

query getPostComments($postTtuid: ID!, $nbComments: Int!, $nbChildComments: Int!){
  Post(ttuid: $postTtuid){
      comments(first: $nbComments, orderBy: created_at_asc){
          ...Comment
          comments(first: $nbChildComments, orderBy: created_at_asc){
            ...Comment
          }
      }
  }
}

Any idea why?

We've now [email protected]

@jonasdumas
Copy link

Same remark as the end of this:
#47

@johnymontana
Copy link
Contributor

Hi @jonasdumas - I've created Issue #373 to track your DateTime ordering issue.

Let's keep the discussion here to the nested filtering bug described above. Thanks!

@johnymontana
Copy link
Contributor

@tbrixey @leefreemanxyz Closing this issue as it should be resolved in v2.11.3. Please reopen if you're still seeing the same behavior.

@tbrixey
Copy link

tbrixey commented Jan 14, 2020

This fixes my issue thanks!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants