active-orient 0.79 → 0.80

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- p, s = operation.gsub(/\s+/, "").split("=")
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
- q = OrientSupport::OrientQuery.new where: { "#{p}.left(#{s.length})" => s } ,order: { p => order }
23
- query_database q
24
-
27
+ query( where: { "#{p}.left(#{s.length})" => s } ,order: { p => order }).execute
25
28
  end
26
29
  end
@@ -0,0 +1,6 @@
1
+ class E #< ActiveOrient::Model
2
+ def self.naming_convention name=nil
3
+ name.present? ? name.upcase : ref_name.upcase
4
+ end
5
+ end
6
+
@@ -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
- def uniq_index
12
- create_property :in, type: :link, linked_class: :V
13
- create_property :out, type: :link, linked_class: :V
14
- create_index "#{ref_name}_idx", on: [ :in, :out ]
15
- end
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
- def create from:, to: , attributes: {}, transaction: false
22
- return nil if from.blank? || to.blank?
23
- statement = "CREATE EDGE #{ref_name} from #{from.to_or} to #{to.to_or}"
24
- transaction = true if [:fire, :complete, :run].include?(transaction)
25
- ir= db.execute( transaction: transaction ){ statement }
26
- from.reload! # get last version
27
- to.is_a?(Array)? to.each( &:reload! ) : to.reload!
28
- ir
29
-
30
- rescue ArgumentError => e
31
- logger.error{ "wrong parameters #{keyword_arguments} \n\t\t required: from: , to: , attributes:\n\t\t Edge is NOT created"}
32
- end
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
- def delete where:
69
+ def delete where:
45
70
 
46
- db.execute { "delete edge #{ref_name} #{db.compose_where(where)}" }
47
- reset_rid_store
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
- Removes the actual ActiveOrient::Model-Edge-Object
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 = content_attributes.reject{|k,_| [:in, :out].include?(k) }
67
- "<#{self.class.to_s.demodulize}[#{rrid}] -i-> ##{ attributes[:in].rid} #{displayed_attributes.to_human} -o-> #{out.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
@@ -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 differrent namespaces
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
- Required modelfiles are gone, if the class is destroyed.
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
- def require_model_file the_directory = nil
105
- logger.progname = 'ModelClass#RequireModelFile'
106
- the_directory = Pathname( the_directory.presence || ActiveOrient::Model.model_dir ) rescue nil # the_directory is a Pathname
107
- return nil if the_directory.nil?
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.info{ "#{filename} sucessfully loaded" }
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.info{ "model-file not present: #{filename}" }
138
+ logger.debug{ "model-file not present: #{filename} --> skipping" }
121
139
  nil #return_value
122
140
  end
123
141
  else
124
- logger.info{ "Directory #{ the_directory } not present " }
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
- ORD.create_class :test
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 a record.
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
- returns the affected record
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
- db.upsert self, set: set, where: where
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 nessesary
209
+ Sets a value to certain attributes, overwrites existing entries, creates new attributes if necessary
176
210
 
177
- IB::Account.update_all connected: false
178
- IB::Account.update_all where: "account containsText 'F'", set:{ connected: false }
211
+ returns the count of affected records
179
212
 
180
- **note: By calling UpdateAll, all records of the Class previously stored in the rid-cache are removed from the cache. Thus autoload gets the updated records.
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 update_all where: {} , set: {}, **arg
184
- if where.empty?
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 optionaly create an automatic index
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 :float :decimal
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
- db.get_records from: self
396
+ query.execute
315
397
  end
316
398
 
317
399
  # get the first element of the class
318
400
 
319
- def first where: {}
320
- db.get_records(from: self, where: where, limit: 1).pop
321
- end
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
- orientdb.count from: self, **args
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 Batch.
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 anything etween »select« and »from« in the query-string
361
- we use »projection«, which acceps different arguments
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
- --> submited database-request: query/hc_database/sql/select from Log where priority = 'high'/-1
511
+ --> submitted database-request: query/hc_database/sql/select from Log where priority = 'high'/-1
427
512
  => [ #<Log:0x0000000480f7d8 @metadata={ ... }, ...
428
513
 
429
- Multible arguments are joined via "and" eg
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
- query= OrientSupport::OrientQuery.new kind: :match, start:{ class: self.classname }
445
- query.match_statements[0].where = attributes unless attributes.empty?
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
- The Query starts at the given ActiveOrient::Model-Class. The where-cause narrows the sample to certain
457
- records. In the simplest version this can be returned:
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 result-set has two attributes: Industries and Subcategories, pointing to the filtered datasets.
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
- By using subsequent »connect« and »statement« method-calls even complex Match-Queries can be clearly constructed.
534
+ It can be modified further by passing a block, ie.
483
535
 
484
- =end
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
- def match where: {}
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
- end
542
+ second_list = Base.query_database( q ){|x| x[:second_list]}.first
496
543
 
497
544
 
498
- =begin
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
- The result is not nessessary an Object of the Class.
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
- query.from self if set_from && query.is_a?(OrientSupport::OrientQuery) && query.from.nil?
521
- sql_cmd = -> (command) {{ type: "cmd", language: "sql", command: command }}
522
- result = db.execute do
523
- query.to_s # sql_cmd[query.to_s]
524
- end
525
- if block_given?
526
- result.is_a?(Array)? result.map{|x| yield x } : yield(result)
527
- else
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
- def delete_records where: {}
555
- orientdb.delete_records self, where: where
556
- end
557
- alias delete_documents delete_records
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:, attribute: "DEFAULT", alteration: # :nodoc:
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