Как вернуть несколько узлов в Neo4j, используя плагин Java?

Я пытаюсь написать функцию на 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:

"Довод ResourceIterator<Node> в положении 0 в passName с типом Label не может быть преобразован в тип Neo4j: не знаю, как отобразить org.neo4j.graphdb.ResourceIterator к системе типов Neo4j."

Затем я попытался преобразовать ResourceIterator в поток с помощью

Stream<Node> nodesStream = nodes.stream();

Та же ошибка - Neo4j не может отобразить поток..

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");

РЕДАКТИРОВАТЬ

После изменения @UserFunction на @Procedure с mode.READ:

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;
       }

} 

В этом случае я получаю: "Процедуры с нулевыми полями вывода должны быть объявлены как VOID".

Есть идеи? Спасибо!

1 ответ

Решение

В Neo4j вы можете расширить Cypher, создав несколько пользовательских user defined function или же procedure,

user defined function это просто конвертер, он доступен только для чтения и возвращает единственный тип, который может быть: long, Long, double, Double, boolean, Boolean, String, Node, Relationship, Path, Map<String, Object, or List<T>

procedure Может принимать аргументы, выполнять операции с базой данных и возвращать результаты (в виде потока).

В вашем коде вы определили user functionи я думаю, что вы хотите это procedure, Вот почему у вас есть ошибка приведения ResourceIterator к Neo4j Type System,

Вы должны сделать эти изменения:

  • замещать @UserFunction(value = "boris.example") от @Procedure(value = "boris.example", mode = Mode.READ)
  • Измените тип возврата вашего метода на Stream<Node>

Приветствия.

редактировать

Процедура должна вернуть pojo или простой тип. Так что вы должны обернуть Node в пойо вот так:

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;
        }
    }


}
Другие вопросы по тегам