如何使用Java插件返回Neo4j中的多个节点?

时间:2017-07-13 08:15:26

标签: java neo4j neo4j-apoc neo4j-plugin

我尝试在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转换为Stream
Stream<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;。

有什么想法吗? 谢谢!

1 个答案:

答案 0 :(得分:1)

在Neo4j中,您可以通过创建一些自定义user defined functionprocedure来扩展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。这就是为什么您从ResourceIteratorNeo4j 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;
        }
    }


}