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

在Neo4J中,如何在Java的密码查询中将标签设置为参数?,java,neo4j,cypher,Java,Neo4j,Cypher,我对来自Java的Neo4J中的cypher中的参数有问题。我运行嵌入式数据库 代码应该是这样的(GraphDB.cypher直接进入ExecutionEngine) 文档(和教程)告诉我们使用{}来覆盖参数,但这也被用作属性的cypher-json符号。 @看 有没有其他方法可以解决这个问题,而不是像这样构建查询字符串(或使用其他模板方法) 这是必需的,因为目标标签可以更改,我希望完全重用代码 提前谢谢 [[在得到(叹息)不作为答案后编辑]] 由于目前(2014.6)不支持这种形式的参数,我将

我对来自Java的Neo4J中的cypher中的参数有问题。我运行嵌入式数据库

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

文档(和教程)告诉我们使用{}来覆盖参数,但这也被用作属性的cypher-json符号。 @看

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

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

提前谢谢

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

由于目前(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);
}
HashMap参数=newhashmap();
参数put(“标签1”、“组”);
参数put(“theRelation”、“isMemberOf”);
参数put(“标签2”、“人”);
参数put(“aName”、“唐老鸭”);
GraphDB.cypher(“匹配(n1:#标签1#)-[r:#关系#]->(n2:#标签2#),其中n2.Name={aName}返回n1,r,n2”,参数);
... 具有
公共静态ExecutionResult密码(字符串查询、映射参数){
for(字符串键:params.keySet()){
query=query.replaceAll(“#”+key+“#”,String.valueOf(params.get(key));
}
返回参数==null?cypherEngine.execute(查询):cypherEngine.execute(查询,参数);
}

可以有一个更可读的

恐怕目前不支持

这可能与本期中解释的原因完全相同:


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

刚刚找到了一种方法来实现这一点,因为我遇到了同样的问题:

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


不确定是否有一种简单的方法可以支持多个可能的标签…

不要将标签视为信息文档最重要的属性,而是将其视为“映射”中要填充的属性键的模式。(neo4j引用properties对象的可怕名称)

对于NER,根据定义,共享相同合并查询的实体共享在运行时设置的相同参数;因此,它们应该共享一个标签,使标签硬编码,而不是参数化

您仍然可以按属性进行查询。不会影响节点之间关系类型或属性键本身的值不应为标签


您还可以向现有节点添加标签,理想情况下是向现有节点添加新特性,这是节点定义的扩展。如果您要在节点之间创建关系,那么这将是基于节点属性分析添加标签的理想时机,只要关系类型对于每个节点的标签来说都是唯一的。

是的,您可以静态定义查询模板,但提供此类功能有点超出了Neo4j的范围,你不觉得吗?@Raxa,你用“replacer”的解决方案很有趣。乍一看,您对“#标签1#”的使用似乎是静态的,因此没有解决使用
参数
动态指定Cypher
标签的真正问题。但是,如果将其视为一个简单的占位符,并由
参数
中的匹配项替换,则它确实可以动态地传递
标签
。不确定是否会有任何标准解决方案,但这是一个非常有趣的缓解措施。令人遗憾的是,Neo4J文档向我们兜售了7.5中的想法,“这意味着开发人员不必求助于字符串构建来创建查询。”显然,这根本不是真正的动机。如果Cypher引擎解决了这些问题,并代表我们进行了上述替换,那就更明智了。开发人员可以完全参数化查询,随着Neo4J的不断改进,它可以在任何地方利用这种参数化。现在Neo4J 4还不支持这种功能吗?我正在尝试一个类似的查询,但得到了相同的错误。非常简单的答案。天才!为了补充这个答案,如果您还想对关系执行相同的操作,您需要使用类型内置函数,例如:
MATCH(a)-[r]->(b)其中{relName}=TYPE(r)返回ID(r)作为relId,TYPE(r)作为relName
您可以使用
any()
函数支持多个标签。例如,
MATCH(o)WHERE ANY(标签中的项目(o)WHERE item IN$list\u of_labels)
但没有优化,它将是一个完整的数据库扫描,每个节点都有检查,而按标签查找是一个标签扫描存储操作。您可以动态构造您的密码查询,然后。使用apoc.cypher.run来执行它对我来说很有效,不过我必须去掉javascript中查询Neo4J4的花括号,例如,
MATCH(pOg),其中pOg.name=$pOgName和$pOgLabel IN LABELS(pOg)
GraphDB.cypher("MATCH (n:" + labelName + ")-[r:" + relationName + "]->...
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);
}
MATCH (n) WHERE {label} IN labels(n)