Releases: neo4j/cypher-dsl
2021.2.1
Now with optional driver integration and executable results. Please have a look at the new section in the docs: http://neo4j-contrib.github.io/cypher-dsl/current/#driver-integration
🚀 Features
- Distinguish between statements and result statements: The Cypher-DSL knows whether a statement would actually return
data or not - Provide optional integration with the Neo4j-Java-Driver to execute statements.
- Allow to register Spring converters with the annotation processor. [codegen]
- GH-182 - Add support for scalar converter functions.
- GH-183 - Add trim function.
- GH-184 - Add split function.
- GH-180 - Add support for LOAD CSV and friends.
- GH-187 - Add
returningRaw
for returning arbitrary (aliased) Cypher fragments (bot as part of a statement or as a
generalRETURN xxx
clause without preceding query) - Resolve named parameters in raw literals: You can mix now the expression placeholder
$E
and named parameters in raw
Cypher literals giving you much more flexibility in regards what to pass to the raw litera.
🐛 Bug Fixes
- GH-177 - Create a valid loadable and instantiable name when working on nested, inner classes. [codegen]
- GH-186 - Pretty print subqueries and fix double rendering of Labels after subquery.
🧹 Housekeeping
- Remove unnecessary subpackage 'valid'. [codegen] (test code only)
- Upgrade to GraalVM 21.1.0.
- Update Spring dependencies for codegen.
Thanks to @Andy2003 for contributing to this release.
2021.2.0
2021.2 doesn't bring any new features apart from being now a Java library supporting the Java module system not only with automatic module names but also with a correct module-info.java
when running on JDK 11+ on the module path.
The Cypher-DSL uses the technique of JEP 238: Multi-Release JAR Files to provide a module-info.java
for projects being on JDK 11+.
The MR-Jar allows us to compile for JDK 8 but also support JDK 11 (we choose 11 as it is the current LTS release as time of writing).
To use the Cypher-DSL in a modular application you would need to require the following modules:
module org.neo4j.cypherdsl.examples.core {
requires org.neo4j.cypherdsl.core;
}
This release comes with a small catch: We do support using some QueryDSL features. Query-DSL will have correct automatic module names in their 5.x release and we asked them to backport those to the 4.x line on which the Cypher-DSL optionally depends (See 2805).
Until then we statically require (that is "optional" in module speak) Query-DSL via the artifact name. This can cause errors when the artifact (querydsl-core.jar
) is renamed via the build process or similar. We are gonna improve that as soon as we can depend on fixed automatic module names.
Apart from this big change there is no change in any public API. This release should be a drop-in replacement for the prior.
A big thank you to @sormuras for his invaluable lessons about the Java module system.
2021.1.2
This release comes with two notable things: It uses a couple of annotations on the API to guide developers using it correctly. IDEs like IDEA will now issue warnings if you don't use a returned builder, or a new instance of an object while wrongly assuming you mutated state.
In the light of that we discovered that the RelationshipChain
pattern was mutable and returning a mutated instance while it should have returned a fresh one.
Warning This might be a breaking change for users having code like this:
var pattern = Cypher.node("Start").named("s")
.relationshipTo(Cypher.anyNode())
.relationshipTo(Cypher.node("End").named("e"));
pattern.named("x");
Prior to 2021.1.2 this would give the pattern the name x
and modify it in place.
From 2021.1.2 onwards you must use the returned value:
pattern = pattern.named("x");
We think that this change is crucial and necessary as all other patterns are immutable as intended and in sum, they build
up truly immutable statements. One pattern that is mutable like the above invalides the whole guarantee about the statement.
🚀 Features
- Add
named(SymbolicName s)
to RelationshipChain. - Generate $TYPE field containing the relationship type. [SDN 6 Annotation Processor]
- Introduce some optional annotations for guidance along the api.
📖 Documentation
- GH-173 - Improve documentation. [A collection of small improvements]
🐛 Bug Fixes
- GH-174 - Extract types via the visitor API and avoid casting element types. [SDN 6 Annotation Processor]
- Ensure immutability of
RelationshipChain
.
🧹 Housekeeping
- Remove unnecessary close (will be taken care of via
@Container
). [Only test related] - Run tests on JDK 16
2021.1.1
2021.1.0
2021.1.0 comes with a ton of new features and a handful of breaking changes. Fear not, the breaking changes are resolvable by recompiling your application. We turned Node
, Relationship
and Property
into interfaces and provide now NodeBase
and RelationshipBase
so that you can use them to build a static meta-model of your application. A PropertyBase
might follow.
Find out everything about the new possibility to define a static meta model in the manual. The manual also includes a major part about the two new modules we offer: org.neo4j:neo4j-cypher-dsl-codegen-core
and org.neo4j:neo4j-cypher-dsl-codegen-sdn6
. neo4j-cypher-dsl-codegen-core
provides the infrastructure necessary to build code generators for creating a domain model following our recommendation and neo4j-cypher-dsl-codegen-sdn6
is a first implementation of that: A Java annotation processor that can be added to any Spring Data Neo4j 6 project in version 6.0.6 or higher. It will find your annotated domain classes and turn them into a model you can use to build queries.
Last but not least: We added support for some expressions of the more generic QueryDSL. This will require com.querydsl:querydsl-core
on the class path but only if you decide to call Cypher#adapt(foreignExpression)
. This is a feature that is driven by Spring Data Neo4j 6.1 in which we build upon this to provide a QuerydslPredicateExecutor
. Find more in this section of the manual.
🚀 Features
- GH-154 - Make Node and Relationship extendable.
- GH-155 - Provide infrastructure for generating a static meta model.
- GH-156 - Create an annotation processor for Spring Data Neo4j 6.
- GH-167 - Add support for some Query-DSL expressions.
- Introduce a statement context for allowing anonymous parameters (use
Cypher#anonParameter()
to define a parameter with a value but without a name. The name will be accessible on the statement after rendering). - Make rendering of constants as parameters configurable.
- Allow specification of the direction while creating a sort item.
- Introduce an interface for Property.
📖 Documentation
- GH-152 - Document usage of PatterElement in tests.
- GH-164 - Improve public extendable API and add documentation.
🐛 Bug Fixes
- Fix SymbolicName#toString.
- Clear visited name cache after single queries.
🧹 Housekeeping
2021.0.2
WARNING: This will already be the last release of the 2021.0 line. 2021.1 will be API compatible but not ABI compatible, as some classes have been changed into interfaces. That means it is not a drop in replacement, but your application needs to be recompiled.
🚀 Features
- GH-157 - Provide a method to turn a Java map into an expression.
- GH-158 - Improve pretty printing of subqueries.
- Allow the use of raw cypher as expressions.
- Allow symbolic names to be used as aliases.
- Cache some symbolic names.
- Add support for the keys() function.
📖 Documentation
- GH-152 - Document usage of PatterElement in tests.
🐛 Bug Fixes
- GH-149 - Avoid possible stackoverflow exception during visitor traversal.
- GH-159 - Fix missing labels for nodes after
WITH
.
🧹 Housekeeping
- GH-148 - Add jQAssistant rules and improve building documentation.
- Add Maven PMD plugin.
Thanks @Andy2003 for the improvements of the pretty printer.
2021.0.1
🚀 Features
- GH-147 - Configuration infrastructure for renderer. First use case being a simple, pretty printing renderer.
The feature looks like this:
var c = node("Configuration").named("c");
var d = node("Cypher-DSL").named("d");
var mergeStatement = merge(c.relationshipTo(d, "CONFIGURES"))
.onCreate()
.set(
d.property("version").to(literalOf("2021.0.1")),
c.property("prettyPrint").to(literalTrue())
)
.onMatch().set(c.property("indentStyle").to(literalOf("TAB")))
.returning(d).build();
var renderer = Renderer.getRenderer(Configuration.prettyPrinting());
System.out.println(renderer.render(mergeStatement));
and gives you:
MERGE (c:Configuration)-[:CONFIGURES]->(d:`Cypher-DSL`)
ON CREATE SET d.version = '2021.0.1', c.prettyPrint = true
ON MATCH SET c.indentStyle = 'TAB'
RETURN d
2021.0.0
2021.0.0 comes with a lot of new features.
Thanks to @Andy2003 for his contributions!
Andy is one of our first users outside Spring Data Neo4j 6 and he started to use the Cypher-DSL in Neo4j GraphQL Java. Neo4j GraphQL Java is a library to translate GraphQL based schemas and queries to Cypher and execute those statements with the Neo4j database.
It can be used from a wide variety of frameworks.
We are happy and proud to be part of this and even more so about the input and contribution we got back from Andy.
Of course thanks for your input in form of tickets and discussions go out to @utnaf, @aaramg, @K-Lovelace and @maximelovino as well!
Noteworthy
Two things should be mentioned:
The bugfix for GH-121 might change behavior for some users: The changes prevents the forced rendering of an alias for objects when the original object - the one that has been aliased - is passed down to the DSL after an alias has been created.
The original intention for that behaviour was related to Map projection, in which the alias is actually rendered before the object.
So now the use of an aliased expression the first time triggers a AS b
respectively b: a
in a map projection. All further calls will just render b
. If the original object is used again, a
will be rendered. If that is not desired in your query and you rely on the alias, make sure you use the aliased expression returned from .as("someAlias")
.
The other thing are the combined features GH-135 and GH-146. The Statement
class has become a fully fledged accessor to the Cypher String and the parameters used and if provided, the values for those. The following shows a small example:
var person = Cypher.node("Person").named("p");
var statement = Cypher
.match(person)
.where(person.property("nickname").isEqualTo(Cypher.parameter("nickname")))
.set(
person.property("firstName").to(Cypher.parameter("firstName").withValue("Thomas")),
person.property("name").to(Cypher.parameter("name", "Anderson"))
)
.returning(person)
.build();
assertThat(statement.getCypher())
.isEqualTo("MATCH (p:`Person`) WHERE p.nickname = $nickname SET p.firstName = $firstName, p.name = $name RETURN p");
Collection<String> parameterNames = statement.getParameterNames();
assertThat(parameterNames).containsExactlyInAnyOrder("nickname", "firstName", "name");
Map<String, Object> parameters = statement.getParameters();
assertThat(parameters).hasSize(2);
assertThat(parameters).containsEntry("firstName", "Thomas");
assertThat(parameters).containsEntry("name", "Anderson");
What's Changed
🚀 Features
- GH-122 - Add support for index hints.
- GH-123 - Expose nested building of nested properties as public API.
- GH-124 - Add support for Neo4j's mathematical functions.
- GH-127 - Allow dynamic property lookup.
- GH-128 - Provide asConditions for RelationshipPatterns.
- GH-129 - Allow Expressions as Parameter for Skip and Limit.
- GH-131 - Add support for projections on symbolic names.
- GH-133 - Allow symbolic names to be used as condition.
- GH-135 - Collect parameters defined on a statement.
- GH-141 - Provide a property function on all expressions.
- GH-142 - Provide a point function accepting generic expressions as parameter.
- GH-146 - Allow a statement to render itself.
📖 Documentation
- GH-126 - Document how to call arbitrary functions and procedures.
🐛 Bug Fixes
- Prevent double rendering of Node content when using generated names.
- GH-121 - Don't force rendering of aliases when the original object is used.
- GH-137 - Fix grouping of nested conditions.
🧹 Housekeeping
2020.1.6
No new features.
Re-released 2020.1.5 due downtime and staging issues of oss.sonatype.org.