在Neo4J中,如何将标签设置为Java的密码查询中的参数?

2022-09-04 08:30:16

我在Java的Neo4J中的cypher中的参数有问题。我运行嵌入的数据库。

代码应该是这样的(GraphDB.cypher直接进入执行引擎)

HashMap<String, Object> parameter = new HashMap<>();
parameter.put("theLabel1", "Group");
parameter.put("theRelation", "isMemberOf");
parameter.put("theLabel2", "Person");
GraphDB.cypher("MATCH (n1:{theLabel1})-[r:{theRelation}]->(n2:{theLabel2}) RETURN n1, r, n2", parameter);

但它以这个例外结束

Exception in thread "main" Invalid input '{': expected whitespace or a label name (line 1, column 11)
"MATCH (n1:{theLabel1})-[r:{theRelation}]->(n2:{theLabel2}) RETURN n1, r, n2"

文档(和教程)告诉使用 { } 来覆盖参数,但这也用作属性的密码 json 表示法。@See http://docs.neo4j.org/chunked/milestone/tutorials-cypher-parameters-java.html

有没有另一种方法可以解决这个问题,而不是像这样构建查询字符串(或使用其他模板方法)

GraphDB.cypher("MATCH (n:" + labelName + ")-[r:" + relationName + "]->...

这是必需的,因为目标标签可以更改,并且我想完全重用代码。

提前致谢。

[[在得到A(叹息)后编辑不作为答案]]

由于目前不支持这种形式的参数(2014.6),因此在发送查询之前,我将运行一个小的替换器。

HashMap<String, Object> parameter = new HashMap<>();
parameter.put("theLabel1", "Group");
parameter.put("theRelation", "isMemberOf");
parameter.put("theLabel2", "Person");

parameter.put("aName", "Donald Duck");

GraphDB.cypher("MATCH (n1:#theLabel1#)-[r:#theRelation#]->(n2:#theLabel2#) WHERE n2.Name = {aName} RETURN n1, r, n2", parameter);

... with ...

public static ExecutionResult cypher(String query, Map<String, Object> params) {
    for (String key : params.keySet()) {
        query = query.replaceAll("#" + key + "#", String.valueOf(params.get(key)));
    }
    return params == null ? cypherEngine.execute(query) : cypherEngine.execute(query, params);
}

可以有一个更可读性


答案 1

恐怕目前不支持。

它可能出于与本期解释的原因完全相同的原因:https://github.com/neo4j/neo4j/pull/1542

参数化查询背后的想法是重用(缓存)执行计划。如果节点标签或关系类型发生变化,则执行计划将完全不相同,从而破坏了执行计划缓存的有用性。


答案 2

只是想出了一种方法来完成这个,因为我遇到了同样的事情:

MATCH (n) WHERE {label} IN labels(n)

labels() 函数返回节点上的所有标签,IN 运算符测试列表中是否存在。显然,Cypher允许这种构造,因为它利用了谓词中变量字段中的参数。根据 Cypher 文档,比较 WHERE 子句中的标签或属性以及节点定义中的直接属性/标签嵌入以相同的方式进行优化,因此不应对性能产生重大影响。

不确定支持多种可能标签的简单方法...


推荐