neo4j-core 3.1.1 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +7 -12
- data/README.md +7 -7
- data/lib/neo4j-core.rb +3 -2
- data/lib/neo4j-core/active_entity.rb +8 -10
- data/lib/neo4j-core/cypher_translator.rb +61 -59
- data/lib/neo4j-core/hash_with_indifferent_access.rb +31 -22
- data/lib/neo4j-core/helpers.rb +15 -17
- data/lib/neo4j-core/label.rb +7 -6
- data/lib/neo4j-core/query.rb +271 -268
- data/lib/neo4j-core/query_clauses.rb +371 -355
- data/lib/neo4j-core/query_find_in_batches.rb +26 -26
- data/lib/neo4j-core/version.rb +1 -1
- data/lib/neo4j-embedded.rb +2 -2
- data/lib/neo4j-embedded/cypher_response.rb +40 -41
- data/lib/neo4j-embedded/embedded_database.rb +21 -22
- data/lib/neo4j-embedded/embedded_ha_session.rb +13 -11
- data/lib/neo4j-embedded/embedded_impermanent_session.rb +9 -8
- data/lib/neo4j-embedded/embedded_label.rb +64 -70
- data/lib/neo4j-embedded/embedded_node.rb +68 -73
- data/lib/neo4j-embedded/embedded_relationship.rb +6 -13
- data/lib/neo4j-embedded/embedded_session.rb +128 -132
- data/lib/neo4j-embedded/embedded_transaction.rb +34 -33
- data/lib/neo4j-embedded/property.rb +84 -77
- data/lib/neo4j-embedded/to_java.rb +24 -23
- data/lib/neo4j-server.rb +1 -1
- data/lib/neo4j-server/cypher_authentication.rb +105 -103
- data/lib/neo4j-server/cypher_label.rb +25 -23
- data/lib/neo4j-server/cypher_node.rb +180 -177
- data/lib/neo4j-server/cypher_node_uncommited.rb +11 -9
- data/lib/neo4j-server/cypher_relationship.rb +101 -102
- data/lib/neo4j-server/cypher_response.rb +171 -170
- data/lib/neo4j-server/cypher_session.rb +209 -205
- data/lib/neo4j-server/cypher_transaction.rb +66 -48
- data/lib/neo4j-server/resource.rb +17 -22
- data/lib/neo4j/entity_equality.rb +3 -4
- data/lib/neo4j/label.rb +13 -16
- data/lib/neo4j/node.rb +30 -34
- data/lib/neo4j/property_container.rb +3 -3
- data/lib/neo4j/property_validator.rb +4 -5
- data/lib/neo4j/relationship.rb +17 -22
- data/lib/neo4j/session.rb +19 -21
- data/lib/neo4j/tasks/config_server.rb +2 -3
- data/lib/neo4j/tasks/neo4j_server.rake +82 -74
- data/lib/neo4j/transaction.rb +23 -22
- data/neo4j-core.gemspec +21 -16
- metadata +72 -2
@@ -1,9 +1,8 @@
|
|
1
|
-
module Neo4j
|
2
|
-
|
3
|
-
class
|
4
|
-
|
5
|
-
|
6
|
-
java_clazz.class_eval do
|
1
|
+
module Neo4j
|
2
|
+
module Embedded
|
3
|
+
class EmbeddedRelationship
|
4
|
+
class << self
|
5
|
+
Java::OrgNeo4jKernelImplCore::RelationshipProxy.class_eval do
|
7
6
|
include Neo4j::Embedded::Property
|
8
7
|
include Neo4j::EntityEquality
|
9
8
|
include Neo4j::Relationship::Wrapper
|
@@ -39,7 +38,7 @@ module Neo4j::Embedded
|
|
39
38
|
end
|
40
39
|
|
41
40
|
def _rel_type
|
42
|
-
getType
|
41
|
+
getType.name.to_sym
|
43
42
|
end
|
44
43
|
tx_methods :rel_type
|
45
44
|
|
@@ -67,14 +66,8 @@ module Neo4j::Embedded
|
|
67
66
|
def _end_node
|
68
67
|
getEndNode
|
69
68
|
end
|
70
|
-
|
71
69
|
end
|
72
70
|
end
|
73
71
|
end
|
74
|
-
|
75
|
-
extend_java_class(Java::OrgNeo4jKernelImplCore::RelationshipProxy)
|
76
|
-
|
77
72
|
end
|
78
|
-
|
79
|
-
|
80
73
|
end
|
@@ -5,166 +5,162 @@ Neo4j::Session.register_db(:embedded_db) do |*args|
|
|
5
5
|
end
|
6
6
|
|
7
7
|
|
8
|
-
module Neo4j
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
module Neo4j
|
9
|
+
module Embedded
|
10
|
+
class EmbeddedSession < Neo4j::Session
|
11
|
+
class Error < StandardError
|
12
|
+
end
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
attr_reader :graph_db, :db_location, :properties_file
|
15
|
+
extend Forwardable
|
16
|
+
extend Neo4j::Core::TxMethods
|
17
|
+
def_delegator :@graph_db, :begin_tx
|
18
18
|
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
20
|
+
def initialize(db_location, config = {})
|
21
|
+
@db_location = db_location
|
22
|
+
@auto_commit = !!config[:auto_commit]
|
23
|
+
@properties_file = config[:properties_file]
|
24
|
+
Neo4j::Session.register(self)
|
25
|
+
end
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
def db_type
|
28
|
+
:embedded_db
|
29
|
+
end
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
def inspect
|
32
|
+
"#{self.class} db_location: '#{@db_location}', running: #{running?}"
|
33
|
+
end
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
def version
|
36
|
+
# Wow
|
37
|
+
version_string = graph_db.to_java(Java::OrgNeo4jKernel::GraphDatabaseAPI).getDependencyResolver.resolveDependency(Java::OrgNeo4jKernel::KernelData.java_class).version.to_s
|
38
|
+
version_string.split(' ')[-1]
|
39
|
+
end
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
41
|
+
def start
|
42
|
+
fail Error, 'Embedded Neo4j db is already running' if running?
|
43
|
+
puts "Start embedded Neo4j db at #{db_location}"
|
44
|
+
factory = Java::OrgNeo4jGraphdbFactory::GraphDatabaseFactory.new
|
45
|
+
db_service = factory.newEmbeddedDatabaseBuilder(db_location)
|
46
|
+
db_service.loadPropertiesFromFile(properties_file) if properties_file
|
47
|
+
@graph_db = db_service.newGraphDatabase
|
48
|
+
Neo4j::Session._notify_listeners(:session_available, self)
|
49
|
+
@engine = Java::OrgNeo4jCypherJavacompat::ExecutionEngine.new(@graph_db)
|
50
|
+
end
|
51
51
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
end
|
52
|
+
def factory_class
|
53
|
+
Java::OrgNeo4jTest::ImpermanentGraphDatabase
|
54
|
+
end
|
56
55
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
56
|
+
def begin_tx
|
57
|
+
if Neo4j::Transaction.current
|
58
|
+
# Handle nested transaction "placebo transaction"
|
59
|
+
Neo4j::Transaction.current.push_nested!
|
60
|
+
else
|
61
|
+
Neo4j::Embedded::EmbeddedTransaction.new(@graph_db.begin_tx)
|
62
|
+
end
|
63
|
+
Neo4j::Transaction.current
|
63
64
|
end
|
64
|
-
Neo4j::Transaction.current
|
65
|
-
end
|
66
65
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
66
|
+
def close
|
67
|
+
super
|
68
|
+
shutdown
|
69
|
+
end
|
71
70
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
71
|
+
def shutdown
|
72
|
+
graph_db && graph_db.shutdown
|
73
|
+
@graph_db = nil
|
74
|
+
end
|
76
75
|
|
77
|
-
|
78
|
-
|
79
|
-
|
76
|
+
def running?
|
77
|
+
!!graph_db
|
78
|
+
end
|
80
79
|
|
81
|
-
|
82
|
-
|
83
|
-
|
80
|
+
def create_label(name)
|
81
|
+
EmbeddedLabel.new(self, name)
|
82
|
+
end
|
84
83
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
84
|
+
def load_node(neo_id)
|
85
|
+
_load_node(neo_id)
|
86
|
+
end
|
87
|
+
tx_methods :load_node
|
88
|
+
|
89
|
+
# Same as load but does not return the node as a wrapped Ruby object.
|
90
|
+
#
|
91
|
+
def _load_node(neo_id)
|
92
|
+
return nil if neo_id.nil?
|
93
|
+
@graph_db.get_node_by_id(neo_id.to_i)
|
94
|
+
rescue Java::OrgNeo4jGraphdb.NotFoundException
|
95
|
+
nil
|
96
|
+
end
|
98
97
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
98
|
+
def load_relationship(neo_id)
|
99
|
+
_load_relationship(neo_id)
|
100
|
+
end
|
101
|
+
tx_methods :load_relationship
|
103
102
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
103
|
+
def _load_relationship(neo_id)
|
104
|
+
return nil if neo_id.nil?
|
105
|
+
@graph_db.get_relationship_by_id(neo_id.to_i)
|
106
|
+
rescue Java::OrgNeo4jGraphdb.NotFoundException
|
107
|
+
nil
|
108
|
+
end
|
110
109
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
110
|
+
def query(*args)
|
111
|
+
if [[String], [String, String]].include?(args.map(&:class))
|
112
|
+
query, params = args[0, 2]
|
113
|
+
Neo4j::Embedded::ResultWrapper.new(_query(query, params), query)
|
114
|
+
else
|
115
|
+
options = args[0] || {}
|
116
|
+
Neo4j::Core::Query.new(options.merge(session: self))
|
117
|
+
end
|
118
118
|
end
|
119
|
-
end
|
120
119
|
|
121
120
|
|
122
|
-
|
123
|
-
|
124
|
-
|
121
|
+
def find_all_nodes(label)
|
122
|
+
EmbeddedLabel.new(self, label).find_nodes
|
123
|
+
end
|
125
124
|
|
126
|
-
|
127
|
-
|
128
|
-
|
125
|
+
def find_nodes(label, key, value)
|
126
|
+
EmbeddedLabel.new(self, label).find_nodes(key, value)
|
127
|
+
end
|
129
128
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
129
|
+
# Performs a cypher query with given string.
|
130
|
+
# Remember that you should close the resource iterator.
|
131
|
+
# @param [String] q the cypher query as a String
|
132
|
+
# @return (see #query)
|
133
|
+
def _query(q, params = {})
|
134
|
+
@engine ||= Java::OrgNeo4jCypherJavacompat::ExecutionEngine.new(@graph_db)
|
135
|
+
@engine.execute(q, Neo4j::Core::HashWithIndifferentAccess.new(params))
|
136
|
+
rescue StandardError => e
|
137
|
+
raise Neo4j::Session::CypherError.new(e.message, e.class, 'cypher error')
|
138
|
+
end
|
140
139
|
|
141
|
-
|
142
|
-
|
143
|
-
|
140
|
+
def query_default_return(as)
|
141
|
+
" RETURN #{as}"
|
142
|
+
end
|
144
143
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
144
|
+
def _query_or_fail(q)
|
145
|
+
@engine ||= Java::OrgNeo4jCypherJavacompat::ExecutionEngine.new(@graph_db)
|
146
|
+
@engine.execute(q)
|
147
|
+
end
|
149
148
|
|
150
|
-
|
151
|
-
|
152
|
-
|
149
|
+
def search_result_to_enumerable(result)
|
150
|
+
result.map { |column| column['n'].wrapper }
|
151
|
+
end
|
153
152
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
153
|
+
def create_node(properties = nil, labels = [])
|
154
|
+
if labels.empty?
|
155
|
+
graph_db.create_node
|
156
|
+
else
|
157
|
+
labels = EmbeddedLabel.as_java(labels)
|
158
|
+
graph_db.create_node(labels)
|
159
|
+
end.tap do |java_node|
|
160
|
+
properties.each_pair { |k, v| java_node[k] = v } if properties
|
161
|
+
end
|
160
162
|
end
|
161
|
-
|
162
|
-
_java_node
|
163
|
+
tx_methods :create_node
|
163
164
|
end
|
164
|
-
tx_methods :create_node
|
165
|
-
|
166
165
|
end
|
167
|
-
|
168
|
-
|
169
|
-
|
170
166
|
end
|
@@ -1,35 +1,36 @@
|
|
1
|
-
module Neo4j
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
1
|
+
module Neo4j
|
2
|
+
module Embedded
|
3
|
+
class EmbeddedTransaction
|
4
|
+
attr_reader :root_tx
|
5
|
+
include Neo4j::Transaction::Instance
|
6
|
+
|
7
|
+
def initialize(root_tx)
|
8
|
+
@root_tx = root_tx
|
9
|
+
register_instance
|
10
|
+
end
|
11
|
+
|
12
|
+
def acquire_read_lock(entity)
|
13
|
+
@root_tx.acquire_read_lock(entity)
|
14
|
+
end
|
15
|
+
|
16
|
+
def acquire_write_lock(entity)
|
17
|
+
@root_tx.acquire_write_lock(entity)
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def inspect
|
22
|
+
"EmbeddedTransaction [nested: #{@pushed_nested} failed?: #{failure?} active: #{Neo4j::Transaction.current == self}]"
|
23
|
+
end
|
24
|
+
|
25
|
+
def _delete_tx
|
26
|
+
@root_tx.failure
|
27
|
+
@root_tx.close
|
28
|
+
end
|
29
|
+
|
30
|
+
def _commit_tx
|
31
|
+
@root_tx.success
|
32
|
+
@root_tx.close
|
33
|
+
end
|
13
34
|
end
|
14
|
-
|
15
|
-
def acquire_write_lock(entity)
|
16
|
-
@root_tx.acquire_write_lock(entity)
|
17
|
-
end
|
18
|
-
|
19
|
-
|
20
|
-
def inspect
|
21
|
-
"EmbeddedTransaction [nested: #{@pushed_nested} failed?: #{failure?} active: #{Neo4j::Transaction.current == self}]"
|
22
|
-
end
|
23
|
-
|
24
|
-
def _delete_tx
|
25
|
-
@root_tx.failure
|
26
|
-
@root_tx.close
|
27
|
-
end
|
28
|
-
|
29
|
-
def _commit_tx
|
30
|
-
@root_tx.success
|
31
|
-
@root_tx.close
|
32
|
-
end
|
33
|
-
|
34
35
|
end
|
35
|
-
end
|
36
|
+
end
|
@@ -1,99 +1,106 @@
|
|
1
1
|
|
2
|
-
# TODO code duplication with the Neo4j::PropertyContainer,
|
2
|
+
# TODO: code duplication with the Neo4j::PropertyContainer,
|
3
3
|
# This module should extend that module by adding transaction around methods
|
4
|
-
module Neo4j
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
module Neo4j
|
5
|
+
module Embedded
|
6
|
+
module Property
|
7
|
+
include Neo4j::PropertyValidator
|
8
|
+
include Neo4j::PropertyContainer
|
9
|
+
extend Neo4j::Core::TxMethods
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
+
# inherit the []= method but add auto transaction around it
|
12
|
+
tx_methods :[]=
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
val = to_ruby_property(key.to_s)
|
15
|
-
end
|
16
|
-
tx_methods :[]
|
17
|
-
|
18
|
-
# Sets the property of this node.
|
19
|
-
# Property keys are always strings. Valid property value types are the primitives(<tt>String</tt>, <tt>Fixnum</tt>, <tt>Float</tt>, <tt>FalseClass</tt>, <tt>TrueClass</tt>) or array of those primitives.
|
20
|
-
#
|
21
|
-
# ==== Gotchas
|
22
|
-
# * Values in the array must be of the same type.
|
23
|
-
# * You can *not* delete or add one item in the array (e.g. person.phones.delete('123')) but instead you must create a new array instead.
|
24
|
-
#
|
25
|
-
# @param [String, Symbol] k of the property to set
|
26
|
-
# @param [String,Fixnum,Float,true,false, Array] v to set
|
27
|
-
def []=(k, v)
|
28
|
-
to_java_property(k, v)
|
29
|
-
end
|
30
|
-
tx_methods :[]=
|
14
|
+
def [](key)
|
15
|
+
return nil unless has_property?(key.to_s)
|
31
16
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
ret[key.to_sym] = val
|
36
|
-
ret
|
37
|
-
end
|
38
|
-
end
|
39
|
-
tx_methods :props
|
17
|
+
to_ruby_property(key.to_s)
|
18
|
+
end
|
19
|
+
tx_methods :[]
|
40
20
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
21
|
+
# Sets the property of this node.
|
22
|
+
# Property keys are always strings. Valid property value types are the primitives:
|
23
|
+
# (<tt>String</tt>, <tt>Fixnum</tt>, <tt>Float</tt>, <tt>FalseClass</tt>, <tt>TrueClass</tt>)
|
24
|
+
# or an array of those primitives.
|
25
|
+
#
|
26
|
+
# ==== Gotchas
|
27
|
+
# * Values in the array must be of the same type.
|
28
|
+
# * You can *not* delete or add one item in the array (e.g. person.phones.delete('123')) but instead you must create a new array instead.
|
29
|
+
#
|
30
|
+
# @param [String, Symbol] k of the property to set
|
31
|
+
# @param [String,Fixnum,Float,true,false, Array] v to set
|
32
|
+
def []=(k, v)
|
33
|
+
to_java_property(k, v)
|
34
|
+
end
|
35
|
+
tx_methods :[]=
|
49
36
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
37
|
+
def props
|
38
|
+
property_keys.each_with_object({}) do |key, ret|
|
39
|
+
ret[key.to_sym] = to_ruby_property(key)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
tx_methods :props
|
54
43
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
44
|
+
def props=(hash)
|
45
|
+
property_keys.each do |key|
|
46
|
+
remove_property(key)
|
47
|
+
end
|
48
|
+
_update_props(hash)
|
49
|
+
hash
|
50
|
+
end
|
51
|
+
tx_methods :props=
|
59
52
|
|
60
|
-
|
61
|
-
|
62
|
-
|
53
|
+
def _update_props(hash)
|
54
|
+
hash.each { |k, v| to_java_property(k, v) }
|
55
|
+
end
|
63
56
|
|
64
|
-
|
65
|
-
|
66
|
-
|
57
|
+
def update_props(hash)
|
58
|
+
_update_props(hash)
|
59
|
+
end
|
60
|
+
tx_methods :update_props
|
67
61
|
|
68
|
-
|
62
|
+
def neo_id
|
63
|
+
get_id
|
64
|
+
end
|
69
65
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
66
|
+
def refresh
|
67
|
+
# nothing is needed in the embedded db since we always asks the database
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
74
71
|
|
75
|
-
|
76
|
-
|
72
|
+
def to_ruby_property(key)
|
73
|
+
val = get_property(key)
|
74
|
+
val.class.superclass == ArrayJavaProxy ? val.to_a : val
|
75
|
+
end
|
77
76
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
77
|
+
def to_java_property(k, v)
|
78
|
+
validate_property(v)
|
79
|
+
|
80
|
+
k = k.to_s
|
81
|
+
case v
|
82
|
+
when nil
|
83
|
+
remove_property(k)
|
84
|
+
when Array
|
85
|
+
type = java_type_from_value(v[0]) || fail("Not allowed to store array with value #{v[0]} type #{v[0].class}")
|
86
|
+
set_property(k, v.to_java(type))
|
87
|
+
else
|
88
|
+
set_property(k, v)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def java_type_from_value(value)
|
93
|
+
case value
|
83
94
|
when String
|
84
|
-
|
95
|
+
:string
|
85
96
|
when Float
|
86
|
-
|
97
|
+
:double
|
87
98
|
when FalseClass, TrueClass
|
88
|
-
|
99
|
+
:boolean
|
89
100
|
when Fixnum
|
90
|
-
|
91
|
-
|
92
|
-
raise "Not allowed to store array with value #{v[0]} type #{v[0].class}"
|
101
|
+
:long
|
102
|
+
end
|
93
103
|
end
|
94
|
-
else
|
95
|
-
set_property(k, v)
|
96
104
|
end
|
97
105
|
end
|
98
|
-
|
99
106
|
end
|