Как вернуть несколько узлов в 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, используя

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 с режимом.ЧИТАЙТЕ:

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».

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


person Grapheneer    schedule 13.07.2017    source источник


Ответы (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 в 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;
        }
    }


}
person logisima    schedule 13.07.2017
comment
Спасибо за ваш ответ. Я пытался сделать это, но потом получаю: Запуск Neo4j не удался: Компонент 'org.neo4j.server.database.LifecycleManagingDatabase@63f85119' был успешно инициализирован, но не запустился. См. приложенное исключение причины Процедуры с нулевыми полями вывода должны быть объявлены как VOID - person Grapheneer; 13.07.2017
comment
Определен здесь в строке 63: fossies.org/linux/neo4j/community/kernel/src/main/java/org/ - person Grapheneer; 13.07.2017