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

Rax*_*axa 10 java neo4j cypher

我在Java中使用Neo4J中的cypher参数时遇到问题.我运行嵌入的数据库.

代码应该是这样的(GraphDB.cypher直接转到ExecutionEngine)

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);
Run Code Online (Sandbox Code Playgroud)

但它以此例外结束

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"
Run Code Online (Sandbox Code Playgroud)

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

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

GraphDB.cypher("MATCH (n:" + labelName + ")-[r:" + relationName + "]->...
Run Code Online (Sandbox Code Playgroud)

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

提前致谢.

[[取得(叹气)没有作为答复后的行为]]

由于这种形式的参数目前(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);
}
Run Code Online (Sandbox Code Playgroud)

可以有更多的阅读

Rol*_*olf 9

我担心此刻不支持此事.

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

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

  • 遗憾的是,Neo4J 文档在 7.5 中向我们推销了“这意味着开发人员不必求助于字符串构建来创建查询”的想法。显然,这根本不是真正的动机。如果 Cypher 引擎解决了这些问题并代表我们进行了上述替换,那就更明智了。然后开发人员可以完全参数化查询,随着 Neo4J 随着时间的推移不断改进,它可以尽可能地利用这种参数化。 (2认同)
  • 现在 Neo4J 4 还不支持这个功能吗?我正在尝试类似的查询并得到相同的错误。 (2认同)

arp*_*ieb 7

刚刚找到了实现这个目标的方法,因为我遇到了同样的事情:

MATCH (n) WHERE {label} IN labels(n)
Run Code Online (Sandbox Code Playgroud)

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

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

  • 但是没有优化,它将是对每个节点进行检查的完整数据库扫描,而按标签查找是标签扫描存储操作。您可以动态构造您的密码查询,然后使用例如apoc.cypher.run来执行它 (2认同)