graphql icon indicating copy to clipboard operation
graphql copied to clipboard

Generate filters for primitive/relational cypher fields

Open rcbevans opened this issue 2 years ago • 3 comments

The library does not currently generate filters for cypher fields.

Given a simple schema like

type Author {
    mostRecentBook: Book @cypher(statement: "MATCH (this)-[:AUTHORED_BOOK]->(b:Book) RETURN b ORDERED BY b.year DESC LIMIT 1")
    lastPublishedYear: Int @cypher(statement: "MATCH (this)...")
    books: [Book!] @relationship(type: "AUTHORED_BOOK", direction: OUT)
}

type Book {
    name: String!
    year: Int
    authors: [Author!]! @relationship:type: "AUTHORED_BOOK", direction: IN)
}

A caller may want to filter authors by those whose most recent book year was later that a certain year, either based on the date on the Book returned by the "mostRecentBook" cypher statement, or the lastPublishedYear field which returns the year as a primitive.

Currently filters are not generated for cypher fields, requiring the lastPublishedYear value to be denormalized into a property on the parent Author(s) in order to have the graphQL filter generated.

From looking at the code, it seems that cypher fields are evaluated in the final return statement whereas filters are evaluated as part of the initial MATCH against the type being queried. To support filtering on cypher queries, any cypher field which is being filtered against would need to be evaluated earlier in the executed query, and then included in the return result. It would be desirable to evaluate filter cypher fields to be evaluated as early as possible to stop further evaluation for matches which are filtered out.

Describe the solution you'd like The library should generate GraphQL filters for both primitive and relational cypher fields as it does for non-cypher fields and relationships.

Describe alternatives you've considered Currently the only solution I have found is to denormalize fields I wish to filter on into the related nodes and maintain these denormalized values every time the ground truth nodes are updated.

rcbevans avatar Oct 29 '21 13:10 rcbevans

Here is another example use case, currently not possible but seemingly common:

type Design {
  pv_count: Int @cypher(statement:"""
    MATCH (this)-[:HAS_SYSTEM]->(p:PressureVessel)
    RETURN count(p)
  """)
}
{
  designs(where:{pv_count_GT:0}) {
    pv_count
  }
}
```

cramatt avatar May 28 '22 15:05 cramatt

Is there an alternative we should do for these fields in the meantime? Would it help if we make those @ computed instead or use @ callback on fields or other nodes they require to update their values?

Tanner-Scadden avatar Sep 05 '22 12:09 Tanner-Scadden