activegraph 11.5.0.beta.1 → 12.0.0.beta.1
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 +4 -4
- data/CHANGELOG.md +8 -0
- data/activegraph.gemspec +1 -1
- data/lib/active_graph/base.rb +4 -0
- data/lib/active_graph/core/element.rb +142 -0
- data/lib/active_graph/core/entity.rb +4 -0
- data/lib/active_graph/core/label.rb +5 -166
- data/lib/active_graph/core/node.rb +0 -4
- data/lib/active_graph/core/query_clauses.rb +4 -4
- data/lib/active_graph/core/schema.rb +23 -28
- data/lib/active_graph/core/type.rb +13 -0
- data/lib/active_graph/migrations/helpers/schema.rb +10 -13
- data/lib/active_graph/model_schema.rb +1 -1
- data/lib/active_graph/node/has_n.rb +1 -1
- data/lib/active_graph/node/labels.rb +15 -12
- data/lib/active_graph/node/persistence.rb +0 -11
- data/lib/active_graph/node/query/query_proxy/link.rb +15 -4
- data/lib/active_graph/node/query/query_proxy.rb +3 -3
- data/lib/active_graph/node/query/query_proxy_eager_loading.rb +1 -1
- data/lib/active_graph/node/query/query_proxy_enumerable.rb +4 -4
- data/lib/active_graph/node/query/query_proxy_methods.rb +14 -16
- data/lib/active_graph/node/query/query_proxy_methods_of_mass_updating.rb +1 -5
- data/lib/active_graph/node/query.rb +1 -1
- data/lib/active_graph/node/query_methods.rb +9 -12
- data/lib/active_graph/relationship/initialize.rb +2 -2
- data/lib/active_graph/relationship/persistence.rb +3 -1
- data/lib/active_graph/relationship/property.rb +1 -5
- data/lib/active_graph/relationship/query.rb +14 -9
- data/lib/active_graph/relationship/related_node.rb +4 -8
- data/lib/active_graph/relationship/types.rb +8 -0
- data/lib/active_graph/relationship/wrapping.rb +1 -1
- data/lib/active_graph/relationship.rb +4 -1
- data/lib/active_graph/shared/identity.rb +6 -3
- data/lib/active_graph/shared/persistence.rb +12 -1
- data/lib/active_graph/shared/query_factory.rb +1 -1
- data/lib/active_graph/shared/type_converters.rb +3 -2
- data/lib/active_graph/version.rb +1 -1
- metadata +21 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5980a6fcd4bee8de9d49abdc805f45292b507d76b6d4299eb3424b57fd33dd98
|
4
|
+
data.tar.gz: 16a8d463cf9b8cf88d814b4a9fd33db8f83e92b3ab4cd2e903377e420b4acd24
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 02bb5a53486be92a3a8724a42525b02148065fb0461fe9400d31c95d3bf7cbe351028cd955fea96dd22ec587baae8abe6c4e9498d131a7019bbee0bb2c78d093
|
7
|
+
data.tar.gz: a98acca7075481e24e9926bfcbb8cb6fadefc9e11cef963fa146fc7c543e8682d7fcb8639e681c3fb5971738d01568623f59456cb93ce36de7c0eaf7a6500abf
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file.
|
|
3
3
|
This file should follow the standards specified on [http://keepachangelog.com/]
|
4
4
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
5
5
|
|
6
|
+
## [12.0.0.beta.1] 2024-01-01
|
7
|
+
|
8
|
+
## Added
|
9
|
+
|
10
|
+
- removed deprecated usage of id (neo_id), replaced with element_id, requires neo4j-ruby-driver 5
|
11
|
+
- removed the possibility of using neo_id as id_property
|
12
|
+
- added id_property to relationships
|
13
|
+
|
6
14
|
## [11.5.0.beta.1] 2023-12-29
|
7
15
|
|
8
16
|
## Added
|
data/activegraph.gemspec
CHANGED
@@ -32,7 +32,7 @@ DESCRIPTION
|
|
32
32
|
|
33
33
|
s.add_dependency('activemodel', '>= 7')
|
34
34
|
s.add_dependency('i18n', '!= 1.8.8') # https://github.com/jruby/jruby/issues/6547
|
35
|
-
s.add_dependency('neo4j-ruby-driver', '>=
|
35
|
+
s.add_dependency('neo4j-ruby-driver', '>= 5')
|
36
36
|
s.add_dependency('orm_adapter', '>= 0.5.0')
|
37
37
|
s.add_dependency('sorted_set')
|
38
38
|
s.add_development_dependency('guard')
|
data/lib/active_graph/base.rb
CHANGED
@@ -60,6 +60,10 @@ module ActiveGraph
|
|
60
60
|
ActiveGraph::Core::Label.new(label_name)
|
61
61
|
end
|
62
62
|
|
63
|
+
def element(name, relationship: false)
|
64
|
+
(relationship ? Core::Type : Core::Label).new(name)
|
65
|
+
end
|
66
|
+
|
63
67
|
def logger
|
64
68
|
@logger ||= (ActiveGraph::Config[:logger] || ActiveSupport::Logger.new(STDOUT))
|
65
69
|
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module ActiveGraph
|
2
|
+
module Core
|
3
|
+
class Element
|
4
|
+
attr_reader :name
|
5
|
+
delegate :version?, to: ActiveGraph::Base
|
6
|
+
|
7
|
+
def initialize(name)
|
8
|
+
@name = name
|
9
|
+
end
|
10
|
+
|
11
|
+
def create_index(*properties, **options)
|
12
|
+
validate_index_options!(options)
|
13
|
+
properties = properties.map { |p| "l.#{p}" }
|
14
|
+
schema_query("CREATE INDEX FOR (l:`#{@name}`) ON (#{properties.join('.')})")
|
15
|
+
end
|
16
|
+
|
17
|
+
def drop_index(property, options = {})
|
18
|
+
validate_index_options!(options)
|
19
|
+
schema_query("SHOW INDEXES YIELD * WHERE labelsOrTypes = $labels AND properties = $properties",
|
20
|
+
labels: [@name], properties: [property]).each do |record|
|
21
|
+
schema_query("DROP INDEX #{record[:name]}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Creates a neo4j constraint on a property
|
26
|
+
# See http://docs.neo4j.org/chunked/stable/query-constraints.html
|
27
|
+
# @example
|
28
|
+
# label = ActiveGraph::Label.create(:person)
|
29
|
+
# label.create_constraint(:name, {type: :unique})
|
30
|
+
#
|
31
|
+
def create_constraint(property, type: :key)
|
32
|
+
schema_query(
|
33
|
+
"CREATE CONSTRAINT #{constraint_name(property, type:)} FOR #{pattern("n:`#{name}`")} REQUIRE n.`#{property}` IS #{constraint_type(type:)}"
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Drops a neo4j constraint on a property
|
38
|
+
# See http://docs.neo4j.org/chunked/stable/query-constraints.html
|
39
|
+
# @example
|
40
|
+
# label = ActiveGraph::Label.create(:person)
|
41
|
+
# label.create_constraint(:name, {type: :unique})
|
42
|
+
# label.drop_constraint(:name, {type: :unique})
|
43
|
+
#
|
44
|
+
def drop_constraint(property, type: :key)
|
45
|
+
schema_query("DROP CONSTRAINT #{constraint_name(property, type:)} IF EXISTS")
|
46
|
+
end
|
47
|
+
|
48
|
+
def drop_uniqueness_constraint(property, options = {})
|
49
|
+
drop_constraint(property, type: :unique)
|
50
|
+
end
|
51
|
+
|
52
|
+
def indexes
|
53
|
+
self.class.indexes.select do |definition|
|
54
|
+
definition[:label] == @name.to_sym
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def drop_indexes
|
59
|
+
self.class.drop_indexes
|
60
|
+
end
|
61
|
+
|
62
|
+
def index?(property)
|
63
|
+
indexes.any? { |definition| definition[:properties] == [property.to_sym] }
|
64
|
+
end
|
65
|
+
|
66
|
+
def constraints(_options = {})
|
67
|
+
ActiveGraph::Base.constraints.select do |definition|
|
68
|
+
definition[:label] == @name.to_sym
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def uniqueness_constraints(_options = {})
|
73
|
+
constraints.select do |definition|
|
74
|
+
definition[:type] == :uniqueness
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def constraint?(property)
|
79
|
+
constraints.any? { |definition| definition[:properties] == [property.to_sym] }
|
80
|
+
end
|
81
|
+
|
82
|
+
def uniqueness_constraint?(property)
|
83
|
+
uniqueness_constraints.include?([property])
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
class << self
|
89
|
+
def indexes
|
90
|
+
ActiveGraph::Base.indexes
|
91
|
+
end
|
92
|
+
|
93
|
+
def drop_indexes
|
94
|
+
indexes.each do |definition|
|
95
|
+
ActiveGraph::Base.query("DROP INDEX #{definition[:name]}") unless definition[:owningConstraint]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def drop_constraints
|
100
|
+
result = ActiveGraph::Base.read_transaction do |tx|
|
101
|
+
tx.run('SHOW CONSTRAINTS YIELD *').to_a
|
102
|
+
end
|
103
|
+
ActiveGraph::Base.write_transaction do |tx|
|
104
|
+
result.each do |record|
|
105
|
+
tx.run("DROP CONSTRAINT `#{record[:name]}`")
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def schema_query(cypher, **params)
|
112
|
+
ActiveGraph::Base.query(cypher, params)
|
113
|
+
end
|
114
|
+
|
115
|
+
def validate_index_options!(options)
|
116
|
+
return unless options[:type] && options[:type] != :exact
|
117
|
+
fail "Type #{options[:type]} is not supported"
|
118
|
+
end
|
119
|
+
|
120
|
+
def constraint_type(type:)
|
121
|
+
case symnolic_type(type:)
|
122
|
+
when :key
|
123
|
+
"#{element_type} KEY"
|
124
|
+
when :unique
|
125
|
+
"UNIQUE"
|
126
|
+
when :not_null
|
127
|
+
"UNIQUE"
|
128
|
+
else
|
129
|
+
":: #{type.to_s.upcase}"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def symnolic_type(type:)
|
134
|
+
type == :key && !ActiveGraph::Base.enterprise? ? :unique : type
|
135
|
+
end
|
136
|
+
|
137
|
+
def constraint_name(property, type:)
|
138
|
+
"`#{element_type}_#{name}##{property}_#{symnolic_type(type:)}`"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -1,173 +1,12 @@
|
|
1
1
|
module ActiveGraph
|
2
2
|
module Core
|
3
|
-
class Label
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
def initialize(name)
|
8
|
-
@name = name
|
9
|
-
end
|
10
|
-
|
11
|
-
def create_index(*properties, **options)
|
12
|
-
validate_index_options!(options)
|
13
|
-
if version?('>=4.4')
|
14
|
-
properties = properties.map { |p| "l.#{p}" }
|
15
|
-
fragment = "FOR (l:`#{@name}`) ON"
|
16
|
-
else
|
17
|
-
fragment = "ON :`#{@name}`"
|
18
|
-
end
|
19
|
-
schema_query("CREATE INDEX #{fragment} (#{properties.join('.')})")
|
20
|
-
end
|
21
|
-
|
22
|
-
def drop_index(property, options = {})
|
23
|
-
validate_index_options!(options)
|
24
|
-
if version?('<4.3')
|
25
|
-
schema_query("DROP INDEX ON :`#{@name}`(#{property})")
|
26
|
-
else
|
27
|
-
schema_query("SHOW INDEXES YIELD * WHERE labelsOrTypes = $labels AND properties = $properties",
|
28
|
-
labels: [@name], properties: [property]).each do |record|
|
29
|
-
schema_query("DROP INDEX #{record[:name]}")
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# Creates a neo4j constraint on a property
|
35
|
-
# See http://docs.neo4j.org/chunked/stable/query-constraints.html
|
36
|
-
# @example
|
37
|
-
# label = ActiveGraph::Label.create(:person)
|
38
|
-
# label.create_constraint(:name, {type: :unique})
|
39
|
-
#
|
40
|
-
def create_constraint(property, constraints)
|
41
|
-
cypher = case constraints[:type]
|
42
|
-
when :unique, :uniqueness
|
43
|
-
_for, _require = version?('>=4.4') ? %w[FOR REQUIRE] : %w[ON ASSERT]
|
44
|
-
"CREATE CONSTRAINT #{_for} (n:`#{name}`) #{_require} n.`#{property}` IS UNIQUE"
|
45
|
-
else
|
46
|
-
fail "Not supported constraint #{constraints.inspect} for property #{property} (expected :type => :unique)"
|
47
|
-
end
|
48
|
-
schema_query(cypher)
|
49
|
-
end
|
50
|
-
|
51
|
-
def create_uniqueness_constraint(property, options = {})
|
52
|
-
create_constraint(property, options.merge(type: :unique))
|
53
|
-
end
|
54
|
-
|
55
|
-
# Drops a neo4j constraint on a property
|
56
|
-
# See http://docs.neo4j.org/chunked/stable/query-constraints.html
|
57
|
-
# @example
|
58
|
-
# label = ActiveGraph::Label.create(:person)
|
59
|
-
# label.create_constraint(:name, {type: :unique})
|
60
|
-
# label.drop_constraint(:name, {type: :unique})
|
61
|
-
#
|
62
|
-
def drop_constraint(property, constraint)
|
63
|
-
return drop_constraint42(property, constraint) if version?('<4.3')
|
64
|
-
type = case constraint[:type]
|
65
|
-
when :unique, :uniqueness
|
66
|
-
'UNIQUENESS'
|
67
|
-
when :exists
|
68
|
-
'NODE_PROPERTY_EXISTENCE'
|
69
|
-
else
|
70
|
-
fail "Not supported constraint #{constraint.inspect}"
|
71
|
-
end
|
72
|
-
schema_query(
|
73
|
-
'SHOW CONSTRAINTS YIELD * WHERE type = $type AND labelsOrTypes = $labels AND properties = $properties',
|
74
|
-
type: type, labels: [name], properties: [property]).first[:name].tap do |constraint_name|
|
75
|
-
schema_query("DROP CONSTRAINT #{constraint_name}")
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def drop_uniqueness_constraint(property, options = {})
|
80
|
-
drop_constraint(property, options.merge(type: :unique))
|
81
|
-
end
|
82
|
-
|
83
|
-
def indexes
|
84
|
-
self.class.indexes.select do |definition|
|
85
|
-
definition[:label] == @name.to_sym
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def drop_indexes
|
90
|
-
self.class.drop_indexes
|
91
|
-
end
|
92
|
-
|
93
|
-
def index?(property)
|
94
|
-
indexes.any? { |definition| definition[:properties] == [property.to_sym] }
|
95
|
-
end
|
96
|
-
|
97
|
-
def constraints(_options = {})
|
98
|
-
ActiveGraph::Base.constraints.select do |definition|
|
99
|
-
definition[:label] == @name.to_sym
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
def uniqueness_constraints(_options = {})
|
104
|
-
constraints.select do |definition|
|
105
|
-
definition[:type] == :uniqueness
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
def constraint?(property)
|
110
|
-
constraints.any? { |definition| definition[:properties] == [property.to_sym] }
|
111
|
-
end
|
112
|
-
|
113
|
-
def uniqueness_constraint?(property)
|
114
|
-
uniqueness_constraints.include?([property])
|
115
|
-
end
|
116
|
-
|
117
|
-
private
|
118
|
-
|
119
|
-
class << self
|
120
|
-
def indexes
|
121
|
-
ActiveGraph::Base.indexes
|
122
|
-
end
|
123
|
-
|
124
|
-
def drop_indexes
|
125
|
-
indexes.each do |definition|
|
126
|
-
begin
|
127
|
-
ActiveGraph::Base.query(
|
128
|
-
if definition[:name]
|
129
|
-
"DROP INDEX #{definition[:name]}"
|
130
|
-
else
|
131
|
-
"DROP INDEX ON :`#{definition[:label]}`(#{definition[:properties][0]})"
|
132
|
-
end)
|
133
|
-
rescue Neo4j::Driver::Exceptions::DatabaseException
|
134
|
-
# This will error on each constraint. Ignore and continue.
|
135
|
-
next
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
def drop_constraints
|
141
|
-
result = ActiveGraph::Base.read_transaction do |tx|
|
142
|
-
tx.run(ActiveGraph::Base.version?('<4.3') ? 'CALL db.constraints' : 'SHOW CONSTRAINTS YIELD *').to_a
|
143
|
-
end
|
144
|
-
ActiveGraph::Base.write_transaction do |tx|
|
145
|
-
result.each do |record|
|
146
|
-
tx.run("DROP #{record.keys.include?(:name) ? "CONSTRAINT #{record[:name]}" : record[:description]}")
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
def schema_query(cypher, **params)
|
153
|
-
ActiveGraph::Base.query(cypher, params)
|
154
|
-
end
|
155
|
-
|
156
|
-
def validate_index_options!(options)
|
157
|
-
return unless options[:type] && options[:type] != :exact
|
158
|
-
fail "Type #{options[:type]} is not supported"
|
3
|
+
class Label < Element
|
4
|
+
def pattern(spec)
|
5
|
+
"(#{spec})"
|
159
6
|
end
|
160
7
|
|
161
|
-
def
|
162
|
-
|
163
|
-
when :unique, :uniqueness
|
164
|
-
"n.`#{property}` IS UNIQUE"
|
165
|
-
when :exists
|
166
|
-
"exists(n.`#{property}`)"
|
167
|
-
else
|
168
|
-
fail "Not supported constraint #{constraint.inspect}"
|
169
|
-
end
|
170
|
-
schema_query("DROP CONSTRAINT ON (n:`#{name}`) ASSERT #{cypher}")
|
8
|
+
def element_type
|
9
|
+
'NODE'
|
171
10
|
end
|
172
11
|
end
|
173
12
|
end
|
@@ -158,7 +158,7 @@ module ActiveGraph
|
|
158
158
|
end
|
159
159
|
|
160
160
|
def from_key_and_single_value(key, value)
|
161
|
-
value.to_sym == :neo_id ? "
|
161
|
+
value.to_sym == :neo_id ? "elementId(#{key})" : "#{key}.#{value}"
|
162
162
|
end
|
163
163
|
end
|
164
164
|
|
@@ -200,7 +200,7 @@ module ActiveGraph
|
|
200
200
|
end
|
201
201
|
|
202
202
|
def array_value?(value, is_set)
|
203
|
-
value.is_a?(
|
203
|
+
value.is_a?(Enumerable) && !is_set
|
204
204
|
end
|
205
205
|
|
206
206
|
def format_label(label_arg)
|
@@ -316,8 +316,8 @@ module ActiveGraph
|
|
316
316
|
def hash_key_value_string(key, value, previous_keys)
|
317
317
|
value.map do |k, v|
|
318
318
|
if k.to_sym == :neo_id
|
319
|
-
v = Array(v).map { |item|
|
320
|
-
key_value_string("
|
319
|
+
v = Array(v).map { |item| item.respond_to?(:neo_id) ? item.neo_id : item }
|
320
|
+
key_value_string("elementId(#{key})", v)
|
321
321
|
else
|
322
322
|
"#{key}.#{from_key_and_value(k, v, previous_keys + [key])}"
|
323
323
|
end
|
@@ -1,21 +1,20 @@
|
|
1
1
|
module ActiveGraph
|
2
2
|
module Core
|
3
3
|
module Schema
|
4
|
-
FILTER = {
|
5
|
-
3 => [:type, 'node_unique_property'],
|
6
|
-
4 => [:uniqueness, 'UNIQUE'],
|
7
|
-
}
|
8
|
-
|
9
4
|
def version
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
5
|
+
Gem::Version.new(component[:versions][0])
|
6
|
+
end
|
7
|
+
|
8
|
+
def edition
|
9
|
+
component[:edition]
|
10
|
+
end
|
11
|
+
|
12
|
+
def enterprise?
|
13
|
+
edition == 'enterprise'
|
15
14
|
end
|
16
15
|
|
17
16
|
def version?(requirement)
|
18
|
-
Gem::Requirement.create(requirement).satisfied_by?(
|
17
|
+
Gem::Requirement.create(requirement).satisfied_by?(version)
|
19
18
|
end
|
20
19
|
|
21
20
|
def indexes
|
@@ -24,17 +23,12 @@ module ActiveGraph
|
|
24
23
|
|
25
24
|
def normalize(result, *extra)
|
26
25
|
result.map do |row|
|
27
|
-
definition(row,
|
28
|
-
.merge(extra.to_h { |key| [key, row[key].to_sym] })
|
26
|
+
definition(row, :index_cypher).merge(extra.to_h { |key| [key, row[key].to_sym] })
|
29
27
|
end
|
30
28
|
end
|
31
29
|
|
32
30
|
def constraints
|
33
|
-
|
34
|
-
raw_indexes.select(&method(:constraint_owned?))
|
35
|
-
else
|
36
|
-
raw_constraints.select(&method(:constraint_filter))
|
37
|
-
end.map { |row| definition(row, :constraint_cypher).merge(type: :uniqueness) }
|
31
|
+
raw_constraints.select(&method(:constraint_filter)).map { |row| definition(row, :constraint_cypher).merge(type: :uniqueness) }
|
38
32
|
end
|
39
33
|
|
40
34
|
private def raw_constraints
|
@@ -45,27 +39,28 @@ module ActiveGraph
|
|
45
39
|
|
46
40
|
def raw_indexes
|
47
41
|
read_transaction do
|
48
|
-
query(
|
49
|
-
.reject { |row| row[:type] == 'LOOKUP' }
|
42
|
+
query('SHOW INDEXES YIELD *', {}, skip_instrumentation: true).reject { |row| row[:type] == 'LOOKUP' }
|
50
43
|
end
|
51
44
|
end
|
52
45
|
|
53
46
|
def constraint_owned?(record)
|
54
|
-
|
47
|
+
record[:owningConstraint]
|
55
48
|
end
|
56
49
|
|
57
50
|
private
|
58
51
|
|
52
|
+
def component
|
53
|
+
@component ||= read_transaction do
|
54
|
+
query('CALL dbms.components()', {}, skip_instrumentation: true).first
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
59
58
|
def major
|
60
59
|
@major ||= version.segments.first
|
61
60
|
end
|
62
61
|
|
63
62
|
def constraint_filter(record)
|
64
|
-
%w[UNIQUENESS RELATIONSHIP_PROPERTY_EXISTENCE NODE_PROPERTY_EXISTENCE NODE_KEY].include?(record[:type])
|
65
|
-
end
|
66
|
-
|
67
|
-
def index_cypher_v3(label, properties)
|
68
|
-
"INDEX ON :#{label}#{com_sep(properties, nil)}"
|
63
|
+
%w[UNIQUENESS RELATIONSHIP_UNIQUENESS RELATIONSHIP_PROPERTY_EXISTENCE NODE_PROPERTY_EXISTENCE NODE_KEY RELATIONSHIP_KEY].include?(record[:type])
|
69
64
|
end
|
70
65
|
|
71
66
|
def index_cypher(label, properties)
|
@@ -82,11 +77,11 @@ module ActiveGraph
|
|
82
77
|
|
83
78
|
def definition(row, template)
|
84
79
|
{ label: label(row), properties: properties(row), name: row[:name],
|
85
|
-
create_statement: row[:createStatement] || send(template,label(row), row[:properties]) }
|
80
|
+
create_statement: row[:createStatement] || send(template, label(row), row[:properties]) }
|
86
81
|
end
|
87
82
|
|
88
83
|
def label(row)
|
89
|
-
row[
|
84
|
+
row[:labelsOrTypes].first.to_sym
|
90
85
|
end
|
91
86
|
|
92
87
|
def properties(row)
|
@@ -6,18 +6,16 @@ module ActiveGraph
|
|
6
6
|
MISSING_CONSTRAINT_OR_INDEX = 'No such %{type} for %{label}#%{property}'.freeze
|
7
7
|
DUPLICATE_CONSTRAINT_OR_INDEX = 'Duplicate %{type} for %{label}#%{property}'.freeze
|
8
8
|
|
9
|
-
def add_constraint(
|
10
|
-
|
11
|
-
|
12
|
-
label_object = ActiveGraph::Base.label_object(label)
|
13
|
-
if label_object.constraint?(property)
|
9
|
+
def add_constraint(name, property, relationship: false, type: :key, force: false)
|
10
|
+
element = ActiveGraph::Base.element(name, relationship:)
|
11
|
+
if element.constraint?(property)
|
14
12
|
if force
|
15
|
-
|
13
|
+
element.drop_constraint(property, type:)
|
16
14
|
else
|
17
|
-
fail_duplicate_constraint_or_index!(:constraint,
|
15
|
+
fail_duplicate_constraint_or_index!(:constraint, name, property)
|
18
16
|
end
|
19
17
|
end
|
20
|
-
|
18
|
+
element.create_constraint(property, type:)
|
21
19
|
end
|
22
20
|
|
23
21
|
def add_index(label, property, options = {})
|
@@ -33,11 +31,10 @@ module ActiveGraph
|
|
33
31
|
label_object.create_index(property)
|
34
32
|
end
|
35
33
|
|
36
|
-
def drop_constraint(
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
label_object.drop_constraint(property, type: type)
|
34
|
+
def drop_constraint(name, property, type: :key, relationship: false, force: false)
|
35
|
+
element = ActiveGraph::Base.element(name, relationship:)
|
36
|
+
fail_missing_constraint_or_index!(:constraint, name, property) unless force || element.constraint?(property)
|
37
|
+
element.drop_constraint(property, type:)
|
41
38
|
end
|
42
39
|
|
43
40
|
def drop_index(label, property, options = {})
|
@@ -55,7 +55,7 @@ module ActiveGraph
|
|
55
55
|
# should be private
|
56
56
|
def schema_elements_list(by_model, db_results)
|
57
57
|
by_model.flat_map do |model, property_names|
|
58
|
-
label = model.
|
58
|
+
label = model.mapped_element_name.to_sym
|
59
59
|
property_names.map do |property_name|
|
60
60
|
exists = db_results[label] && db_results[label].include?([property_name])
|
61
61
|
[model, label, property_name, exists]
|
@@ -286,7 +286,7 @@ module ActiveGraph::Node
|
|
286
286
|
query_proxy = self.class.as(:previous).where(neo_id: result_cache.map(&:neo_id))
|
287
287
|
query_proxy = self.class.send(:association_query_proxy, association_name, previous_query_proxy: query_proxy, node: :next, optional: true)
|
288
288
|
|
289
|
-
Hash[*query_proxy.pluck('
|
289
|
+
Hash[*query_proxy.pluck('elementId(previous)', 'collect(next)').flatten(1)].each_value do |records|
|
290
290
|
records.each do |record|
|
291
291
|
record.instance_variable_set('@source_proxy_result_cache', records)
|
292
292
|
end
|
@@ -108,7 +108,7 @@ module ActiveGraph
|
|
108
108
|
|
109
109
|
# Deletes all nodes and connected relationships from Cypher.
|
110
110
|
def delete_all
|
111
|
-
neo4j_query("MATCH (n:`#{mapped_label_name}`)
|
111
|
+
neo4j_query("MATCH (n:`#{mapped_label_name}`) DETACH DELETE n")
|
112
112
|
end
|
113
113
|
|
114
114
|
# Returns each node to Ruby and calls `destroy`. Be careful, as this can be a very slow operation if you have many nodes. It will generate at least
|
@@ -127,11 +127,15 @@ module ActiveGraph
|
|
127
127
|
@mapped_label_name || label_for_model
|
128
128
|
end
|
129
129
|
|
130
|
+
alias mapped_element_name mapped_label_name
|
131
|
+
|
130
132
|
# @return [ActiveGraph::Label] the label for this class
|
131
133
|
def mapped_label
|
132
134
|
ActiveGraph::Core::Label.new(mapped_label_name)
|
133
135
|
end
|
134
136
|
|
137
|
+
alias mapped_element mapped_label
|
138
|
+
|
135
139
|
def base_class
|
136
140
|
unless self < ActiveGraph::Node
|
137
141
|
fail "#{name} doesn't belong in a hierarchy descending from Node"
|
@@ -160,6 +164,7 @@ module ActiveGraph
|
|
160
164
|
|
161
165
|
self.mapped_label_name = name
|
162
166
|
end
|
167
|
+
|
163
168
|
# rubocop:enable Naming/AccessorMethodName
|
164
169
|
|
165
170
|
private
|
@@ -184,20 +189,18 @@ module ActiveGraph
|
|
184
189
|
end
|
185
190
|
|
186
191
|
def label_for_model
|
187
|
-
|
192
|
+
name.nil? ? object_id.to_s.to_sym : decorated_label_name
|
188
193
|
end
|
189
194
|
|
190
195
|
def decorated_label_name
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
name.to_sym
|
196
|
+
case ActiveGraph::Config[:module_handling]
|
197
|
+
when :demodulize
|
198
|
+
name.demodulize
|
199
|
+
when Proc
|
200
|
+
ActiveGraph::Config[:module_handling].call name
|
201
|
+
else
|
202
|
+
name
|
203
|
+
end.to_sym
|
201
204
|
end
|
202
205
|
end
|
203
206
|
end
|