cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

NeoDash Maps: properties as points

guido
Graph Buddy

In this post @bennu_neo suggested a query to produce a point on a map. 
When I duplicate this and insert my own coordinates, it works fine:

UNWIND [{id: "1234", label: "H1", type: "House", point: point({latitude:51.22074896608231, longitude:4.4067613031634645})}] AS x
RETURN x

However, I need the point to be a node property (in this case: property "point" of node h:House, viz "point({latitude:51.22074896608231, longitude:4.4067613031634645})"). The query would therefore look like this:

MATCH (n:Name)-[r2:HAS_NAME_VARIANT]-(p:Producer)-[r:HAS_ADDRESS]->(a:Address) 
WHERE n.Name = $neodash_name_name
OPTIONAL MATCH (a:Address)-[r3:IS_HOUSE]->(h:House)
WITH p, h, h.point AS GEO
UNWIND [{id: p.ProducerID, label: "H1", type: "House", point: GEO }] AS x
RETURN x

This does not work. What am I missing?
Thanks!

1 ACCEPTED SOLUTION

Hi @glilienfield and @guido ,

I think this (https://community.neo4j.com/t5/integrations/neodash-maps-properties-as-points/m-p/64780/highlight/tr...) is a good solution to the problem.

If you don't want to write a separate script, It may also be interesting to look into apoc virtual nodes to create ephemeral nodes at query time so that they can be plotted on a map by NeoDash:

// Assuming that `Location` nodes have two string properties: `longitude` and `latitude`.
MATCH (n:Location)
WITH point({latitude: toFloat(n.latitude), longitude: toFloat(n.longitude)}) as point
RETURN apoc.create.vNode(['VirtualLocation'],{point: point}) 

 

View solution in original post

15 REPLIES 15

I think you are trying to return that map for each row returned from you match results from lines 1-3. If so, you just need to return the map, which will result in one map per row. 

MATCH (n:Name)-[r2:HAS_NAME_VARIANT]-(p:Producer)-[r:HAS_ADDRESS]->(a:Address) 
WHERE n.Name = $neodash_name_name
OPTIONAL MATCH (a:Address)-[r3:IS_HOUSE]->(h:House)
RETURN {id: p.ProducerID, label: "H1", type: "House", point: h.point } AS x

 Let me know if this is not what you were looking for?

Hi @glilienfield ,
Thanks for the suggestion.
Line 2 restricts the results to 1 person. In the current setup 1 person only has 1 house, therefore the result of lines 1->3 is always 1 row.  That is not the problem.
The problem seems to be the conversion of the fixed coordinates to contextual ones. Whatever format I have tried, the inclusion of h.point never seems to work.

Sorry, I am not understanding what is not working.  I am able to create nodes with point properties. What do you mean by 'conversion of the fixed coordinates to contextual ones?"

create({id: 0, point:point({latitude: 20, longitude: 56})})
create({id: 1, point:point({latitude: -20, longitude: 56})})

Screen Shot 2023-01-30 at 3.22.29 PM.png

Hi @glilienfield ,

Sorry for not having explained the issue clearly enough.
I have created 2 test queries, see attachment one.png. The one on the left states the coordinates explicitely (see top row), and works fine, see bottom row.
The one on the right does the same but gets the coordinates from the node property h.point. That doesn't work, see bottom row again.
I have tried different formats of h.point, including exotic ones such as "{\"srid\":{\"low\":4326,\"high\":0},\"x\":4.4067613031634645,\"y\":51.22074896608231}}" but none of them work.

The difference in scale of those two maps is significantly different. Do you expect a house marker to show on a globe map? Or, do you expect it to drill down automatically to street level because there is a marker to show? 

Can you try something like this:

create(p {ProducerID: 1234, point: point({latitude:51.22074896608231, longitude:4.4067613031634645})})
with {id: p.ProducerID, label: "H1", type: "House", point: p.point } AS x
RETURN x

Hi @glilienfield ,

Thanks for the reply.
The map is a default setting in NeoDash, so the same underlying map is used in both test reports: https://{s].tile.openstreetmap.org/{z}/{x}/{y}.png.

I tested your suggestion and that works fine (test3). But when I set the property h.point to exactly the same point({latitude:51.22074896608231, longitude:4.4067613031634645}) in test2, I again get the worldmap (which is kind of an error message).

The problem is not to get NeoDash to capture coordinates as such, but fetching them from a node property.
When I set the report type for test3 to Table (instead of Map), it returns: 

{"id":{"low":1234,"high":0},"label":"H1","type":"House","point":{"srid":{"low":4326,"high":0},"x":4.4067613031634645,"y":51.22074896608231}}

When I do the same for my test2, it returns:

{"id":"P882","label":"H1","type":"House","point":"point({latitude:51.22074896608231, longitude:4.4067613031634645})"}

So there is difference, but I don't know whether that is the cause. Anyhow, when I set the property h.point to the full 

{"srid":{"low":4326,"high":0},"x":4.4067613031634645,"y":51.22074896608231}},

that doesn't work either...

I see a big difference here. Notice that in your test2 as a table, the value of the 'point' property is enclosed in quotes. It is not interpreting the 'point' as a spatial type, but as a string. How are you setting the point property of the house node? 

h.point is presently a string. I have tried

point({latitude:51.22074896608231, longitude:4.4067613031634645})

as a float, but then the Map returns the worldmap and the Table returns nothing.

I think we are on to something. It can't be a string. I assume it has to be a spatial data time. What is the mechanism that you are using to set it? 

The import module in Workspace. 
Alternatives: string, float, integer, boolean, datetime

Now we got it. Workspace doesn't seem to have the capability to import and create a spatial data type. It would need to allow you to set a property as a function of multiple properties from the file properties.

I have the following two solutions:

1. write your own load csv script so you can calculate the point from its latitude and longitude values and set the point property

2. use workspace to import the latitude and longitude values as properties, then run a simple update script after importing to update each new node with the point property calculated from the latitude and longitude values. 

Hi @glilienfield ,
thanks for all the research! This indeed seems to be the problem. 
I will have a go with Niels' suggestion and if that fails I will turn to scripting as you indicate.
I have posted a feature request on the Workspace board so maybe you could support it by voting on it?  https://feedback.neo4j.com/workspace/p/importing-spatial-date-types 
Thanks.

Hi @glilienfield and @guido ,

I think this (https://community.neo4j.com/t5/integrations/neodash-maps-properties-as-points/m-p/64780/highlight/tr...) is a good solution to the problem.

If you don't want to write a separate script, It may also be interesting to look into apoc virtual nodes to create ephemeral nodes at query time so that they can be plotted on a map by NeoDash:

// Assuming that `Location` nodes have two string properties: `longitude` and `latitude`.
MATCH (n:Location)
WITH point({latitude: toFloat(n.latitude), longitude: toFloat(n.longitude)}) as point
RETURN apoc.create.vNode(['VirtualLocation'],{point: point}) 

 

@niels_dejong I integrated your suggestion into my query:

MATCH (n:Name)-[r2:HAS_NAME_VARIANT]-(p:Producer)-[r:HAS_ADDRESS]->(a:Address) 
WHERE n.Name = $neodash_name_name
OPTIONAL MATCH (a:Address)-[r3:IS_HOUSE]->(h:House)
WITH point({latitude: toFloat(h.latitude), longitude: toFloat(h.longitude)}) as point
RETURN apoc.create.vNode(['VirtualLocation'],{point: point}) 

and it works! Thanks!

If returning a map works as well, as you had in your earlier queries, the the following should work too. I didn't know you had the latitude and longitude in the data already.

MATCH (n:Name)-[r2:HAS_NAME_VARIANT]-(p:Producer)-[r:HAS_ADDRESS]->(a:Address) 
WHERE n.Name = $neodash_name_name
OPTIONAL MATCH (a:Address)-[r3:IS_HOUSE]->(h:House)
WITH p, point({latitude: toFloat(h.latitude), longitude: toFloat(h.longitude)}) as point
RETURN {id: p.ProducerID, label: "H1", type: "House", point: point }

.