active-orient 0.79 → 0.80
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/.graphs.txt.swp +0 -0
- data/Gemfile +2 -6
- data/README.md +29 -27
- data/VERSION +1 -1
- data/active-orient.gemspec +4 -3
- data/bin/active-orient-console +18 -6
- data/changelog.md +60 -0
- data/config/connect.yml +8 -8
- data/examples/books.rb +134 -97
- data/graphs.txt +70 -0
- data/lib/active-orient.rb +2 -0
- data/lib/base.rb +38 -17
- data/lib/base_properties.rb +15 -14
- data/lib/class_utils.rb +11 -50
- data/lib/database_utils.rb +23 -22
- data/lib/init.rb +4 -3
- data/lib/model/custom.rb +7 -4
- data/lib/model/e.rb +6 -0
- data/lib/model/edge.rb +74 -30
- data/lib/model/the_class.rb +181 -131
- data/lib/model/the_record.rb +115 -68
- data/lib/model/vertex.rb +261 -126
- data/lib/other.rb +93 -41
- data/lib/rest/change.rb +23 -20
- data/lib/rest/create.rb +71 -63
- data/lib/rest/delete.rb +80 -64
- data/lib/rest/operations.rb +79 -68
- data/lib/rest/read.rb +42 -24
- data/lib/rest/rest.rb +38 -30
- data/lib/support/conversions.rb +42 -0
- data/lib/support/default_formatter.rb +7 -0
- data/lib/support/errors.rb +41 -0
- data/lib/support/orient.rb +167 -58
- data/lib/support/orientquery.rb +526 -348
- data/lib/support/query.rb +92 -0
- metadata +34 -18
- data/examples/test_commands.rb +0 -97
- data/examples/test_commands_2.rb +0 -59
- data/examples/test_commands_3.rb +0 -55
- data/examples/test_commands_4.rb +0 -33
- data/examples/time_graph.md +0 -162
data/lib/model/custom.rb
CHANGED
@@ -14,13 +14,16 @@ The method does not accept further arguments.
|
|
14
14
|
=end
|
15
15
|
def like operation, order: 'asc'
|
16
16
|
# remove all spaces and split the resulting word
|
17
|
-
|
17
|
+
case operation
|
18
|
+
when Hash
|
19
|
+
p,s = operation.keys.first, operation.values.first
|
20
|
+
else
|
21
|
+
p, s = operation.gsub(/\s+/, "").split("=")
|
22
|
+
end
|
18
23
|
if ["%","*"].include?(s[-1])
|
19
24
|
s.chop!
|
20
25
|
end
|
21
26
|
|
22
|
-
|
23
|
-
query_database q
|
24
|
-
|
27
|
+
query( where: { "#{p}.left(#{s.length})" => s } ,order: { p => order }).execute
|
25
28
|
end
|
26
29
|
end
|
data/lib/model/e.rb
ADDED
data/lib/model/edge.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
class E < ActiveOrient::Model
|
2
2
|
## class methods
|
3
3
|
class << self
|
4
|
+
def naming_convention name=nil
|
5
|
+
name.present? ? name.upcase : ref_name.upcase
|
6
|
+
end
|
7
|
+
|
4
8
|
=begin
|
5
9
|
Establish constrains on Edges
|
6
10
|
|
@@ -8,63 +12,103 @@ After applying this method Edges are uniq!
|
|
8
12
|
|
9
13
|
Creates individual indices for child-classes if applied to the class itself.
|
10
14
|
=end
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
15
|
+
def uniq_index
|
16
|
+
create_property :in, type: :link, linked_class: :V
|
17
|
+
create_property :out, type: :link, linked_class: :V
|
18
|
+
create_index "#{ref_name}_idx", on: [ :in, :out ]
|
19
|
+
end
|
16
20
|
|
17
21
|
=begin
|
18
22
|
Instantiate a new Edge between two Vertices
|
19
23
|
|
24
|
+
Properties can be placed using the :set-directive or simply by adding key: value- parameter-pairs
|
25
|
+
|
26
|
+
if the creation of an edged is not possible, due to constrains (uniq_index), the already
|
27
|
+
connecting edge is returned
|
28
|
+
|
29
|
+
the method is thread safe, if transaction and update_cache are set to false
|
20
30
|
=end
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
def create from:, to: , set: {}, transaction: false, update_cache: false, **attributes
|
32
|
+
return nil if from.blank? || to.blank?
|
33
|
+
set.merge!(attributes)
|
34
|
+
content = set.empty? ? "" : "content #{set.to_orient.to_json}"
|
35
|
+
statement = "CREATE EDGE #{ref_name} from #{from.to_or} to #{to.to_or} #{content}"
|
36
|
+
transaction = true if [:fire, :complete, :run].include?(transaction)
|
37
|
+
ir= db.execute( transaction: transaction, process_error: false ){ statement }
|
38
|
+
if update_cache
|
39
|
+
from.reload! # get last version
|
40
|
+
to.is_a?(Array)? to.each( &:reload! ) : to.reload!
|
41
|
+
end
|
42
|
+
to.is_a?(Array) ? ir : ir.first # return the plain edge, if only one is created
|
43
|
+
rescue RestClient::InternalServerError => e
|
44
|
+
sentence= JSON.parse( e.response)['errors'].last['content']
|
45
|
+
if sentence =~ /found duplicated key/
|
46
|
+
ref_rid = sentence.split.last.expand # return expanded rid
|
47
|
+
else
|
48
|
+
raise
|
49
|
+
end
|
50
|
+
rescue ArgumentError => e
|
51
|
+
logger.error{ "wrong parameters #{keyword_arguments} \n\t\t required: from: , to: , attributes:\n\t\t Edge is NOT created"}
|
52
|
+
end
|
33
53
|
|
34
54
|
=begin
|
35
55
|
Fires a "delete edge" command to the database.
|
36
56
|
|
57
|
+
|
37
58
|
The where statement can be empty ( "" or {}"), then all edges are removed
|
38
59
|
|
39
60
|
The rid-cache is resetted
|
40
61
|
|
62
|
+
|
63
|
+
to_do: Implement :all=> true directive
|
64
|
+
support from: , to: syntax
|
65
|
+
|
41
66
|
:call-seq:
|
42
67
|
delete where:
|
43
68
|
=end
|
44
|
-
|
69
|
+
def delete where:
|
45
70
|
|
46
|
-
|
47
|
-
|
71
|
+
db.execute { "delete edge #{ref_name} #{db.compose_where(where)}" }
|
72
|
+
reset_rid_store
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
def connect dir= "-" , **args # arguments: direction: :both,
|
78
|
+
# count: 1,
|
79
|
+
# # as: nil
|
80
|
+
|
81
|
+
direction = case dir
|
82
|
+
when "-"
|
83
|
+
:both
|
84
|
+
when '->'
|
85
|
+
:out
|
86
|
+
when '<-'
|
87
|
+
:in
|
88
|
+
when Symbol
|
89
|
+
dir
|
90
|
+
end
|
91
|
+
args[:direction] ||= direction
|
92
|
+
|
93
|
+
|
94
|
+
OrientSupport::MatchConnection.new self, **args
|
95
|
+
end
|
48
96
|
|
49
|
-
end
|
50
|
-
|
51
97
|
end # class methods
|
52
98
|
|
53
99
|
### instance methods ###
|
54
100
|
|
55
101
|
=begin
|
56
|
-
|
102
|
+
Deletes the actual ActiveOrient::Model-Edge-Object
|
57
103
|
|
58
|
-
This method overloads the unspecified ActiveOrient::Model#remove-Method
|
59
104
|
=end
|
60
|
-
def remove
|
61
|
-
# remove works on record-level
|
62
|
-
db.delete_edge self
|
63
|
-
end
|
64
105
|
|
106
|
+
def delete
|
107
|
+
db.execute{ "delete edge #{ref_name} #{rrid}" }
|
108
|
+
end
|
65
109
|
def to_human
|
66
|
-
displayed_attributes =
|
67
|
-
"<#{self.class.to_s.demodulize}[#{rrid}]
|
110
|
+
displayed_attributes = attributes.reject{|k,_| [:in, :out].include?(k) }
|
111
|
+
"<#{self.class.to_s.demodulize}[#{rrid}] :.: #{ attributes[:out].rid}->#{displayed_attributes.to_human}->#{attributes[:in].rid}>"
|
68
112
|
end
|
69
113
|
|
70
114
|
end
|
data/lib/model/the_class.rb
CHANGED
@@ -13,7 +13,7 @@ include OrientSupport::Support
|
|
13
13
|
NamingConvention provides a translation from database-names to class-names.
|
14
14
|
|
15
15
|
It can be overwritten to provide different conventions for different classes, eg. Vertexes or edges
|
16
|
-
and to introduce distinct naming-conventions in
|
16
|
+
and to introduce distinct naming-conventions in different namespaces
|
17
17
|
|
18
18
|
To overwrite use
|
19
19
|
class Model # < ActiveOrient::Model[:: ...]
|
@@ -59,7 +59,7 @@ Override to change its behavior
|
|
59
59
|
|
60
60
|
def orientdb_class name:, superclass: nil # :nodoc: # public method: autoload_class
|
61
61
|
|
62
|
-
ActiveOrient.database_classes[name].presence || ActiveOrient::Model
|
62
|
+
ActiveOrient.database_classes[name.to_s].presence || ActiveOrient::Model
|
63
63
|
rescue NoMethodError => e
|
64
64
|
logger.error { "Error in orientdb_class: is ActiveOrient.database_classes initialized ? \n\n\n" }
|
65
65
|
logger.error{ e.backtrace.map {|l| " #{l}\n"}.join }
|
@@ -91,7 +91,7 @@ In fact, the model-files are loaded instead of required.
|
|
91
91
|
Thus, even after recreation of a class (Class.delete_class, ORD.create_class classname)
|
92
92
|
custom methods declared in the model files are present.
|
93
93
|
|
94
|
-
|
94
|
+
If a class is destroyed (i.e. the database class is deleted), the ruby-class and its methods vanish, too.
|
95
95
|
|
96
96
|
The directory specified is expanded by the namespace. The parameter itself is the base-dir.
|
97
97
|
|
@@ -100,32 +100,52 @@ Example:
|
|
100
100
|
model_dir : 'lib/model'
|
101
101
|
searched directory: 'lib/model/hc'
|
102
102
|
|
103
|
+
|
104
|
+
ActiveOrient::Model.modeldir is aimed to be set to the application dir. It may be a String, Pathname or
|
105
|
+
an array of strings or pathnames.
|
106
|
+
|
107
|
+
The parameter `dir` is used internally and by gems to ensure that basic methods are loaded first.
|
108
|
+
|
109
|
+
|
103
110
|
=end
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
111
|
+
def require_model_file dir = nil
|
112
|
+
logger.progname = 'ModelClass#RequireModelFile'
|
113
|
+
# model-dir can either be a string or an array of string or pathnames
|
114
|
+
default = [ActiveOrient::Model.model_dir].flatten
|
115
|
+
# access the default dir's first
|
116
|
+
the_directories = case dir
|
117
|
+
when String, Pathname
|
118
|
+
default.present? ? [dir] + default : [dir]
|
119
|
+
when Array
|
120
|
+
default.present? ? dir + default : dir
|
121
|
+
else
|
122
|
+
default.present? ? default : []
|
123
|
+
end.uniq.compact
|
124
|
+
the_directories.uniq.map do |raw_directory|
|
125
|
+
the_directory = Pathname( raw_directory )
|
108
126
|
if File.exists?( the_directory )
|
109
127
|
model= self.to_s.underscore + ".rb"
|
110
128
|
filename = the_directory + model
|
111
129
|
if File.exists?(filename )
|
112
130
|
if load filename
|
113
|
-
logger.
|
131
|
+
logger.debug{ "#{filename} sucessfully loaded" }
|
114
132
|
self #return_value
|
115
133
|
else
|
116
134
|
logger.error{ "#{filename} load error" }
|
117
135
|
nil #return_value
|
118
136
|
end
|
119
137
|
else
|
120
|
-
logger.
|
138
|
+
logger.debug{ "model-file not present: #{filename} --> skipping" }
|
121
139
|
nil #return_value
|
122
140
|
end
|
123
141
|
else
|
124
|
-
logger.
|
142
|
+
logger.error{ "Directory #{ the_directory } not present " }
|
125
143
|
nil #return_value
|
126
144
|
end
|
145
|
+
end.compact.present? # return true only if at least one model-file is present
|
146
|
+
|
127
147
|
rescue TypeError => e
|
128
|
-
puts "TypeError: #{e.message}"
|
148
|
+
puts "THE CLASS#require_model_file -> TypeError: #{e.message}"
|
129
149
|
puts "Working on #{self.to_s} -> #{self.superclass}"
|
130
150
|
puts "Class_hierarchy: #{orientdb.class_hierarchy.inspect}."
|
131
151
|
print e.backtrace.join("\n")
|
@@ -133,6 +153,12 @@ Example:
|
|
133
153
|
#
|
134
154
|
end
|
135
155
|
|
156
|
+
|
157
|
+
# creates an inherent class
|
158
|
+
def create_class *c
|
159
|
+
orientdb.create_class( *c ){ self }
|
160
|
+
end
|
161
|
+
|
136
162
|
########## CREATE ############
|
137
163
|
|
138
164
|
=begin
|
@@ -140,7 +166,7 @@ Universal method to create a new record.
|
|
140
166
|
It's overloaded to create specific kinds, eg. edge and vertex and is called only for abstract classes
|
141
167
|
|
142
168
|
Example:
|
143
|
-
|
169
|
+
V.create_class :test
|
144
170
|
Test.create string_attribute: 'a string', symbol_attribute: :a_symbol, array_attribute: [34,45,67]
|
145
171
|
Test.create link_attribute: Test.create( :a_new_attribute => 'new' )
|
146
172
|
|
@@ -157,49 +183,61 @@ Example:
|
|
157
183
|
end
|
158
184
|
end
|
159
185
|
|
186
|
+
|
187
|
+
# returns a OrientSupport::OrientQuery
|
188
|
+
def query **args
|
189
|
+
OrientSupport::OrientQuery.new( **( {from: self}.merge args))
|
190
|
+
end
|
191
|
+
|
160
192
|
=begin
|
161
|
-
Creates or updates
|
193
|
+
Creates or updates records.
|
162
194
|
Parameter:
|
163
195
|
- set: A hash of attributes to insert or update unconditionally
|
164
196
|
- where: A string or hash as condition which should return just one record.
|
165
197
|
|
166
198
|
The where-part should be covered with an unique-index.
|
167
199
|
|
168
|
-
|
200
|
+
|
201
|
+
returns the affected record, if the where-condition is set properly.
|
202
|
+
Otherwise upsert acts as »update« and returns all updated records (as array).
|
169
203
|
=end
|
170
|
-
def upsert set: nil, where:
|
204
|
+
def upsert set: nil, where: , **args
|
171
205
|
set = where if set.nil?
|
172
|
-
|
206
|
+
query( **args.merge( kind: :upsert, set: set, where: where )).execute(reduce: true){|y| y[:$current].reload!}
|
173
207
|
end
|
174
208
|
=begin
|
175
|
-
Sets a value to certain attributes, overwrites existing entries, creates new attributes if
|
209
|
+
Sets a value to certain attributes, overwrites existing entries, creates new attributes if necessary
|
176
210
|
|
177
|
-
|
178
|
-
IB::Account.update_all where: "account containsText 'F'", set:{ connected: false }
|
211
|
+
returns the count of affected records
|
179
212
|
|
180
|
-
|
213
|
+
IB::Account.update connected: false
|
214
|
+
IB::Account.update where: "account containsText 'F'", set:{ connected: false }
|
215
|
+
# or
|
216
|
+
IB::Account.update connected: false, where: "account containsText 'F'"
|
181
217
|
=end
|
182
218
|
|
183
|
-
def
|
184
|
-
|
185
|
-
set.merge! arg
|
186
|
-
end
|
187
|
-
db.update_records self, set: set, where: where
|
188
|
-
|
189
|
-
end
|
190
|
-
#
|
191
|
-
# removes a property from the collection (where given) or the entire class
|
192
|
-
def remove attribute, where:{}
|
193
|
-
db.update_records self, remove: attribute, where: where
|
219
|
+
def update! where: nil , set: {}, **arg
|
220
|
+
query( kind: :update!, set: set.merge(arg), where: where).execute(reduce: true){|y| y[:count]}
|
194
221
|
end
|
195
222
|
|
223
|
+
alias update_all update!
|
224
|
+
|
225
|
+
|
226
|
+
# same as update!, but returns a list of updated records
|
227
|
+
def update where: , set: {}, **arg
|
228
|
+
# In OrientDB V.3 the database only returns the affected rid's
|
229
|
+
# We have to update the contents manually, this is done in the execute-block
|
230
|
+
query( kind: :update, set: set.merge(arg), where: where).execute{|y| y[:$current].reload!}
|
231
|
+
end
|
232
|
+
|
196
233
|
=begin
|
197
|
-
Create a Property in the Schema of the Class and
|
234
|
+
Create a Property in the Schema of the Class and optionally create an automatic index
|
198
235
|
|
199
236
|
Examples:
|
200
237
|
|
201
|
-
create_property :customer_id, type: integer, index: :unique
|
238
|
+
create_property :customer_id, type: :integer, index: :unique
|
202
239
|
create_property( :name, type: :string ) { :unique }
|
240
|
+
create_property( :name, type: :string ) { name: 'some_index', on: :automatic, type: :unique }
|
203
241
|
create_property :in, type: :link, linked_class: V (used by edges)
|
204
242
|
|
205
243
|
:call-seq: create_property(field (required),
|
@@ -207,7 +245,7 @@ Examples:
|
|
207
245
|
linked_class: nil
|
208
246
|
|
209
247
|
supported types:
|
210
|
-
:bool :double :datetime
|
248
|
+
:bool :double :datetime = :date :float :decimal
|
211
249
|
:embedded_list = :list :embedded_map = :map :embedded_set = :set
|
212
250
|
:int :integer :link_list :link_map :link_set
|
213
251
|
|
@@ -231,6 +269,7 @@ a `linked_class:` parameter can be specified. Argument is the OrientDB-Class-Con
|
|
231
269
|
:bool => "BOOLEAN",
|
232
270
|
:double => "BYTE",
|
233
271
|
:datetime => "DATE",
|
272
|
+
:date => "DATE",
|
234
273
|
:float => "FLOAT",
|
235
274
|
:decimal => "DECIMAL",
|
236
275
|
:embedded_list => "EMBEDDEDLIST",
|
@@ -284,6 +323,25 @@ a `linked_class:` parameter can be specified. Argument is the OrientDB-Class-Con
|
|
284
323
|
|
285
324
|
|
286
325
|
# Add an Index
|
326
|
+
#
|
327
|
+
# Parameters:
|
328
|
+
# name (string / symbol),
|
329
|
+
# [ on: :automatic / single Column, Array of Columns,
|
330
|
+
# [ type: :unique, :nonunique, :dictionary,:fulltext, {other supported index-types} ]]
|
331
|
+
#
|
332
|
+
# Default:
|
333
|
+
# on: :automatic
|
334
|
+
# type: :unique
|
335
|
+
#
|
336
|
+
# Example
|
337
|
+
#
|
338
|
+
# ORD.create_vertex_class :pagination
|
339
|
+
# Pagination.create_property :col1 , type: :string
|
340
|
+
# Pagination.create_property :col2, type: :integer
|
341
|
+
# Pagination.create_property :col3, type: :string
|
342
|
+
# Pagination.create_property :col4, type: :integer
|
343
|
+
# Pagination.create_index :composite, :on => [:col1, :col2, :col3], type: 'dictionary'
|
344
|
+
|
287
345
|
def create_index name, **attributes
|
288
346
|
orientdb.create_index self, name: name, **attributes
|
289
347
|
end
|
@@ -291,6 +349,30 @@ a `linked_class:` parameter can be specified. Argument is the OrientDB-Class-Con
|
|
291
349
|
# list all Indexes
|
292
350
|
def indexes
|
293
351
|
properties[:indexes]
|
352
|
+
end
|
353
|
+
|
354
|
+
|
355
|
+
def migrate_property property, to: , linked_class: nil, via: 'tzr983'
|
356
|
+
if linked_class.nil?
|
357
|
+
create_property via, type: to
|
358
|
+
else
|
359
|
+
create_property via, type: to, linked_class: linked_class
|
360
|
+
end
|
361
|
+
# my_count = query.kind(:update!).set( "#{via} = #{property} ").execute(reduce: true){|c| c[:count]}
|
362
|
+
# logger.info{" migrate property: #{count} records prosessed"}
|
363
|
+
all.each{ |r| r.update set:{ via => r[property.to_sym] }}
|
364
|
+
nullify = query.kind(:update!).set( property: nil ).execute(reduce: true){|c| c[:count]}
|
365
|
+
# raise "migrate property: count of erased items( #{nullify} differs from total count (#{my_count}) " if nullify != my_count
|
366
|
+
db.execute{" alter property #{ref_name}.#{via} name '#{property}' "}
|
367
|
+
logger.info{ "successfully migrated #{property} to #{:to} " }
|
368
|
+
|
369
|
+
|
370
|
+
|
371
|
+
|
372
|
+
|
373
|
+
|
374
|
+
|
375
|
+
|
294
376
|
end
|
295
377
|
########## GET ###############
|
296
378
|
|
@@ -311,31 +393,35 @@ a `linked_class:` parameter can be specified. Argument is the OrientDB-Class-Con
|
|
311
393
|
# get all the elements of the class
|
312
394
|
|
313
395
|
def all
|
314
|
-
|
396
|
+
query.execute
|
315
397
|
end
|
316
398
|
|
317
399
|
# get the first element of the class
|
318
400
|
|
319
|
-
def first
|
320
|
-
|
321
|
-
|
401
|
+
def first **args
|
402
|
+
query( **( { order: "@rid" , limit: 1 }.merge args)).execute(reduce: true)
|
403
|
+
end
|
404
|
+
# db.get_records(from: self, where: where, limit: 1).pop
|
405
|
+
#end
|
322
406
|
|
323
407
|
# get the last element of the class
|
408
|
+
def last **args
|
409
|
+
query( **( { order: {"@rid" => 'desc'} , limit: 1 }.merge args)).execute(reduce: true)
|
410
|
+
end
|
324
411
|
|
325
|
-
def last where: {}
|
326
|
-
db.get_records(from: self, where: where, order: {"@rid" => 'desc'}, limit: 1).pop
|
327
|
-
end
|
328
412
|
# Used to count of the elements in the class
|
329
|
-
|
413
|
+
#
|
414
|
+
# Examples
|
415
|
+
# TestClass.count where: 'last_access is NULL' # only records where 'last_access' is not set
|
416
|
+
# TestClass.count # all records
|
330
417
|
def count **args
|
331
|
-
|
418
|
+
query( **( { projection: 'COUNT(*)' }.merge args )).execute(reduce: true){|x| x[:"COUNT(*)"]}
|
332
419
|
end
|
333
420
|
|
334
421
|
# Get the properties of the class
|
335
422
|
|
336
423
|
def properties
|
337
424
|
object = orientdb.get_class_properties self
|
338
|
-
#HashWithIndifferentAccess.new :properties => object['properties'], :indexes => object['indexes']
|
339
425
|
{:properties => object['properties'], :indexes => object['indexes']}
|
340
426
|
end
|
341
427
|
alias get_class_properties properties
|
@@ -348,7 +434,7 @@ a `linked_class:` parameter can be specified. Argument is the OrientDB-Class-Con
|
|
348
434
|
|
349
435
|
=begin
|
350
436
|
»GetRecords« uses the REST-Interface to query the database. The alternative »QueryDatabase« submits
|
351
|
-
the query via
|
437
|
+
the query via Execute.
|
352
438
|
|
353
439
|
Both methods rely on OrientSupport::OrientQuery and its capacity to support complex query-builds.
|
354
440
|
The method requires a hash of arguments. The following keys are supported:
|
@@ -357,8 +443,8 @@ The method requires a hash of arguments. The following keys are supported:
|
|
357
443
|
|
358
444
|
SQL-Queries use »select« to specify a projection (ie. `select sum(a), b+5 as z from class where ...`)
|
359
445
|
|
360
|
-
In ruby »select« is a method of enumeration. To specify
|
361
|
-
we use »projection«, which
|
446
|
+
In ruby »select« is a method of enumeration. To specify what to »select« from in the query-string
|
447
|
+
we use »projection«, which accepts different arguments
|
362
448
|
|
363
449
|
projection: a_string --> inserts the sting as it appears
|
364
450
|
projection: an OrientSupport::OrientQuery-Object --> performs a sub-query and uses the result for further querying though the given parameters.
|
@@ -413,100 +499,59 @@ tested prior to the method-call. The OrientQuery-Object is then provided with th
|
|
413
499
|
alias get_documents get_records
|
414
500
|
|
415
501
|
|
416
|
-
def custom_where search_string
|
417
|
-
q = OrientSupport::OrientQuery.new from: self, where: search_string
|
418
|
-
#puts q.compose
|
419
|
-
query_database q
|
420
|
-
end
|
421
502
|
=begin
|
422
503
|
Performs a query on the Class and returns an Array of ActiveOrient:Model-Records.
|
423
504
|
|
505
|
+
Fall-back method, is overloaded by Vertex.where
|
506
|
+
|
507
|
+
Is aliased by »custom_where»
|
508
|
+
|
424
509
|
Example:
|
425
510
|
Log.where priority: 'high'
|
426
|
-
-->
|
511
|
+
--> submitted database-request: query/hc_database/sql/select from Log where priority = 'high'/-1
|
427
512
|
=> [ #<Log:0x0000000480f7d8 @metadata={ ... }, ...
|
428
513
|
|
429
|
-
|
514
|
+
Multiple arguments are joined via "and" eg:
|
430
515
|
Aktie.where symbol: 'TSL, exchange: 'ASX'
|
431
516
|
---> select from aktie where symbol = 'TLS' and exchange = 'ASX'
|
432
517
|
|
433
|
-
|
434
|
-
Where performs a »match-Query« that returns only links to the queries records.
|
435
|
-
These are autoloaded (and reused from the cache). If changed database-records should be obtained,
|
436
|
-
custom_query should be used. It performs a "select form class where ... " query which returns records
|
437
|
-
instead of links.
|
438
|
-
|
439
|
-
Property.custom_where( "'Hamburg' in exchanges.label")
|
440
|
-
|
441
518
|
=end
|
442
519
|
|
443
520
|
def where *attributes
|
444
|
-
|
445
|
-
|
446
|
-
# the block contains a result-record :
|
447
|
-
#<ActiveOrient::Model:0x0000000003972e00
|
448
|
-
# @metadata={:type=>"d", :class=>nil, :version=>0, :fieldTypes=>"test_models=x"}, @d=nil,
|
449
|
-
# @attributes={:test_models=>"#29:3", :created_at=>Thu, 28 Mar 2019 10:43:51 +0000}>]
|
450
|
-
# ^...........° -> classname.pluralize
|
451
|
-
query_database( query, set_from: false){| record | record.is_a?(ActiveOrient::Model) ? record : record.send( self.classnamepluralize.to_sym ) }
|
521
|
+
q= OrientSupport::OrientQuery.new where: attributes
|
522
|
+
query_database( q)
|
452
523
|
end
|
453
|
-
=begin
|
454
|
-
Performs a Match-Query
|
455
524
|
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
Industry.match where:{ name: "Communications" }
|
460
|
-
=> #<ActiveOrient::Model::Query:0x00000004309608 @metadata={"type"=>"d", "class"=>nil, "version"=>0, "fieldTypes"=>"Industries=x"}, @attributes={"Industries"=>"#21:1", (...)}>
|
461
|
-
|
462
|
-
The attributes are the return-Values of the Match-Query. Unless otherwise noted, the pluralized Model-Classname is used as attribute in the result-set.
|
463
|
-
|
464
|
-
I.match( where: { name: 'Communications' }).first.Industries
|
465
|
-
|
466
|
-
is the same then
|
467
|
-
Industry.where name: "Communications"
|
468
|
-
|
469
|
-
|
470
|
-
The Match-Query uses this result-set as start for subsequent queries on connected records.
|
471
|
-
These connections are defined in the Block
|
472
|
-
|
473
|
-
var = Industry.match do | query |
|
474
|
-
query.connect :in, count: 2, as: 'Subcategories'
|
475
|
-
puts query.to_s # print the query before sending it to the database
|
476
|
-
query # important: block has to return the query
|
477
|
-
end
|
478
|
-
=> MATCH {class: Industry, as: Industries} <-- {} <-- { as: Subcategories } RETURN Industries, Subcategories
|
525
|
+
alias custom_where where
|
526
|
+
=begin
|
527
|
+
QueryDatabase sends the Query directly to the database.
|
479
528
|
|
480
|
-
The
|
529
|
+
The query returns a hash if a result set is expected
|
530
|
+
select {something} as {result} (...)
|
531
|
+
leads to
|
532
|
+
[ { :{result} => {result of query} } ]
|
481
533
|
|
482
|
-
|
534
|
+
It can be modified further by passing a block, ie.
|
483
535
|
|
484
|
-
=
|
536
|
+
q = OrientSupport::OrientQuery.new( from: :base )
|
537
|
+
.projection( 'first_list[5].second_list[9] as second_list' )
|
538
|
+
.where( label: 9 )
|
485
539
|
|
486
|
-
|
487
|
-
query= OrientSupport::OrientQuery.new kind: :match, start:{ class: self.classname }
|
488
|
-
query.match_statements[0].where = where unless where.empty?
|
489
|
-
if block_given?
|
490
|
-
query_database yield(query), set_from: false
|
491
|
-
else
|
492
|
-
send :where, where
|
493
|
-
end
|
540
|
+
q.to_s => 'select first_list[5].second_list[9] as second_list from base where label = 9 '
|
494
541
|
|
495
|
-
|
542
|
+
second_list = Base.query_database( q ){|x| x[:second_list]}.first
|
496
543
|
|
497
544
|
|
498
|
-
|
499
|
-
QueryDatabase sends the Query directly to the database.
|
545
|
+
The query returns (a list of) documents of type ActiveOrient::Model if a document is queried i.e.
|
500
546
|
|
501
|
-
|
547
|
+
q = OrientSupport::OrientQuery.new from: :base
|
548
|
+
q.projection 'expand( first_list[5].second_list[9])' #note: no 'as' statement
|
549
|
+
result2 = Base.query_database( q ).first
|
550
|
+
=> #<SecondList:0x000000000284e840 @metadata={}, @d=nil, @attributes={:zobel=>9, "@class"=>"second_list"}>
|
551
|
+
|
502
552
|
|
503
|
-
The result can be modified further by passing a block.
|
504
|
-
This is helpful, if a match-statement is used and the records should be autoloaded:
|
505
553
|
|
506
|
-
result = query_database(query, set_from: false){| record | record[ self.classname.pluralize ] }
|
507
554
|
|
508
|
-
This autoloads (fetches from the cache/ or database) the attribute self.classname.pluralize (taken from method: where )
|
509
|
-
|
510
555
|
|
511
556
|
query_database is used on model-level and submits
|
512
557
|
select (...) from class
|
@@ -517,16 +562,14 @@ query_database is used on model-level and submits
|
|
517
562
|
=end
|
518
563
|
|
519
564
|
def query_database query, set_from: true
|
520
|
-
|
521
|
-
|
522
|
-
result = db.execute
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
result
|
529
|
-
end
|
565
|
+
# note: the parameter is not used anymore
|
566
|
+
query.from self if query.is_a?(OrientSupport::OrientQuery) && query.from.nil?
|
567
|
+
result = db.execute{ query.to_s }
|
568
|
+
result = if block_given?
|
569
|
+
result.is_a?(Array) ? result.map{|x| yield(x) } : yield(result)
|
570
|
+
else
|
571
|
+
result
|
572
|
+
end
|
530
573
|
if result.is_a? Array
|
531
574
|
OrientSupport::Array.new work_on: self, work_with: result
|
532
575
|
else
|
@@ -550,11 +593,18 @@ query_database is used on model-level and submits
|
|
550
593
|
alias delete_document delete_record
|
551
594
|
|
552
595
|
# Query the database and delete the records of the resultset
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
596
|
+
#
|
597
|
+
# Returns the count of datasets effected
|
598
|
+
def delete_records where: {} , **args
|
599
|
+
if args[:all] == true
|
600
|
+
where = {}
|
601
|
+
else
|
602
|
+
where.merge!(args) if where.is_a?(Hash)
|
603
|
+
return 0 if where.empty?
|
604
|
+
end
|
605
|
+
orientdb.delete_records( self, where: where ).count
|
606
|
+
end
|
607
|
+
alias delete delete_records
|
558
608
|
|
559
609
|
|
560
610
|
|
@@ -598,7 +648,7 @@ To get their value you can do:
|
|
598
648
|
See http://orientdb.com/docs/2.1/SQL-Alter-Property.html
|
599
649
|
=end
|
600
650
|
|
601
|
-
def alter_property property
|
651
|
+
def alter_property property, attribute: "DEFAULT", alteration: # :nodoc:
|
602
652
|
orientdb.alter_property self, property: property, attribute: attribute, alteration: alteration
|
603
653
|
end
|
604
654
|
|