Search code examples
neo4jneo4jclientneo4j-spatial

Neo4j spatial withinDistance only returns one node


I am using the spatial server plugin for Neo4j 2.0 and manage to add Users and Cities with their geo properties lat/lon to a spatial index "geom". Unfortunately I cannot get the syntax right to get them back via Neo4jClient :( What I want is basically:

  1. Translate the cypher query START n=node:geom('withinDistance:[60.0,15.0, 100.0]') RETURN n; to Neo4jClient syntax so I can get all the users within a given distance from a specified point.

  2. Even more helpful would be if it is possible to return the nodes with their respective distance to the point?

  3. Is there any way to get the nearest user or city from a given point without specify a distance?


UPDATE

After some trial and error I have solved question 1 and the problem communicating with Neo4j spatial through Neo4jClient. Below Neo4jClient query returns 1 user but only the nearest one even though the database contains 2 users who should be returned. I have also tried plain cypher through the web interface without any luck. Have I completely misunderstood what withinDistance is supposed to do? :) Is there really no one who can give a little insight to question 2 and 3 above? It would be very much appreciated!

var queryString = string.Format("withinDistance:[" + latitude + ", " + longitude + ", " + distance + "]");
        var graphResults = graphClient.Cypher
            .Start(new { user = Node.ByIndexQuery("geom", queryString) })
            .Return((user) => new
            {
                EntityList = user.CollectAsDistinct<UserEntity>()
            }).Results;

Solution

  • After some trial and error and help from the experts in the Neo4j google group all my problems are now solved :)

    1. Neo4jClient can be used to query withinDistance as below. Unfortunately withinDistance couldn't handle attaching parameters in the normal way so you would probably want to check your latitude, longitude and distance before using them. Also those metrics have to be doubles in order for the query to work.

      var queryString = string.Format("withinDistance:[" + latitude + ", " + longitude + ", " + distance + "]");
      var graphResults = graphClient.Cypher
                      .Start(new { city = Node.ByIndexQuery("geom", queryString) })
                      .Where("city:City")
                      .Return((city) => new
                      {
                          Entity = city.As<CityEntity>()
                      })
                      .Limit(1)
                      .Results;
      
    2. Cypher cannot be used to return distance, you have to calculate it yourself. Obviously you should be able to use REST http://localhost:7474/db/data/index/node/geom?query=withinDistance:[60.0,15.0,100.0]&ordering=score to get the score (distance) but I didn't get that working and I want to user cypher.

    3. No there isn't but limit the result to 1 as in the query above and you will be fine.

    A last note regarding this subject is that you should not add your nodes to the spatial layer just the spatial index. I had a lot of problems and strange exceptions before figure this one out.