2. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
Luigi Dell’Aquila
Core Developer and Director of Consulting
OrientDB LTD
Twitter: @ldellaquila
http://www.orientdb.com
4. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
Summary
•What is OrientDB
•OrientDB GeoSpatial API
•Importing Geo data (Java and/or Node.js)
•Querying Geo data (OrientDB Studio)
•Displaying Geo data (Angular2, Google Maps)
•Adding Relationships - graph data
•Graph + Spatial queries
5. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
What is OrientDB
•Multi-Model Database (Document, Graph and more)
•Tables Classes
•Extended SQL
•JOIN Physical Pointers
•Schema, No-Schema, Hybrid
•HTTP + Binary protocols
•Stand-alone or Embedded
•Distributed Multi-Master
•Apache 2 license
6. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
Install
•http://www.orientdb.com/download/
•http://central.maven.org/maven2/com/
orientechnologies/orientdb-spatial/VERSION/
orientdb-spatial-VERSION-dist.jar
> cd orientdb-community/bin/
> ./server.sh
7. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
OrientDB GeoSpatial Classes
•OPoint
•OLine
•OPolygon
•OMultiPoint
•OMultiline
•OMultiPlygon
8. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
OrientDB GeoSpatial Functions
•ST_GeomFromText(text)
•ST_Equals(geom, geom)
•ST_Contains(geom, geom)
•ST_Disjoint(geom, geom)
•ST_Intersects(geom, geom)
•ST_Distance_Sphere(geom, geom)
•and more…
9. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
Our Data Model
CREATE CLASS POI EXTENDS V
CREATE PROPERTY POI.location EMBEDDED OPoint
CREATE INDEX POI.location on POI(location) SPATIAL ENGINE LUCENE
CREATE CLASS Natural EXTENDS V
CREATE PROPERTY Natural.location EMBEDDED OPolygon
CREATE INDEX Natural.location on Natural(location) SPATIAL ENGINE LUCENE
CREATE CLASS Person EXTENDS V
CREATE PROPERTY Person.location EMBEDDED OPoint
CREATE CLASS FriendOf EXTENDS E
10. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
Our Data Source (WKT)
WKT,osm_id,name,type
"POINT (14.4641804 50.0972109)",24569342,"Invalidovna, Metro B",station
"POINT (14.4739792 50.1036789)",24569358,"Palmovka, Metro B",station
"POINT (14.4921863 50.1062907)",24569412,"Českomoravská, Metro B",station
11. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
Now let’s import data!
Let’s do it in Java
you can download some Geo files from
http://www.mapcruzin.com/free-spain-maps.htm
and convert them to WKT using QGis (www.qgis.org)
12. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
Maven Dependencies
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>com.orientechnologies</groupId>
<artifactId>orientdb-graphdb</artifactId>
<version>2.2.13</version>
</dependency>
13. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
Read from CSV
Reader reader = new FileReader("/path/to/poi_file.csv");
CSVParser parser = CSVFormat.DEFAULT.parse(reader);
Iterator<CSVRecord> iterator = parser.iterator();
iterator.next(); //discard the header
while(iterator.hasNext()){ //read each row
importRecord(iterator.next());
}
14. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
OrientDB connection
Reader reader = new FileReader("/path/to/poi_file.csv");
CSVParser parser = CSVFormat.DEFAULT.parse(reader);
Iterator<CSVRecord> iterator = parser.iterator();
iterator.next(); //discard the header
OrientGraph graph =
new OrientGraph("remote:localhost/testdb", "admin", "admin");
while(iterator.hasNext()){ //read each row
importRecord(iterator.next(), graph);
}
graph.shutdown();
15. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
importRecord()
void importRecord(CSVRecord record, OrientGraph graph) {
String wkt = record.get(0);
String name = record.get(2);
String type = record.get(3);
graph.command(new OCommandSQL(
"insert into Natural " +
"set name = ?, type = ?, " +
"location = ST_GeomFromText(?)"))
.execute(name, type, wkt);
}
16. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
Querying geo data
We are here:
(40.399640, -3.8375544)
(lat, lon)
18. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
Clone the scaffolding
> git clone https://github.com/luigidellaquila/geospatial-demo
> cd geospatial-demo
> npm install
(it’s a clone of https://github.com/angular/quickstart)
> npm start
19. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
Clone the scaffolding
> git clone https://github.com/luigidellaquila/geospatial-demo
> cd geospatial-demo
> npm install
(it’s a clone of https://github.com/angular/quickstart)
> npm start
> cd <orientdb-home>/www
> ln -s <quickstart-path>
> tsc -w
20. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
We need Google Maps
<script src=“https://maps.googleapis.com/maps/api/js?key=API_KEY"
async defer></script>
21. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
Let’s display a map (app.html)
<div class=“container">
<div class="row">
<div class="col-md-12" id="map" style=“height:600px"></div>
</div>
</div>
22. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
Draw the map
drawMap(){
var controller = this;
let mapProp = {
center: new google.maps.LatLng(40.399640, -3.8375544),
zoom: 16,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
controller.map = new google.maps.Map(document.getElementById("map"), mapProp);
controller.map.addListener("click", function(point: any){
controller.zone.run(()=> {
controller.lat = point.latLng.lat();
controller.lon = point.latLng.lng();
});
});
}
23. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
Create a Person
createPerson(): void{
var location = {
// the location object
}
var queryString = ””; // OrientDB statement
this.orient.command(
queryString,
(result) => { /* Success callback */ },
(error) => { /* Error callback */ }
);
}
24. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
Create a Person
createPerson(): void{
var location = {
"@class": "OPoint",
coordinates: [this.lon, this.lat]
}
var queryString = ””; // OrientDB statement
this.orient.command(
queryString,
(result) => { /* Success callback */ },
(error) => { /* Error callback */ }
);}
25. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
Create a Person
createPerson(): void{
var location = {
"@class": "OPoint",
coordinates: [this.lon, this.lat]
}
var queryString = `insert into Person
set name = '${this.personName}',
location = ${JSON.stringify(location)}`;
this.orient.command(
queryString,
(result) => { /* Success callback */ },
(error) => { /* Error callback */ }
);
}
26. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
Create a Person
createPerson(): void{
var location = {
"@class": "OPoint",
coordinates: [this.lon, this.lat]
}
var queryString = `insert into Person
set name = '${this.personName}',
location = ${JSON.stringify(location)}`;
this.orient.command(
queryString,
(res) => {
let body = res.json();
let person = body.result[0];
this.addPersonToMap(person)
},
(e) => { console.log(e) });
}
27. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
Add Person Vertex to Orient via REST API
command(statement: string, success: (data: any) => void, error: (err: any) => void): void{
var url = this.url + "sql/-/-1"
var headers = new Headers();
headers.append("Authorization", "Basic " + btoa(this.username+":"+this.password));
this.http.post( // HTTP POST
url, // the URL
JSON.stringify({
"command": statement // the SQL command
}),
{headers: headers} // the authentication data
).toPromise()
.then(success)
.catch(error);
}
28. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
Add Person to the Map
addPersonToMap(personData:any){
let location = personData.location;
let coordinates = location.coordinates;
let controller = this;
let marker = new google.maps.Marker({
position: {lat:coordinates[1], lng:coordinates[0]},
map: this.map,
title: personData.name,
rid: personData["@rid"]
});
google.maps.event.addListener(marker, 'click', function() {
controller.onMarkerClick(marker);
});
}
29. Luigi Dell’Aquila @ldellaquila Madrid - Nov 18-19 2016
Add an edge between people
(FriendOf)
createEdge(from:any, to:any): void{
this.orient.command(
`create edge FriendOf from ${from.rid} to ${to.rid}`,
(x)=>{console.log(x)},
(x)=>{console.log(x)}
)
this.addEdgeBetweenMarkersToMap(from, to);
}