We are in process of trying out Neo4j to see how it fits our product.
As newbie to Neo4j, one thing has caused some questions which is why I would like to ask help from smarter people!
The use case is following: node (vehicle, event) can have a location that is in MGRS format. So for example, a Land Rover Defender has location of 35V LF 72593 90864 (1m precision). You can read about the format here - Military Grid Reference System - Wikipedia
Now, how do we present this with graph model?
The simple answer would be to add property for node. However, we have a use case where we have to find all other vehicles within 100m from Land Rover.
If we could use time-tree like graph, then the graph would look like this:
CREATE (root:LocationRoot),
(gzd:GridZoneDesignator{designator: '4Q'}), // Grid zone designator
(msq:MeterSquareIdentifier{identifier: 'FJ'}), // 100,000 meter square identifier
(precisionLevelOne:PrecisionLevelOne{easting: 1, northing: 6}), // Precision level 10 km
(precisionLevelTwo:PrecisionLevelTwo{easting: 2, northing: 7}), // Precision level 1 km
(precisionLevelThree:PrecisionLevelThree{easting: 3, northing: 8}), // Precision level 100 m
(precisionLevelFour:PrecisionLevelFour{easting: 4, northing: 9}), // Precision level 10 m
(precisionLevelFive:PrecisionLevelFive{easting: 5, northing: 0}), // Precision level 1 m
// Relationships
(root)-[:FIRST]->(gzd),
(root)-[:LAST]->(gzd),
(root)-[:CHILD]->(gzd),
(gzd)-[:FIRST]->(msq),
(gzd)-[:LAST]->(msq),
(gzd)-[:CHILD]->(msq),
(msq)-[:FIRST]->(precisionLevelOne),
(msq)-[:LAST]->(precisionLevelOne),
(msq)-[:CHILD]->(precisionLevelOne),
(precisionLevelOne)-[:FIRST]->(precisionLevelTwo),
(precisionLevelOne)-[:LAST]->(precisionLevelTwo),
(precisionLevelOne)-[:CHILD]->(precisionLevelTwo),
(precisionLevelTwo)-[:FIRST]->(precisionLevelThree),
(precisionLevelTwo)-[:LAST]->(precisionLevelThree),
(precisionLevelTwo)-[:CHILD]->(precisionLevelThree),
(precisionLevelThree)-[:FIRST]->(precisionLevelFour),
(precisionLevelThree)-[:LAST]->(precisionLevelFour),
(precisionLevelThree)-[:CHILD]->(precisionLevelFour),
(precisionLevelFour)-[:FIRST]->(precisionLevelFive),
(precisionLevelFour)-[:LAST]->(precisionLevelFive),
(precisionLevelFour)-[:CHILD]->(precisionLevelFive);
Or if the create nodes for both easting and northing:
CREATE (root:LocationRoot),
(gzd:GridZoneDesignator{designator: '35V'}), // Grid zone designator
(msq:MeterSquareIdentifier{identifier: 'LF'}), // 100,000 meter square identifier
(eastingPrecisionLevelOne:EastingPrecisionLevelOne{easting: 7}), // Precision level 10 km
(northingPrecisionLevelOne:NorthingPrecisionLevelOne{northing: 9}),
(eastingPrecisionLevelTwo:EastingPrecisionLevelTwo{easting: 2}), // Precision level 1 km
(northingPrecisionLevelTwo:NorthingPrecisionLevelTwo{northing: 0}),
(eastingPrecisionLevelThree:EastingPrecisionLevelThree{easting: 5}), // Precision level 100 m
(northingPrecisionLevelThree:NorthingPrecisionLevelThree{northing: 8}),
(eastingPrecisionLevelFour:EastingPrecisionLevelFour{easting: 9}), // Precision level 10 m
(northingPrecisionLevelFour:NorthingPrecisionLevelFour{northing: 6}),
(eastingPrecisionLevelFive:EastingPrecisionLevelFive{easting: 3}), // Precision level 1 m
(northingPrecisionLevelFive:NorthingPrecisionLevelFive{northing: 4}),
// Relationships
(root)-[:FIRST]->(gzd),
(root)-[:LAST]->(gzd),
(root)-[:CHILD]->(gzd),
(gzd)-[:FIRST]->(msq),
(gzd)-[:LAST]->(msq),
(gzd)-[:CHILD]->(msq),
(msq)-[:FIRST]->(eastingPrecisionLevelOne),
(msq)-[:FIRST]->(northingPrecisionLevelOne),
(msq)-[:LAST]->(eastingPrecisionLevelOne),
(msq)-[:LAST]->(northingPrecisionLevelOne),
(msq)-[:CHILD]->(eastingPrecisionLevelOne),
(msq)-[:CHILD]->(northingPrecisionLevelOne),
(eastingPrecisionLevelOne)-[:FIRST]->(eastingPrecisionLevelTwo),
(northingPrecisionLevelOne)-[:FIRST]->(northingPrecisionLevelTwo),
(eastingPrecisionLevelOne)-[:LAST]->(eastingPrecisionLevelTwo),
(northingPrecisionLevelOne)-[:LAST]->(northingPrecisionLevelTwo),
(eastingPrecisionLevelOne)-[:CHILD]->(eastingPrecisionLevelTwo),
(northingPrecisionLevelOne)-[:CHILD]->(northingPrecisionLevelTwo),
(eastingPrecisionLevelTwo)-[:FIRST]->(eastingPrecisionLevelThree),
(northingPrecisionLevelTwo)-[:FIRST]->(northingPrecisionLevelThree),
(eastingPrecisionLevelTwo)-[:LAST]->(eastingPrecisionLevelThree),
(northingPrecisionLevelTwo)-[:LAST]->(northingPrecisionLevelThree),
(eastingPrecisionLevelTwo)-[:CHILD]->(eastingPrecisionLevelThree),
(northingPrecisionLevelTwo)-[:CHILD]->(northingPrecisionLevelThree),
(eastingPrecisionLevelThree)-[:FIRST]->(eastingPrecisionLevelFour),
(northingPrecisionLevelThree)-[:FIRST]->(northingPrecisionLevelFour),
(eastingPrecisionLevelThree)-[:LAST]->(eastingPrecisionLevelFour),
(northingPrecisionLevelThree)-[:LAST]->(northingPrecisionLevelFour),
(eastingPrecisionLevelThree)-[:CHILD]->(eastingPrecisionLevelFour),
(northingPrecisionLevelThree)-[:CHILD]->(northingPrecisionLevelFour),
(eastingPrecisionLevelFour)-[:FIRST]->(eastingPrecisionLevelFive),
(northingPrecisionLevelFour)-[:FIRST]->(northingPrecisionLevelFive),
(eastingPrecisionLevelFour)-[:LAST]->(eastingPrecisionLevelFive),
(northingPrecisionLevelFour)-[:LAST]->(northingPrecisionLevelFive),
(eastingPrecisionLevelFour)-[:CHILD]->(eastingPrecisionLevelFive),
(northingPrecisionLevelFour)-[:CHILD]->(northingPrecisionLevelFive);
Then finding vehicles 100m from somewhere would be a matter of traversing the graph.
However, is there simpler solution to this as I feel I am over-engineering simple things...
One idea would be to use Point type, but how accurate is the distance calculation? Can it find with 1m precision?
We have also a use case where a user draws a box on the map and we have to find all vehicles in that area. Are there methods for doing this when using Point?
Hope somebody can share some knowledge on these matters.