Neo4j Spatial через REST через JAVA API не работает (для меня)

Я работаю над приложением Grails поверх Neo4J, которое я также хотел бы экспортировать как базу данных ГИС.

Глядя на примеры использования neo4j в GeoServer/uDig, кажется, что пространственная интеграция осуществляется только через встроенные базы данных neo4j.

Кто-нибудь знает, можно ли настроить так, чтобы мой Neo4J был доступен через REST, чтобы я мог взаимодействовать с ним из разных мест?

На первый взгляд кажется, что это должно быть возможно:

// Works with this embedded database
//def graphDb = new GraphDatabaseFactory().newEmbeddedDatabase("/tmp/foo.db");

// Doesn't work with this REST database
graphDb = new RestGraphDatabase("http://localhost:7474/db/data");

Transaction tx = graphDb.beginTx()

SpatialDatabaseService spatialService = new SpatialDatabaseService(graphDb)
SimplePointLayer layer = spatialService.createSimplePointLayer("points")

Со встроенной базой данных пространственный индекс создается просто отлично. Однако с базой данных REST я просто получаю нулевой указатель:

Caused by NullPointerException: null
->>  149 | createCompiler in org.neo4j.cypher.ExecutionEngine
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|     48 | <init>    in     ''
|     59 | createInnerEngine in org.neo4j.cypher.javacompat.ExecutionEngine
|     43 | <init>    in     ''
|     41 | getReferenceNode in org.neo4j.gis.spatial.utilities.ReferenceNodes
|     78 | getSpatialRoot in org.neo4j.gis.spatial.SpatialDatabaseService
|    114 | getLayer  in     ''
|    259 | containsLayer in     ''
|    303 | createLayer in     ''
|    287 | createSimplePointLayer in     ''
|    267 | createSimplePointLayer in     ''
|     37 | <init>    in net.foo.db.neo4j.Neo4JService

SpatialDatabaseService принимает GraphDatabaseService, поэтому я не понимаю, почему он не работает с REST.

Это баг или фича (или недоразумение с моей стороны?)

Я могу, конечно, использовать create index API для создания пространственного индекса:

graphDb.index().forNodes( "points", ["provider": "spatial", "geometry_type": "point", "lat": "lat", "lon":"lon"])

так что это работает, но я не могу создать новый слой таким образом.


person Dr Joe    schedule 28.10.2014    source источник


Ответы (2)


RestGraphDatabase — это поддельная база данных, которая не предлагает всех возможностей. Теоретически это можно заставить работать, но это будет очень расточительно, поскольку каждая предположительно встроенная операция будет передаваться по сети в виде http-запросов.

Установите Spatial как плагин на свой сервер, а затем получите к нему доступ с помощью методов REST плагина.

См.: http://neo4j-contrib.github.io/spatial/#spatial-server-plugin

person Michael Hunger    schedule 30.10.2014
comment
Хм, значит ли это, что если я не могу интегрировать neo4j в GeoServer и в то же время использовать базу данных в качестве основного компонента моего собственного приложения? Я надеялся сделать это, чтобы обеспечить слой визуализации поверх основной логики. - person Dr Joe; 30.10.2014

Хотя я действительно не понимаю, что вы делаете с этим приложением Grail и прочим, судя по вашим исключениям, похоже, что вы пытаетесь сделать что-то вроде этого:

ExecutionEngine executionEngine = new ExecutionEngine(graphDatabaseService);

где ExecutionEngine из cypher.javacompat, а GraphDatabaseService указывает на RestGraphDatabase.

ExecutionEngine основывается на нашем внутреннем API ядра, который он может получить только из встроенной базы данных.

Чтобы выполнять запросы Cypher к RestGraphDatabase, вам нужно получить его RestAPI из getRestAPI и использовать для него метод запроса.

Сообщение в этой группе Google объясняет это: https://groups.google.com/forum/#!topic/neo4j/Q6lsOakSgyA

Ниже приведен пример программы, которую я сделал, которая использует базу данных RestGraphDatabase для создания и выполнения запросов. Надеюсь это поможет.

package rash.experiments.neo4j;

import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.Transaction;
import org.neo4j.rest.graphdb.RestGraphDatabase;
import org.neo4j.rest.graphdb.query.RestCypherQueryEngine;
import org.neo4j.rest.graphdb.util.QueryResult;

public class Neo4JRestTest
{
    private static enum RelType implements RelationshipType
    {
        KNOWS
    }

    public static void main(String args[])
    {
        RestGraphDatabase graphDatabaseService = new RestGraphDatabase("http://10.20.230.12:7474/db/data/");
        RestCypherQueryEngine executionEngine = new RestCypherQueryEngine(graphDatabaseService.getRestAPI());

        try(Transaction transaction = graphDatabaseService.beginTx())
        {
            Node rash = graphDatabaseService.createNode();
            rash.setProperty("userId", 4);
            rash.setProperty("username", "rash");
            rash.setProperty("name", "Rahul Chaudhary");

            Node honey = graphDatabaseService.createNode();
            honey.setProperty("userId", 5);
            honey.setProperty("username", "honey");
            honey.setProperty("name", "Honey Anant");

            Relationship knowsRelationship = rash.createRelationshipTo(honey, RelType.KNOWS);
            knowsRelationship.setProperty("since", 2011);

            transaction.success();
        }

        try(Transaction transaction = graphDatabaseService.beginTx())
        {
            QueryResult<Map<String,Object>> executionResult = executionEngine.query("match (node) return node", null);
            Iterator<Map<String, Object>> resourceIterator = executionResult.iterator();

            while(resourceIterator.hasNext())
            {
                Set<Entry<String, Object>> map = resourceIterator.next().entrySet();
                for(Entry<String, Object> entry : map)
                {
                    Node node = (Node) entry.getValue();
                    System.out.println("UserId: " + node.getProperty("userId"));
                    System.out.println("Username: " + node.getProperty("username"));
                    System.out.println();
                }

                System.out.println("--------------------------\n");
            }

            transaction.success();
        }
    }
}
person Rash    schedule 25.02.2015