neography 1.3.6 → 1.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c0370d9441fe781940dd20f4a89eac1306299d8a
4
- data.tar.gz: 51f228c713783eac9783df52a61676ddead5435c
3
+ metadata.gz: c8915c7b2abbc72fbe16cb33d50b7e80d0c71b15
4
+ data.tar.gz: 2933f91d72dd64da8a60f9a2155068b9baacff32
5
5
  SHA512:
6
- metadata.gz: ac5122807662830386f371b96335e98b6d3b967bd871dbe8c4f5e53de41ece3638e251d05d891a9323f5551c80d4ae3e1857307c23573c56bf414416a3e4445e
7
- data.tar.gz: 6e8b5282ece9f8b52c30c5b599a7ea7ef1d08facb786d34b62be2078e836214f51e4782123d88295de50d71b49abc4f2011f30f45a86db42a8eda51b99ba514a
6
+ metadata.gz: 89c856460ee6365d4e24ebb270349b2fba5f8e4430afba1ba093ba3f85eed84bb524881e19a3f0e9e20792a57d2e5d930ec473b0234af1c3034cdafd136b133c
7
+ data.tar.gz: e7bcf2213babefd378c24c910163795c680a49a8bbb9cec62cb46064cb5f9506adbd16d7e58cee9ec412529f3ff74055527f998d3207793ab3877121c221dc11
@@ -1,4 +1,4 @@
1
- script: "bundle exec rake neo4j:install['enterprise','2.0.0'] neo4j:start spec --trace"
1
+ script: "bundle exec rake neo4j:install['enterprise','2.0.0'] neo4j:get_spatial neo4j:start spec --trace"
2
2
  language: ruby
3
3
  rvm:
4
4
  - 1.9.3
data/README.md CHANGED
@@ -138,12 +138,29 @@ node2 = @neo.create_node("age" => 33, "name" => "Roel")
138
138
  @neo.add_node_to_index("people", "name", "max", node1)
139
139
  @neo.get_node_index("people", "name", "max")
140
140
 
141
- # Cypher queries:
142
- @neo.execute_query("start n=node(0) return n")
143
-
144
141
  # Batches:
145
142
  @neo.batch [:create_node, {"name" => "Max"}],
146
143
  [:create_node, {"name" => "Marc"}]
144
+
145
+ # Cypher queries:
146
+ @neo.execute_query("start n=node(0) return n")
147
+
148
+ ```
149
+
150
+ You can also use the [cypher gem](https://github.com/andreasronge/neo4j-cypher) instead of writing cypher as text.
151
+
152
+
153
+ ```
154
+ node(1).outgoing(rel(:friends).where{|r| r[:since] == 1994})
155
+ ```
156
+
157
+ would become:
158
+
159
+ ```
160
+ START me=node(1)
161
+ MATCH (me)-[friend_rel:`friends`]->(friends)
162
+ WHERE (friend_rel.since = 1994)
163
+ RETURN friends
147
164
  ```
148
165
 
149
166
  This is just a small sample of the full API, see the [Wiki documentation](https://github.com/maxdemarzi/neography/wiki) for the full API.
@@ -28,6 +28,7 @@ require 'neography/rest/extensions'
28
28
  require 'neography/rest/batch'
29
29
  require 'neography/rest/clean'
30
30
  require 'neography/rest/transactions'
31
+ require 'neography/rest/spatial'
31
32
 
32
33
  require 'neography/errors'
33
34
 
@@ -69,6 +70,7 @@ module Neography
69
70
  @batch = Batch.new(@connection)
70
71
  @clean = Clean.new(@connection)
71
72
  @transactions = Transactions.new(@connection)
73
+ @spatial = Spatial.new(@connection)
72
74
  end
73
75
 
74
76
  # meta-data
@@ -452,7 +454,53 @@ module Neography
452
454
  def batch_not_streaming(*args)
453
455
  @batch.not_streaming(*args)
454
456
  end
457
+
458
+ # spatial
459
+
460
+ def get_spatial
461
+ @spatial.index
462
+ end
463
+
464
+ def add_point_layer(layer, lat = nil, lon = nil)
465
+ @spatial.add_point_layer(layer, lat, lon)
466
+ end
467
+
468
+ def add_editable_layer(layer, format, node_property_name)
469
+ @spatial.add_editable_layer(layer, format, node_property_name)
470
+ end
471
+
472
+ def get_layer(layer)
473
+ @spatial.get_layer(layer)
474
+ end
455
475
 
476
+ def add_geometry_to_layer(layer, geometry)
477
+ @spatial.add_geometry_to_layer(layer, geometry)
478
+ end
479
+
480
+ def edit_geometry_from_layer(layer, geometry, node)
481
+ @spatial.edit_geometry_from_layer(layer, geometry, node)
482
+ end
483
+
484
+ def add_node_to_layer(layer, node)
485
+ @spatial.add_node_to_layer(layer, node)
486
+ end
487
+
488
+ def find_geometries_in_bbox(layer, minx, maxx, miny, maxy)
489
+ @spatial.find_geometries_in_bbox(layer, minx, maxx, miny, maxy)
490
+ end
491
+
492
+ def find_geometries_within_distance(layer, pointx, pointy, distance)
493
+ @spatial.find_geometries_within_distance(layer, pointx, pointy, distance)
494
+ end
495
+
496
+ def create_spatial_index(name, type = nil, lat = nil, lon = nil)
497
+ @spatial.create_spatial_index(name, type, lat, lon)
498
+ end
499
+
500
+ def add_node_to_spatial_index(index, id)
501
+ @spatial.add_node_to_spatial_index(index, id)
502
+ end
503
+
456
504
  # clean database
457
505
 
458
506
  # For testing (use a separate neo4j instance)
@@ -0,0 +1,154 @@
1
+ module Neography
2
+ class Rest
3
+ class Spatial
4
+ extend Neography::Rest::Paths
5
+ include Neography::Rest::Helpers
6
+
7
+ add_path :index, "/ext/SpatialPlugin"
8
+ add_path :add_simple_point_layer, "/ext/SpatialPlugin/graphdb/addSimplePointLayer"
9
+ add_path :add_editable_layer, "/ext/SpatialPlugin/graphdb/addEditableLayer"
10
+ add_path :get_layer, "/ext/SpatialPlugin/graphdb/getLayer"
11
+ add_path :add_geometry_to_layer, "/ext/SpatialPlugin/graphdb/addGeometryWKTToLayer"
12
+ add_path :edit_geometry_from_layer, "/ext/SpatialPlugin/graphdb/updateGeometryFromWKT"
13
+ add_path :add_node_to_layer, "/ext/SpatialPlugin/graphdb/addNodeToLayer"
14
+ add_path :find_geometries_in_bbox, "/ext/SpatialPlugin/graphdb/findGeometriesInBBox"
15
+ add_path :find_geometries_within_distance,"/ext/SpatialPlugin/graphdb/findGeometriesWithinDistance"
16
+ add_path :create_index, "/index/node"
17
+ add_path :add_to_index, "/index/node/:index"
18
+
19
+ def initialize(connection)
20
+ @connection = connection
21
+ end
22
+
23
+ def index
24
+ @connection.get(index_path)
25
+ end
26
+
27
+ def add_point_layer(layer, lat, lon)
28
+ options = {
29
+ :body => {
30
+ :layer => layer,
31
+ :lat => lat || "lat",
32
+ :lon => lon || "lon"
33
+ }.to_json,
34
+ :headers => json_content_type.merge({'Accept' => 'application/json;charset=UTF-8'})
35
+ }
36
+
37
+ @connection.post(add_simple_point_layer_path, options)
38
+ end
39
+
40
+ def add_editable_layer(layer, format = "WKT", node_property_name = "wkt")
41
+ options = {
42
+ :body => {
43
+ :layer => layer,
44
+ :format => format,
45
+ :nodePropertyName => node_property_name
46
+ }.to_json,
47
+ :headers => json_content_type.merge({'Accept' => 'application/json;charset=UTF-8'})
48
+ }
49
+
50
+ @connection.post(add_editable_layer_path, options)
51
+ end
52
+
53
+ def get_layer(layer)
54
+ options = {
55
+ :body => {
56
+ :layer => layer
57
+ }.to_json,
58
+ :headers => json_content_type.merge({'Accept' => 'application/json;charset=UTF-8'})
59
+ }
60
+ @connection.post(get_layer_path, options)
61
+ end
62
+
63
+ def add_geometry_to_layer(layer, geometry)
64
+ options = {
65
+ :body => {
66
+ :layer => layer,
67
+ :geometry => geometry
68
+ }.to_json,
69
+ :headers => json_content_type.merge({'Accept' => 'application/json;charset=UTF-8'})
70
+ }
71
+ @connection.post(add_geometry_to_layer_path, options)
72
+ end
73
+
74
+ def edit_geometry_from_layer(layer, geometry, node)
75
+ options = {
76
+ :body => {
77
+ :layer => layer,
78
+ :geometry => geometry,
79
+ :geometryNodeId => get_id(node)
80
+ }.to_json,
81
+ :headers => json_content_type.merge({'Accept' => 'application/json;charset=UTF-8'})
82
+ }
83
+ @connection.post(edit_geometry_from_layer_path, options)
84
+ end
85
+
86
+ def add_node_to_layer(layer, node)
87
+ options = {
88
+ :body => {
89
+ :layer => layer,
90
+ :node => get_id(node)
91
+ }.to_json,
92
+ :headers => json_content_type.merge({'Accept' => 'application/json;charset=UTF-8'})
93
+ }
94
+ @connection.post(add_node_to_layer_path, options)
95
+ end
96
+
97
+ def find_geometries_in_bbox(layer, minx, maxx, miny, maxy)
98
+ options = {
99
+ :body => {
100
+ :layer => layer,
101
+ :minx => minx,
102
+ :maxx => maxx,
103
+ :miny => miny,
104
+ :maxy => maxy
105
+ }.to_json,
106
+ :headers => json_content_type.merge({'Accept' => 'application/json;charset=UTF-8'})
107
+ }
108
+ @connection.post(find_geometries_in_bbox_path, options)
109
+ end
110
+
111
+ def find_geometries_within_distance(layer, pointx, pointy, distance)
112
+ options = {
113
+ :body => {
114
+ :layer => layer,
115
+ :pointX => pointx,
116
+ :pointY => pointy,
117
+ :distanceInKm => distance
118
+ }.to_json,
119
+ :headers => json_content_type.merge({'Accept' => 'application/json;charset=UTF-8'})
120
+ }
121
+ @connection.post(find_geometries_within_distance_path, options)
122
+ end
123
+
124
+ def create_spatial_index(name, type, lat, lon)
125
+ options = {
126
+ :body => {
127
+ :name => name,
128
+ :config => {
129
+ :provider => "spatial",
130
+ :geometry_type => type || "point",
131
+ :lat => lat || "lat",
132
+ :lon => lon || "lon"
133
+ }
134
+ }.to_json,
135
+ :headers => json_content_type.merge({'Accept' => 'application/json;charset=UTF-8'})
136
+ }
137
+ @connection.post(create_index_path, options)
138
+ end
139
+
140
+ def add_node_to_spatial_index(index, id)
141
+ options = {
142
+ :body => {
143
+ :uri => @connection.configuration + "/node/#{get_id(id)}",
144
+ :key => "k",
145
+ :value => "v"
146
+ }.to_json,
147
+ :headers => json_content_type.merge({'Accept' => 'application/json;charset=UTF-8'})
148
+ }
149
+ @connection.post(add_to_index_path(:index => index), options)
150
+ end
151
+
152
+ end
153
+ end
154
+ end
@@ -155,4 +155,51 @@ namespace :neo4j do
155
155
  end
156
156
  end
157
157
 
158
+ task :get_spatial, :version do |t, args|
159
+ args.with_defaults(:version => "2.0.0")
160
+ puts "Installing Neo4j-Spatial #{args[:version]}"
161
+
162
+ unless File.exist?('neo4j-spatial.zip')
163
+ df = File.open('neo4j-spatial.zip', 'wb')
164
+ case args[:version]
165
+ when "2.0.0"
166
+ dist = "dist.neo4j.org"
167
+ request = "/spatial/neo4j-spatial-0.12-neo4j-2.0.0-server-plugin.zip"
168
+ when "1.9"
169
+ dist = "dist.neo4j.org.s3.amazonaws.com"
170
+ request = "/spatial/neo4j-spatial-0.11-neo4j-1.9-server-plugin.zip"
171
+ when "1.8.2"
172
+ dist = "dist.neo4j.org.s3.amazonaws.com"
173
+ request = "/spatial/neo4j-spatial-0.9.1-neo4j-1.8.2-server-plugin.zip"
174
+ else
175
+ abort("I don't know that version of the neo4j spatial plugin")
176
+ end
177
+
178
+ begin
179
+ Net::HTTP.start(dist) do |http|
180
+ http.request_get(request) do |resp|
181
+ resp.read_body do |segment|
182
+ df.write(segment)
183
+ end
184
+ end
185
+ end
186
+ ensure
187
+ df.close()
188
+ end
189
+ end
190
+
191
+ # Extract to neo4j plugins directory
192
+ Zip::File.open('neo4j-spatial.zip') do |zip_file|
193
+ zip_file.each do |f|
194
+ f_path=File.join("neo4j/plugins/", f.name)
195
+ FileUtils.mkdir_p(File.dirname(f_path))
196
+ begin
197
+ zip_file.extract(f, f_path) unless File.exist?(f_path)
198
+ rescue
199
+ puts f.name + " failed to extract."
200
+ end
201
+ end
202
+ end
203
+
204
+ end
158
205
  end
@@ -1,3 +1,3 @@
1
1
  module Neography
2
- VERSION = "1.3.6"
2
+ VERSION = "1.3.7"
3
3
  end
@@ -0,0 +1,166 @@
1
+ require 'spec_helper'
2
+
3
+ describe Neography::Rest do
4
+ before(:each) do
5
+ @neo = Neography::Rest.new
6
+ end
7
+
8
+ describe "find the spatial plugin" do
9
+ it "can get a description of the spatial plugin" do
10
+ si = @neo.get_spatial
11
+ si.should_not be_nil
12
+ si["graphdb"]["addEditableLayer"].should_not be_nil
13
+ end
14
+ end
15
+
16
+ describe "add a point layer" do
17
+ it "can add a simple point layer" do
18
+ pl = @neo.add_point_layer("restaurants")
19
+ pl.should_not be_nil
20
+ pl.first["data"]["layer"].should == "restaurants"
21
+ pl.first["data"]["geomencoder_config"].should == "lon:lat"
22
+ end
23
+
24
+ it "can add a simple point layer with lat and long" do
25
+ pl = @neo.add_point_layer("coffee_shops", "latitude", "longitude")
26
+ pl.should_not be_nil
27
+ pl.first["data"]["layer"].should == "coffee_shops"
28
+ pl.first["data"]["geomencoder_config"].should == "longitude:latitude"
29
+ end
30
+ end
31
+
32
+ describe "add an editable layer" do
33
+ it "can add an editable layer" do
34
+ el = @neo.add_editable_layer("zipcodes", "WKT", "wkt")
35
+ el.should_not be_nil
36
+ el.first["data"]["layer"].should == "zipcodes"
37
+ el.first["data"]["geomencoder_config"].should == "wkt"
38
+ end
39
+ end
40
+
41
+ describe "get a spatial layer" do
42
+ it "can get a layer" do
43
+ sl = @neo.get_layer("restaurants")
44
+ sl.should_not be_nil
45
+ sl.first["data"]["layer"].should == "restaurants"
46
+ end
47
+ end
48
+
49
+ describe "create a spatial index" do
50
+ it "can create a spatial index" do
51
+ index = @neo.create_spatial_index("restaurants")
52
+ index["provider"].should == "spatial"
53
+ index["geometry_type"].should == "point"
54
+ index["lat"].should == "lat"
55
+ index["lon"].should == "lon"
56
+ end
57
+ end
58
+
59
+ describe "add geometry to spatial layer" do
60
+ it "can add a geometry" do
61
+ geometry = "LINESTRING (15.2 60.1, 15.3 60.1)"
62
+ geo = @neo.add_geometry_to_layer("zipcodes", geometry)
63
+ geo.should_not be_nil
64
+ geo.first["data"]["wkt"].should == geometry
65
+ end
66
+ end
67
+
68
+ describe "update geometry from spatial layer" do
69
+ it "can update a geometry" do
70
+ geometry = "LINESTRING (15.2 60.1, 15.3 60.1)"
71
+ geo = @neo.add_geometry_to_layer("zipcodes", geometry)
72
+ geo.should_not be_nil
73
+ geo.first["data"]["wkt"].should == geometry
74
+ geometry = "LINESTRING (14.7 60.1, 15.3 60.1)"
75
+ existing_geo = @neo.edit_geometry_from_layer("zipcodes", geometry, geo)
76
+ existing_geo.first["data"]["wkt"].should == geometry
77
+ existing_geo.first["self"].split('/').last.to_i.should == geo.first["self"].split('/').last.to_i
78
+ end
79
+ end
80
+
81
+ describe "add a node to a layer" do
82
+ it "can add a node to a simple point layer" do
83
+ properties = {:name => "Max's Restaurant", :lat => 41.8819, :lon => 87.6278}
84
+ node = @neo.create_node(properties)
85
+ node.should_not be_nil
86
+ added = @neo.add_node_to_layer("restaurants", node)
87
+ added.first["data"]["lat"].should == properties[:lat]
88
+ added.first["data"]["lon"].should == properties[:lon]
89
+
90
+ added = @neo.add_node_to_index("restaurants", "dummy", "dummy", node)
91
+ added["data"]["lat"].should == properties[:lat]
92
+ added["data"]["lon"].should == properties[:lon]
93
+ end
94
+ end
95
+
96
+ describe "find geometries in a bounding box" do
97
+ it "can find a geometry in a bounding box" do
98
+ properties = {:name => "Max's Restaurant", :lat => 41.8819, :lon => 87.6278}
99
+ node = @neo.find_geometries_in_bbox("restaurants", 87.5, 87.7, 41.7, 41.9)
100
+ node.should_not be_empty
101
+ node.first["data"]["lat"].should == properties[:lat]
102
+ node.first["data"]["lon"].should == properties[:lon]
103
+ node.first["data"]["name"].should == "Max's Restaurant"
104
+ end
105
+
106
+ it "can find a geometry in a bounding box using cypher" do
107
+ properties = {:lat => 60.1, :lon => 15.2}
108
+ @neo.create_spatial_index("geombbcypher", "point", "lat", "lon")
109
+ node = @neo.create_node(properties)
110
+ added = @neo.add_node_to_index("geombbcypher", "dummy", "dummy", node)
111
+ existing_node = @neo.execute_query("start node = node:geombbcypher('bbox:[15.0,15.3,60.0,60.2]') return node")
112
+ existing_node.should_not be_empty
113
+ existing_node["data"][0][0]["data"]["lat"].should == properties[:lat]
114
+ existing_node["data"][0][0]["data"]["lon"].should == properties[:lon]
115
+ end
116
+
117
+ it "can find a geometry in a bounding box using cypher two" do
118
+ properties = {:lat => 60.1, :lon => 15.2}
119
+ @neo.create_spatial_index("geombbcypher2", "point", "lat", "lon")
120
+ node = @neo.create_node(properties)
121
+ added = @neo.add_node_to_spatial_index("geombbcypher2", node)
122
+ existing_node = @neo.execute_query("start node = node:geombbcypher2('bbox:[15.0,15.3,60.0,60.2]') return node")
123
+ existing_node.should_not be_empty
124
+ existing_node["data"][0][0]["data"]["lat"].should == properties[:lat]
125
+ existing_node["data"][0][0]["data"]["lon"].should == properties[:lon]
126
+ end
127
+
128
+ end
129
+
130
+ describe "find geometries within distance" do
131
+ it "can find a geometry within distance" do
132
+ properties = {:name => "Max's Restaurant", :lat => 41.8819, :lon => 87.6278}
133
+ node = @neo.find_geometries_within_distance("restaurants", 87.627, 41.881, 10)
134
+ node.should_not be_empty
135
+ node.first["data"]["lat"].should == properties[:lat]
136
+ node.first["data"]["lon"].should == properties[:lon]
137
+ node.first["data"]["name"].should == "Max's Restaurant"
138
+ end
139
+
140
+ it "can find a geometry within distance using cypher" do
141
+ properties = {:lat => 60.1, :lon => 15.2}
142
+ @neo.create_spatial_index("geowdcypher", "point", "lat", "lon")
143
+ node = @neo.create_node(properties)
144
+ added = @neo.add_node_to_index("geowdcypher", "dummy", "dummy", node)
145
+ existing_node = @neo.execute_query("start n = node:geowdcypher({bbox}) return n", {:bbox => "withinDistance:[60.0,15.0,100.0]"})
146
+ existing_node.should_not be_empty
147
+ existing_node.should_not be_empty
148
+ existing_node["data"][0][0]["data"]["lat"].should == properties[:lat]
149
+ existing_node["data"][0][0]["data"]["lon"].should == properties[:lon]
150
+ end
151
+
152
+ it "can find a geometry within distance using cypher 2" do
153
+ properties = {:lat => 60.1, :lon => 15.2}
154
+ @neo.create_spatial_index("geowdcypher2", "point", "lat", "lon")
155
+ node = @neo.create_node(properties)
156
+ added = @neo.add_node_to_spatial_index("geowdcypher2", node)
157
+ existing_node = @neo.execute_query("start n = node:geowdcypher2({bbox}) return n", {:bbox => "withinDistance:[60.0,15.0,100.0]"})
158
+ existing_node.should_not be_empty
159
+ existing_node.should_not be_empty
160
+ existing_node["data"][0][0]["data"]["lat"].should == properties[:lat]
161
+ existing_node["data"][0][0]["data"]["lon"].should == properties[:lon]
162
+ end
163
+
164
+ end
165
+
166
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: neography
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.6
4
+ version: 1.3.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Max De Marzi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-23 00:00:00.000000000 Z
11
+ date: 2014-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -202,6 +202,7 @@ files:
202
202
  - lib/neography/rest/relationship_types.rb
203
203
  - lib/neography/rest/relationships.rb
204
204
  - lib/neography/rest/schema_indexes.rb
205
+ - lib/neography/rest/spatial.rb
205
206
  - lib/neography/rest/transactions.rb
206
207
  - lib/neography/tasks.rb
207
208
  - lib/neography/version.rb
@@ -231,6 +232,7 @@ files:
231
232
  - spec/integration/rest_relationship_spec.rb
232
233
  - spec/integration/rest_relationship_types_spec.rb
233
234
  - spec/integration/rest_schema_index_spec.rb
235
+ - spec/integration/rest_spatial_spec.rb
234
236
  - spec/integration/rest_transaction_spec.rb
235
237
  - spec/integration/rest_traverse_spec.rb
236
238
  - spec/matchers.rb
@@ -312,6 +314,7 @@ test_files:
312
314
  - spec/integration/rest_relationship_spec.rb
313
315
  - spec/integration/rest_relationship_types_spec.rb
314
316
  - spec/integration/rest_schema_index_spec.rb
317
+ - spec/integration/rest_spatial_spec.rb
315
318
  - spec/integration/rest_transaction_spec.rb
316
319
  - spec/integration/rest_traverse_spec.rb
317
320
  - spec/matchers.rb