简体   繁体   English

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

[英]In Neo4J, how to set the label as a parameter in a cypher query from Java?

I have problems with parameter in cypher in Neo4J from Java. 我在Java中使用Neo4J中的cypher参数时遇到问题。 I run the the database embedded. 我运行嵌入的数据库。

The code should be like this (GraphDB.cypher goes directly to the ExecutionEngine) 代码应该是这样的(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);

but it ends in this exception 但它以此例外结束

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"

The documentation (and tutorial) tells to use the { } to cover the parameters, BUT this is also used as the cypher json notation for properties. 文档(和教程)告诉使用{}来覆盖参数,但这也用作属性的密码json表示法。 @See http://docs.neo4j.org/chunked/milestone/tutorials-cypher-parameters-java.html @参见http://docs.neo4j.org/chunked/milestone/tutorials-cypher-parameters-java.html

Is there another way to solve this issue rather than building the query string like this (or with other template methods) 是否有另一种方法来解决此问题,而不是像这样(或使用其他模板方法)构建查询字符串

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

This is needed because the target label can change and I want to reuse the code completly. 这是必需的,因为目标标签可以更改,我想完全重用代码。

Thanks in advance. 提前致谢。

[[EDITED AFTER GETTING A (sigh) NO AS ANSWER]] [[取得(叹气)没有作为答复后的行为]]

Since this form of parameter is currently (2014.6) not supported, I will run a little replacer right before sending the query. 由于这种形式的参数目前(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);
}

There can be a more readble 可以有更多的阅读

I am afraid this is not supported at the moment. 我担心此刻不支持此事。

And it might for the very same reason than the one explained in this issue: https://github.com/neo4j/neo4j/pull/1542 . 它可能与本期中解释的原因完全相同: https//github.com/neo4j/neo4j/pull/1542

The idea behind parametrized queries is to re-use (cache) execution plans. 参数化查询背后的想法是重用(缓存)执行计划。 If a node label or a relationship type varies, the execution plan wouldn't be the same at all, thus ruining the usefulness of execution plan caching. 如果节点标签或关系类型不同,则执行计划根本不会相同,从而破坏了执行计划缓存的有用性。

Just figured out a way to accomplish this as I was running into the same thing: 刚刚找到了实现这个目标的方法,因为我遇到了同样的事情:

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

The labels() function returns all labels on a node, and the IN operator tests for existence in the list. labels()函数返回节点上的所有标签,IN运算符测试列表中是否存在。 Apparently Cypher allows this construct because it's leveraging a parameter in a variable field in the predicate. 显然Cypher允许这种结构,因为它利用了谓词中变量字段中的参数。 According to the Cypher docs, comparing labels or properties in WHERE clauses and direct property/label embeds in the node definition are optimized the same way, so shouldn't be a significant performance hit. 根据Cypher文档,比较WHERE子句中的标签或属性以及节点定义中的直接属性/标签嵌入都以相同的方式进行优化,因此不应该是显着的性能损失。

Not sure about an easy way to support multiple possible labels... 不确定支持多种可能标签的简单方法......

Don't think of labels as the most important property for a document of information, instead, think of them as the schema for what property keys to populate in the "map". 不要将标签视为信息文档最重要的属性,而应将其视为“地图”中填充的属性键的模式。 (the awful name for neo4j to reference the properties object) (neo4j引用属性对象的可怕名称)

For NER, entities that share the same merge query, by definition share the same parameters being set at run-time; 对于NER,根据定义,共享相同合并查询的实体共享在运行时设置的相同参数; therefore, they should share a label, which makes a label hardcoded, not parameterized. 因此,他们应该共享一个标签,使标签硬编码,而不是参数化。

You can still query by properties. 您仍然可以按属性查询。 Values that would not affect the types of relationships between nodes, or the property keys themselves, should not be labels. 不影响节点之间关系类型的值或属性键本身不应该是标签。

You can also add labels to existing nodes, ideally as new properties are added to an existing node, an expansion of the node's definition. 您还可以向现有节点添加标签,理想情况是将新属性添加到现有节点,扩展节点的定义。 If you are creating relationships between nodes, that would be an ideal time to add labels based on the analysis of node properties, as long as the relationship type is somewhat unique to the labels of each node. 如果要在节点之间创建关系,那么这将是基于节点属性分析添加标签的理想时间,只要关系类型对每个节点的标签有些独特。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM