Question

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;
Was it helpful?

Solution 2

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.

OTHER TIPS

The client won't let you using the fluent system, the closest you could get would be something like:

var geoQuery = client.Cypher
    .Start( new{n = Node.ByIndexLookup("geom", "withindistance", "[60.0,15.0, 100.0]")})
    .Return(n => n.As<????>());

but that generates cypher like:

START n=node:`geom`(withindistance = [60.0,15.0, 100.0])   RETURN n

which wouldn't work, which unfortunately means you have two options:

  1. Get the code and create a pull request adding this in
  2. Go dirty and use the IRawGraphClient interface. Now this is VERY frowned upon, and I wouldn't normally suggest it, but I don't see you having much choice if you want to use the client as-is. To do this you need to do something like: (sorry Tatham)

((IRawGraphClient)client).ExecuteGetCypherResults<Node<string>>(new CypherQuery("START n=node:geom('withinDistance:[60.0,15.0, 100.0]') RETURN n", null, CypherResultMode.Projection));

I don't know the spatial system, so you'll have to wait for someone who does know it to get back to you for the other questions - and I have no idea what is returned (hence the Node<string> return type, but if you get that worked out, you should change that to a proper POCO.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top