我尝试在Java中编写一个函数,在我的Neo4j图形数据库中查找具有相同名称和标签的节点。
@UserFunction(value = "boris.example")
@Description("finds nodes with same name")
public ResourceIterator<Node> passName(@Name("nodeId") long nodeId)
{
Node nodeX = null;
Node node = db.getNodeById( nodeId ); //Find node with spcific ID
Object nameVal = node.getProperties("name"); //Get its name
Label label = Label.label("VersionableObject"); //Decl. of label
// Find nodes by label and name
ResourceIterator<Node> nodes = db.findNodes(label, "name", nameVal);
nodes.close();
return nodes;
}
此功能导致以下异常,拒绝启动Neo4j:
&#34; ResourceIterator<Node>
位置0处的参数passName
类型Label
无法转换为Neo4j类型:不知道如何将org.neo4j.graphdb.ResourceIterator
映射到Neo4j类型系统。&#34;
然后我尝试使用
将ResourceIterator转换为StreamStream<Node> nodesStream = nodes.stream();
相同错误 - Neo4j无法映射Stream ..
ResourceIterator<Node> nodes = db.findNodes(label, "name", nameVal);
while (nodes.hasNext()) {
nodeX = nodes.next();
}
nodes.close();
return nodeX;
Neo4j中的输出为空,即使它应该找到3个节点。
将流转换为数组或列表也不起作用。
查找一个节点并显示自身或其属性,例如:
Node node = db.getNodeById( nodeId );
Map<String, Object> propertyMap = node.getProperties("name");
修改
使用mode.READ将@UserFunction更改为@Procedure后:
package org.neo4j.example.procedure_template;
import org.neo4j.graphdb.ResourceIterator;
import java.util.stream.Stream;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Label;
import org.neo4j.graphdb.Node;
import org.neo4j.logging.Log;
import org.neo4j.procedure.*;
import org.neo4j.procedure.Description;
import org.neo4j.procedure.Name;
public class FindNode {
@Context
public GraphDatabaseService db;
@Context
public Log log;
public FindNode() {
}
@Procedure(value = "boris.getAllNodesWithProperty", mode = Mode.READ)
@Description("boris.getAllNodesWithProperty - finds Node by ID and return defined Property")
public Stream<Node> passName(@Name("nodeId") long nodeId)
{
Node node = db.getNodeById( nodeId );
Object nameVal = node.getProperties("name");
Label label = Label.label("VersionableObject");
ResourceIterator<Node> nodes = db.findNodes(label, "name", nameVal);
Stream<Node> nodesStream = nodes.stream();
return nodesStream;
}
}
在这种情况下,我得到:&#34;零输出字段的程序必须声明为VOID&#34;。
有什么想法吗? 谢谢!
答案 0 :(得分:1)
在Neo4j中,您可以通过创建一些自定义user defined function
或procedure
来扩展Cypher。
user defined function
只是一个转换器,它是只读的,并返回一种类型,可以是:long, Long, double, Double, boolean, Boolean, String, Node, Relationship, Path, Map<String, Object, or List<T>
procedure
可以接受参数,对数据库执行操作,并返回结果(作为Stream)。
在您的代码中,您定义了user function
,我认为您想要的是procedure
。这就是为什么您从ResourceIterator
到Neo4j Type System
的投射错误。
你必须做出这些改变:
@UserFunction(value = "boris.example")
替换为@Procedure(value = "boris.example", mode = Mode.READ)
Stream<Node>
干杯。
程序必须返回pojo
或简单类型。所以你必须将你的Node
包裹在这样的pojo中:
public class FindNode {
@Context
public GraphDatabaseService db;
@Context
public Log log;
@Procedure(value = "boris.getAllNodesWithProperty", mode = Mode.READ)
@Description("boris.getAllNodesWithProperty - finds Node by ID and return defined Property")
public Stream<NodeResult> passName(@Name("nodeId") long nodeId)
{
Node node = db.getNodeById( nodeId );
Object nameVal = node.getProperty("name");
Label label = Label.label("VersionableObject");
ResourceIterator<Node> nodes = db.findNodes(label, "name", nameVal);
return nodes.stream().map( item -> new NodeResult(item));
}
public class NodeResult {
public final Node node;
public NodeResult(Node node) {
this.node = node;
}
}
}