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.
@@ -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