Releases: neo4j/graphql
@neo4j/graphql@5.12.3
Patch Changes
- #6294
8cf40d9
Thanks @MacondoExpress! - Fix bug that causes 1:1 non-nullable relationship filters to produce invalid Cypher.
@neo4j/graphql-ogm@5.12.3
Patch Changes
- Updated dependencies [
8cf40d9
]:- @neo4j/graphql@5.12.3
@neo4j/graphql@6.6.2
Patch Changes
- #6274
0d94cc4
Thanks @angrykoala! - Backport fix #6243: Handles Neo4j error "52N29" on CDC polling by refreshing the cursor. This error could be triggered in some cases by an outdated cursor.
@neo4j/graphql@5.12.2
Patch Changes
- #6275
8a993a8
Thanks @angrykoala! - Backport fix #6243: Handles Neo4j error "52N29" on CDC polling by refreshing the cursor. This error could be triggered in some cases by an outdated cursor.
@neo4j/graphql-ogm@5.12.2
Patch Changes
- Updated dependencies [
8a993a8
]:- @neo4j/graphql@5.12.2
@neo4j/graphql@7.1.1
Patch Changes
- #6243
8d4c5c6
Thanks @angrykoala! - Handles Neo4j error "52N29" on CDC polling by refreshing the cursor. This error could be triggered in some cases by an outdated cursor.
@neo4j/graphql@7.1.0
Minor Changes
-
#6199
4404026
Thanks @angrykoala! - Add support for@cypher
directive of fields targeting types that do not use the@node
directive. For example:type Movie @node { title: String id: String! link: Link! @cypher( statement: """ MATCH(l:${Link}) WHERE l.movieId=this.id RETURN l {.name, .url} as link """ columnName: "link" ) } type Link { movieId: String! url: String! name: String! }
Patch Changes
-
#6223
de2dcea
Thanks @angrykoala! - Fix bug with@populatedBy
. Callback wouldn't be triggered by nested create operations for relationship fields. -
#6236
1866286
Thanks @angrykoala! - Fix bug with some filters not properly working on subscriptions.
@neo4j/introspector@5.0.0
Major Changes
- #5837
721691a
Thanks @MacondoExpress! - Changed how "@neo4j/introspector" generates list fields that now are generated as a list of non-nullable elements, as a list of nullable elements is not supported by Neo4j.
@neo4j/graphql@7.0.0
Major Changes
-
#6153
0779691
Thanks @angrykoala! - Fails schema validation if a field with@relationship
targets a type without@node
.For example, the following schema will fail:
type Movie @node { someActors: [Actor!]! @relationship(type: "ACTED_IN", direction: OUT) } type Actor { name: String }
-
#5899
7335d8f
Thanks @darrellwarde! - Nested mutation operations now follow the relationship direction behaviour as defined inqueryDirection
-
#6048
c667618
Thanks @darrellwarde! - Subscriptions are now an opt-in feature which can be enabled by using the@subscription
directive on either schema or type.For example, to enable subscriptions for the whole schema (equivalent to before this breaking change):
type Movie @node { title: String! } extend schema @subscription
To enable subscriptions just for the
Movie
type:type Movie @node @subscription { title: String! }
-
#5997
a716ef8
Thanks @angrykoala! - Removepublish
method fromNeo4jGraphQLSubscriptionsEngine
interface as it is no longer used with CDC-based subscriptions. Implementing this method on custom engines will no longer have an effect, and it is no longer possible to callpublish
directly onNeo4jGraphQLSubscriptionsCDCEngine
-
#5872
925ad8d
Thanks @angrykoala! - Remove@private
directive. This directive was intended to be used with the library@neo4j/graphql-ogm
which is no longer supported. -
#5895
6afcadd
Thanks @angrykoala! - Fails schema generation if there are conflicting plural names in types. For example, the following schema will fail, due to ambiguousTechs
pluraltype Tech @node(plural: "Techs") { name: String } type Techs { value: String }
-
#5927
530d8cd
Thanks @MacondoExpress! - Thetypename_IN
filter has been renamed totypename
. -
#6077
4cf7c07
Thanks @darrellwarde! - Values specified within the@coalesce
directive are now also returned when selecting those fields, and not just when those fields are used in a filter. -
#5755
9c75f92
Thanks @angrykoala! - Remove support forconnectOrCreate
operations -
#6158
19dc0dd
Thanks @angrykoala! - Remove optionCONNECT_OR_CREATE
from argumentnestedOperations
from@relationship
directives as it is no longer relevant afterconnectOrCreate
have been removed -
#5898
a912404
Thanks @MacondoExpress! - Aggregations are no longer generated forID
fields. -
#5936
d48ea32
Thanks @mjfwebb! - Changes the result projection where there are multiple relationships between two nodes.In the case of using the connection API then multiple relationships will still be represented, as there is the ability to select the relationship properties. In the non-connection API case, the duplicate results will only return distinct results.
-
#6109
6801d70
Thanks @darrellwarde! - Thewhere
field for nested update operations has been moved within theupdate
input field.
Thewhere
in its previous location was a no-op for all nested operations apart fromupdate
.For example, the following syntax would filter the
Post
nodes to update in Version 6:mutation { updateUsers( where: { name: { eq: "Darrell" } } update: { posts: { where: { node: { title: { eq: "Version 7 Release Notes" } } } update: { node: { title: { set: "Version 7 Release Announcement" } } } } } ) }
In Version 7, this
where
has been moved inside theupdate
operation:mutation { updateUsers( where: { name: { eq: "Darrell" } } update: { posts: { update: { where: { node: { title: { eq: "Version 7 Release Notes" } } } node: { title: { set: "Version 7 Release Announcement" } } } } } ) }
-
#6124
d9cfd69
Thanks @angrykoala! - Fixed incorrect behavior ofsingle
andsome
filters on relationships to unions.Given the following union and relationship:
union Production = Movie | Series
and a relationship to this union:
type Actor @node { name: String! actedIn: [Production!]! @relationship(type: "ACTED_IN", direction: OUT) }
These queries previously returned incorrect results:
query { actors( where: { actedIn: { single: { Movie: { title_CONTAINS: "The Office" }, Series: { title_ENDS_WITH: "Office" } } } } ) { name } }
query { actors( where: { actedIn: { some: { Movie: { title_CONTAINS: "The Office" }, Series: { title_ENDS_WITH: "Office" } } } } ) { name } }
Previously, conditions inside single and some were evaluated separately for each concrete type in the union, requiring all to match. This was incorrect.
New behavior:
-
single
: Now correctly returns actors with exactly one related node across the whole union, rather than per type. -
some
: Now correctly returns actors with at least one matching related node of any type in the union.This fix also applies to the deprecated filters
actedIn_SINGLE
andactedIn_SOME
.
-
-
#5931
5ce7d1d
Thanks @darrellwarde! -DateTime
andTime
values are now converted from strings into temporal types in the generated Cypher instead of in server code using the driver. This could result in different values when the database is in a different timezone to the GraphQL server. -
#5778
56022ba
Thanks @darrellwarde! - The deprecateddirected
argument has been removed, andqueryDirection
now only accepts two possible values -DIRECTED
(default) andUNDIRECTED
.Additionally, the
directedArgument
setting ofexcludeDeprecatedFields
has been removed as these deprecated fields have been removed. -
#5976
7ddde75
Thanks @angrykoala! - Sets addVersionPrefix to true by default, this will prepend the Cypher version to all queries by default, ensuring that the correct Cypher version is used in Neo4j:CYPHER 5 MATCH(this:Movie)
This may be incompatible with older versions of Neo4j and can be disabled by setting
cypherQueryOption.addVersionPrefix
in the context to false:{ cypherQueryOptions: { addVersionPrefix: true, }, }
For example, for an apollo server:
await startStandaloneServer(server, { context: async ({ req }) => ({ req, cypherQueryOptions: { addVersionPrefix: false, }, }), listen: { port: 4000 }, });
-
[#5819](http...
@neo4j/graphql@6.6.1
Patch Changes
-
#6171
c75cda3
Thanks @angrykoala! - Cypher optimized for connections only containing aggregate fields. The following query:{ moviesConnection { aggregate { count { nodes } } } }
Will generate the new Cypher:
CALL { MATCH (this:Movie) RETURN { nodes: count(DISTINCT this) } AS var0 } RETURN { aggregate: { count: var0 } } AS this
Instead of the less performant previous Cypher:
CALL { MATCH (this:Movie) RETURN { nodes: count(DISTINCT this) } AS var0 } CALL { WITH * MATCH (this1:Movie) WITH collect({ node: this1 }) AS edges WITH edges, size(edges) AS totalCount CALL { WITH edges UNWIND edges AS edge WITH edge.node AS this1 RETURN collect({ node: { __id: id(this1), __resolveType: "Movie" } }) AS var2 } RETURN var2, totalCount } RETURN { edges: var2, totalCount: totalCount, aggregate: { count: var0 } } AS this