Syntax error on running Cypher Query with dynamic

2019-06-12 22:49发布

问题:

Hello i'm trying to get data by a dynamic Cypher query.. However got an exception like:

org.neo4j.rest.graphdb.query.CypherTransactionExecutionException: Error executing cypher statements [{code=Neo.ClientError.Statement.InvalidSyntax, message=Invalid input '{': expected whitespace or a label name (line 1, column 54)
"MATCH (parentNode:ParentEntity)-[:HAS_A]->(childNode:{dynamicChildEntityType})= WHERE id(parentNode)={parentNodeId}  RETURN childNode order by childNode.orderNr"
                                                      ^}]

while trying to call method:

@Override
public List<ChildEntity> getChildrenOf(Long parentNodeId, String dynamicChildEntityType) {
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("dynamicChildEntityType", dynamicChildEntityType);
    params.put("parentNodeId", parentNodeId);


    String cql = "MATCH (parentNode:ParentEntity)-[:HAS_A]->(childNode:{dynamicChildEntityType})= WHERE id(parentNode)={parentNodeId}  RETURN childNode order by childNode.orderNr";


    return parentRepository.query(cql, params).as(List.class);

}

can you see what is wrong? Can't i use parameters for labels? If so, what do you suggest?

Thanks in advance.

Note: i'm using Neo4j v2.1.6 over Rest Api.

回答1:

You cannot use parameterized labels in Cypher. The rationale for this is that a different label might result in a complete separate query plan. Think of labels having an index, other without indexes, etc. Cypher caches the query plan for a parameterized Cypher string, therefore it's not possible to have labels as parameters.

For labels and relationship types you need to use string concatenation on the client side.



回答2:

You cannot set labels dynamically via parameters, the same is true for relationship types as well.

You can use string concatenation instead :

    @Override
    public List<ChildEntity> getChildrenOf(Long parentNodeId, String dynamicChildEntityType) {

      Map<String, Object> params = new HashMap<String, Object>();
      params.put("dynamicChildEntityType", dynamicChildEntityType);
      params.put("parentNodeId", parentNodeId);


      String cql = "MATCH (parentNode:ParentEntity)-[:HAS_A]->(childNode:"+dynamicChildEntityType+"})= WHERE id(parentNode)={parentNodeId}  RETURN childNode order by childNode.orderNr";


      return parentRepository.query(cql, params).as(List.class);
  }

Other way is to use the addLabels procedure from the APOC library:

its works like this

CALL apoc.create.addLabels(n, {dynamicChildEntityType}) YIELD node

Here is the link of APOC NEO4J APOC