Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to dynamically construct a neo4j cypher query using the GraphRepository pattern

CONTEXT : I am developing a java Spring Boot system backed by a neo4j database. I access the database using the "ClassRepo extends GraphRepository" structure. Writing queries is a simple case of hard coding in my precise query and replacing a specified part of it with a supplied parameter (in this case courseName).

@Query("MATCH (node:Course) WHERE node.name = {courseName}  RETURN node LIMIT 1")
Course findByName(@Param("courseName") String name);

This has all worked fine for me, allowing me to return one, or many results without issue. However, as my project has developed I now offer a large list of options to search by (faceted search, think amazon product filters). It seems silly to write a static cipher query for each and every permutation of chosen, or not chosen filtering options.

My solution (attempt) was to pass in parts of the query as parameters, in essence making a string query builder :

@Query("MATCH (course:Course) -[r]-> (description:CourseYearDescription) " +
        "WITH course, count(description) as relationCount, collect(description) as descriptions " +
        "WHERE relationCount > {numberOfYears} {returnCourse}")
Iterable<Course> findCourseWithNumberOfYears(
        @Param("numberOfYears") int numberOfYears,
        @Param("returnCourse") String returnCourse
);

Where "returnCourse" is a string with the value "RETURN course". I know for a fact that "RETURN course" entered statically in the query string works. I've just removed it and passed the string value in as a parameter to see if it can generate the same query and run it at run time.

This had no real success, returning me to an error page and printing out the following stack:http://pastebin.com/J9VBfpxw

QUESTION: Is there a way to append/insert strings into a cypher query strings used by a GraphRepository, so that the query can be altered dynamically, ie add a where clause to the end of a match query at run time.

like image 914
Jack Dalton Avatar asked Jan 24 '16 17:01

Jack Dalton


People also ask

What language's can be used to query Neo4j?

Cypher is Neo4j's graph query language that lets you retrieve data from the graph. It is like SQL for graphs, and was inspired by SQL so it lets you focus on what data you want out of the graph (not how to go get it).

What Cypher clauses can you use to create a node?

The CREATE clause is used to create nodes and relationships.

What is the correct syntax to create a node with a property in Neo4j?

In Neo4j, properties are the key-value pairs which are used by nodes to store data. CREATE statement is used to create node with properties, you just have to specify these properties separated by commas within the curly braces "{ }". Syntax: CREATE (node:label { key1: value, key2: value, . . . . . . . . . })

What is optional match in Neo4j?

An OPTIONAL MATCH matches patterns against your graph database, just like a MATCH does. The difference is that if no matches are found, OPTIONAL MATCH will use a null for missing parts of the pattern. OPTIONAL MATCH could be considered the Cypher equivalent of the outer join in SQL.


1 Answers

No, there isn't. SDN/Neo4j OGM will not modify custom queries at run time and merely hands them off to be executed by the Cypher engine. Hence, the only things you can parameterize are those that Cypher will allow you to (http://neo4j.com/docs/stable/cypher-parameters.html).

Agree that it does not make sense to define multiple @Query statements for each variation, but what you can do is build your query as a string and use the Neo4jOperations.query* methods that will accept your dynamically generated Cypher queries and a map of parameters (again, parameters that are valid in a Cypher statement).

Hope that helps.

like image 53
Luanne Avatar answered Nov 09 '22 11:11

Luanne