neo4jrb_spatial 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/Gemfile +2 -0
- data/README.md +16 -10
- data/lib/neo4j/active_node/spatial.rb +34 -30
- data/lib/neo4j/spatial.rb +122 -108
- data/lib/neo4jrb_spatial.rb +1 -0
- data/lib/neo4jrb_spatial/errors.rb +7 -0
- data/lib/neo4jrb_spatial/version.rb +1 -1
- data/neo4jrb_spatial.gemspec +2 -2
- metadata +16 -5
- data/bin/console +0 -14
- data/bin/setup +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fb742b0cbfe6febf9d05b442ee46e0b887827370
|
4
|
+
data.tar.gz: e8f00d7f1d1bb32eef67be847d5e15a98a1117e7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 48c8cee0ef882d1e12b880bd5488b3457049ac7af25373bcf936dc0d3cbf1be29ae72388b35a1c31686485f62c3cad27d77f42f24c5c7b751af25ce83a922d1a
|
7
|
+
data.tar.gz: f3490009b572971ea316ad313de889b6589a2299b0b4d8a7c5557bba66784fbf672454f5a8933719e92a322f86b7b77b7717b1eb3de2be22fd3aeaaf7064363d
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,14 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
5
5
|
|
6
6
|
## [Unreleased][unreleased]
|
7
7
|
|
8
|
+
## [1.2.0] - 2016-09-26
|
9
|
+
|
10
|
+
### Fixed
|
11
|
+
|
12
|
+
- Compatibility with `neo4j-core ~> 6.1.4` (see #13)
|
13
|
+
- Some module nesting issues (see #10)
|
14
|
+
- Travis setup (see #13)
|
15
|
+
|
8
16
|
## [1.1.0] - 2015-10-15
|
9
17
|
|
10
18
|
### Fixed
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -2,6 +2,12 @@
|
|
2
2
|
|
3
3
|
Provides support for Neo4j Spatial to Neo4j.rb 5+.
|
4
4
|
|
5
|
+
## Code Status
|
6
|
+
|
7
|
+
[![Build Status](https://secure.travis-ci.org/neo4jrb/neo4jrb_spatial.png?branch=master)](http://travis-ci.org/neo4jrb/neo4jrb_spatial)
|
8
|
+
|
9
|
+
## Introduction
|
10
|
+
|
5
11
|
It is more or less a Neo4j.rb-flavored implementation of [Max De Marzi](https://github.com/maxdemarzi)'s
|
6
12
|
[code](https://github.com/maxdemarzi/neography/blob/46be2bb3c66aea14e707b1e6f82937e65f686ccc/lib/neography/rest/spatial.rb) from
|
7
13
|
[Neography](https://github.com/maxdemarzi/neography).
|
@@ -66,28 +72,28 @@ Neo4j::Session.current.query.start('n = node:restaurants({location})').params(lo
|
|
66
72
|
## Use it with the Neo4j gem
|
67
73
|
|
68
74
|
Neo4j.rb does not support legacy indexes, so adding nodes to spatial indexes needs to happen separately from node creation. This is complicated by the fact that Neo4j.rb creates all nodes in transactions, so `after_create` callbacks won't work; instead, add your node to the index once you've confirmed it has been created.
|
69
|
-
|
75
|
+
|
70
76
|
Start by adding `lat` and `lon` properties to your model. You can also add a `spatial_index` to save yourself some time later.
|
71
|
-
|
77
|
+
|
72
78
|
```
|
73
79
|
class Restaurant
|
74
80
|
include Neo4j::ActiveNode
|
75
81
|
include Neo4j::ActiveNode::Spatial
|
76
|
-
|
82
|
+
|
77
83
|
# This is optional but might make things easier for you later
|
78
84
|
spatial_index 'restaurants'
|
79
|
-
|
85
|
+
|
80
86
|
property :name
|
81
87
|
property :lat
|
82
88
|
property :lon
|
83
89
|
end
|
84
|
-
|
90
|
+
|
85
91
|
# Create it
|
86
92
|
pizza_hut = Restaurant.create(name: 'Pizza Hut', lat: 60.1, lon: 15.1)
|
87
|
-
|
93
|
+
|
88
94
|
# When called without an argument, it will use the value set through `spatial_index` in the model
|
89
95
|
pizza_hut.add_to_spatial_index
|
90
|
-
|
96
|
+
|
91
97
|
# Alternatively, to add it to a different index, just give it that name
|
92
98
|
pizza_hut.add_to_spatial_index('fake_pizza_places')
|
93
99
|
```
|
@@ -112,12 +118,12 @@ Restaurant.all.spatial_match(:r, params_string)
|
|
112
118
|
```
|
113
119
|
|
114
120
|
It then drops you back into a QueryProxy in the context of the class. If you had an `employees` association defined in your model:
|
115
|
-
|
121
|
+
|
116
122
|
```
|
117
123
|
# Find all restaurants within the specified distance, then find their employees who are age 30
|
118
124
|
Restauarant.all.spatial_match(:r, 'withinDistance:[41.99,-87.67,10.0]').employees.where(age: 30)
|
119
125
|
```
|
120
|
-
|
126
|
+
|
121
127
|
If you did no define `spatial_index` on your model or what to query against something other than the model's default, you can feed a third argument: the index to use for the query.
|
122
128
|
|
123
129
|
## Additional Resources
|
@@ -129,4 +135,4 @@ mostly works for an idea of the basics, just replace Neography-specific commands
|
|
129
135
|
|
130
136
|
## Contributions
|
131
137
|
|
132
|
-
Pull requests and maintanence help would be swell. In addition to being fully tested, please ensure rubocop passes by running `rubocop` from the CLI.
|
138
|
+
Pull requests and maintanence help would be swell. In addition to being fully tested, please ensure rubocop passes by running `rubocop` from the CLI.
|
@@ -1,39 +1,43 @@
|
|
1
|
-
module Neo4j
|
2
|
-
module
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
def add_to_spatial_index(index_name = nil)
|
8
|
-
index = index_name || self.class.spatial_index_name
|
9
|
-
fail 'index name not found' unless index
|
10
|
-
Neo4j::Session.current.add_node_to_spatial_index(index, self)
|
11
|
-
end
|
1
|
+
module Neo4j
|
2
|
+
module ActiveNode
|
3
|
+
module Spatial
|
4
|
+
def self.included(other)
|
5
|
+
other.extend(ClassMethods)
|
6
|
+
end
|
12
7
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
# create_index_callback(index_name)
|
18
|
-
@spatial_index_name = index_name
|
8
|
+
def add_to_spatial_index(index_name = nil)
|
9
|
+
index = index_name || self.class.spatial_index_name
|
10
|
+
fail 'index name not found' unless index
|
11
|
+
Neo4j::Session.current.add_node_to_spatial_index(index, self)
|
19
12
|
end
|
20
13
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
14
|
+
module ClassMethods
|
15
|
+
attr_reader :spatial_index_name
|
16
|
+
def spatial_index(index_name = nil)
|
17
|
+
return spatial_index_name unless index_name
|
18
|
+
# create_index_callback(index_name)
|
19
|
+
@spatial_index_name = index_name
|
20
|
+
end
|
21
|
+
|
22
|
+
# This will not work for now. Neo4j Spatial's REST API doesn't seem to work within transactions.
|
23
|
+
# def create_index_callback(index_name)
|
24
|
+
# after_create(proc { |node| Neo4j::Session.current.add_node_to_spatial_index(index_name, node) })
|
25
|
+
# end
|
25
26
|
|
26
|
-
|
27
|
+
# private :create_index_callback
|
28
|
+
end
|
27
29
|
end
|
28
30
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
.
|
35
|
-
|
36
|
-
|
31
|
+
module Query
|
32
|
+
class QueryProxy
|
33
|
+
def spatial_match(var, params_string, spatial_index = nil)
|
34
|
+
index = model.spatial_index_name || spatial_index
|
35
|
+
fail 'Cannot query without index. Set index in model or as third argument.' unless index
|
36
|
+
Neo4j::Session.current.query
|
37
|
+
.start("#{var} = node:#{index}({spatial_params})")
|
38
|
+
.proxy_as(model, var)
|
39
|
+
.params(spatial_params: params_string)
|
40
|
+
end
|
37
41
|
end
|
38
42
|
end
|
39
43
|
end
|
data/lib/neo4j/spatial.rb
CHANGED
@@ -1,130 +1,144 @@
|
|
1
|
-
module Neo4j
|
2
|
-
module
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
module Neo4j
|
2
|
+
module Server
|
3
|
+
module Spatial
|
4
|
+
def spatial?
|
5
|
+
Neo4j::Session.current.connection.get('/db/data/ext/SpatialPlugin').status == 200
|
6
|
+
end
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
def spatial_plugin
|
9
|
+
parse_response! Neo4j::Session.current.connection.get('/db/data/ext/SpatialPlugin').body
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
def add_point_layer(layer, lat = nil, lon = nil)
|
13
|
+
options = {
|
14
|
+
layer: layer,
|
15
|
+
lat: lat || 'lat',
|
16
|
+
lon: lon || 'lon'
|
17
|
+
}
|
17
18
|
|
18
|
-
|
19
|
-
|
19
|
+
spatial_post('/ext/SpatialPlugin/graphdb/addSimplePointLayer', options)
|
20
|
+
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
def add_editable_layer(layer, format = 'WKT', node_property_name = 'wkt')
|
23
|
+
options = {
|
24
|
+
layer: layer,
|
25
|
+
format: format,
|
26
|
+
nodePropertyName: node_property_name
|
27
|
+
}
|
27
28
|
|
28
|
-
|
29
|
-
|
29
|
+
spatial_post('/ext/SpatialPlugin/graphdb/addEditableLayer', options)
|
30
|
+
end
|
30
31
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
32
|
+
def get_layer(layer)
|
33
|
+
options = {
|
34
|
+
layer: layer
|
35
|
+
}
|
36
|
+
spatial_post('/ext/SpatialPlugin/graphdb/getLayer', options)
|
37
|
+
end
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
39
|
+
def add_geometry_to_layer(layer, geometry)
|
40
|
+
options = {
|
41
|
+
layer: layer,
|
42
|
+
geometry: geometry
|
43
|
+
}
|
44
|
+
spatial_post('/ext/SpatialPlugin/graphdb/addGeometryWKTToLayer', options)
|
45
|
+
end
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
47
|
+
def edit_geometry_from_layer(layer, geometry, node)
|
48
|
+
options = {
|
49
|
+
layer: layer,
|
50
|
+
geometry: geometry,
|
51
|
+
geometryNodeId: get_id(node)
|
52
|
+
}
|
53
|
+
spatial_post('/ext/SpatialPlugin/graphdb/updateGeometryFromWKT', options)
|
54
|
+
end
|
54
55
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
56
|
+
def add_node_to_layer(layer, node)
|
57
|
+
options = {
|
58
|
+
layer: layer,
|
59
|
+
node: "#{resource_url}node/#{node.neo_id}"
|
60
|
+
}
|
61
|
+
spatial_post('/ext/SpatialPlugin/graphdb/addNodeToLayer', options)
|
62
|
+
end
|
62
63
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
64
|
+
def find_geometries_in_bbox(layer, minx, maxx, miny, maxy)
|
65
|
+
options = {
|
66
|
+
layer: layer,
|
67
|
+
minx: minx,
|
68
|
+
maxx: maxx,
|
69
|
+
miny: miny,
|
70
|
+
maxy: maxy
|
71
|
+
}
|
72
|
+
spatial_post('/ext/SpatialPlugin/graphdb/findGeometriesInBBox', options)
|
73
|
+
end
|
73
74
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
75
|
+
def find_geometries_within_distance(layer, pointx, pointy, distance)
|
76
|
+
options = {
|
77
|
+
layer: layer,
|
78
|
+
pointX: pointx,
|
79
|
+
pointY: pointy,
|
80
|
+
distanceInKm: distance
|
81
|
+
}
|
82
|
+
spatial_post('/ext/SpatialPlugin/graphdb/findGeometriesWithinDistance', options)
|
83
|
+
end
|
83
84
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
85
|
+
def create_spatial_index(name, type = nil, lat = nil, lon = nil)
|
86
|
+
options = {
|
87
|
+
name: name,
|
88
|
+
config: {
|
89
|
+
provider: 'spatial',
|
90
|
+
geometry_type: type || 'point',
|
91
|
+
lat: lat || 'lat',
|
92
|
+
lon: lon || 'lon'
|
93
|
+
}
|
92
94
|
}
|
93
|
-
|
94
|
-
|
95
|
-
end
|
95
|
+
spatial_post('/index/node', options)
|
96
|
+
end
|
96
97
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
98
|
+
def add_node_to_spatial_index(index, node)
|
99
|
+
options = {
|
100
|
+
uri: "/#{get_id(node)}",
|
101
|
+
key: 'k',
|
102
|
+
value: 'v'
|
103
|
+
}
|
104
|
+
spatial_post("/index/node/#{index}", options)
|
105
|
+
end
|
105
106
|
|
106
|
-
|
107
|
+
private
|
107
108
|
|
108
|
-
|
109
|
-
|
110
|
-
|
109
|
+
def spatial_post(path, options)
|
110
|
+
parse_response! Neo4j::Session.current.connection.post("/db/data/#{path}", options).body
|
111
|
+
end
|
111
112
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
113
|
+
def parse_response!(response)
|
114
|
+
request_error!(response[:exception], response[:message], response[:stack_trace]) if response.is_a?(Hash) && response[:exception]
|
115
|
+
response
|
116
|
+
end
|
117
|
+
|
118
|
+
def request_error!(code, message, stack_trace)
|
119
|
+
fail Neo4jrbSpatial::RequestError, <<-ERROR
|
120
|
+
#{ANSI::CYAN}#{code}#{ANSI::CLEAR}: #{message}
|
121
|
+
#{stack_trace}
|
122
|
+
ERROR
|
123
|
+
end
|
124
|
+
|
125
|
+
def get_id(id)
|
126
|
+
return id.neo_id if id.respond_to?(:neo_id)
|
127
|
+
case id
|
128
|
+
when Array
|
129
|
+
get_id(id.first)
|
130
|
+
when Hash
|
131
|
+
id[:self].split('/').last
|
132
|
+
when String
|
133
|
+
id.split('/').last
|
134
|
+
else
|
135
|
+
id
|
136
|
+
end
|
123
137
|
end
|
124
138
|
end
|
125
|
-
end
|
126
139
|
|
127
|
-
|
128
|
-
|
140
|
+
class CypherSession < Neo4j::Session
|
141
|
+
include Spatial
|
142
|
+
end
|
129
143
|
end
|
130
144
|
end
|
data/lib/neo4jrb_spatial.rb
CHANGED
data/neo4jrb_spatial.gemspec
CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.add_development_dependency 'rspec'
|
23
23
|
spec.add_development_dependency 'pry'
|
24
24
|
|
25
|
-
spec.add_dependency 'neo4j', '>= 5.0.1'
|
26
|
-
spec.add_dependency 'neo4j-core', '>= 5.0.1'
|
25
|
+
spec.add_dependency 'neo4j', '>= 5.0.1', '< 8'
|
26
|
+
spec.add_dependency 'neo4j-core', '>= 5.0.1', '< 7'
|
27
27
|
spec.add_dependency 'neo4j-rake_tasks', '~> 0.3'
|
28
28
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: neo4jrb_spatial
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Grigg
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-09-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -87,6 +87,9 @@ dependencies:
|
|
87
87
|
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: 5.0.1
|
90
|
+
- - "<"
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '8'
|
90
93
|
type: :runtime
|
91
94
|
prerelease: false
|
92
95
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -94,6 +97,9 @@ dependencies:
|
|
94
97
|
- - ">="
|
95
98
|
- !ruby/object:Gem::Version
|
96
99
|
version: 5.0.1
|
100
|
+
- - "<"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '8'
|
97
103
|
- !ruby/object:Gem::Dependency
|
98
104
|
name: neo4j-core
|
99
105
|
requirement: !ruby/object:Gem::Requirement
|
@@ -101,6 +107,9 @@ dependencies:
|
|
101
107
|
- - ">="
|
102
108
|
- !ruby/object:Gem::Version
|
103
109
|
version: 5.0.1
|
110
|
+
- - "<"
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '7'
|
104
113
|
type: :runtime
|
105
114
|
prerelease: false
|
106
115
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -108,6 +117,9 @@ dependencies:
|
|
108
117
|
- - ">="
|
109
118
|
- !ruby/object:Gem::Version
|
110
119
|
version: 5.0.1
|
120
|
+
- - "<"
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '7'
|
111
123
|
- !ruby/object:Gem::Dependency
|
112
124
|
name: neo4j-rake_tasks
|
113
125
|
requirement: !ruby/object:Gem::Requirement
|
@@ -132,11 +144,10 @@ files:
|
|
132
144
|
- CHANGELOG.md
|
133
145
|
- Gemfile
|
134
146
|
- README.md
|
135
|
-
- bin/console
|
136
|
-
- bin/setup
|
137
147
|
- lib/neo4j/active_node/spatial.rb
|
138
148
|
- lib/neo4j/spatial.rb
|
139
149
|
- lib/neo4jrb_spatial.rb
|
150
|
+
- lib/neo4jrb_spatial/errors.rb
|
140
151
|
- lib/neo4jrb_spatial/version.rb
|
141
152
|
- neo4jrb_spatial.gemspec
|
142
153
|
homepage: https://github.com/neo4jrb/neo4jrb_spatial
|
@@ -158,7 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
158
169
|
version: '0'
|
159
170
|
requirements: []
|
160
171
|
rubyforge_project:
|
161
|
-
rubygems_version: 2.
|
172
|
+
rubygems_version: 2.5.1
|
162
173
|
signing_key:
|
163
174
|
specification_version: 4
|
164
175
|
summary: Provides basic support for Neo4j Spatial with Neo4j.rb.
|
data/bin/console
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require 'bundler/setup'
|
4
|
-
require 'neo4jrb_spatial'
|
5
|
-
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require "pry"
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require 'irb'
|
14
|
-
IRB.start
|