active-orient 0.4 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Gemfile +8 -3
  4. data/Guardfile +12 -4
  5. data/README.md +221 -201
  6. data/VERSION +1 -1
  7. data/active-orient.gemspec +3 -2
  8. data/bin/active-orient-console +35 -0
  9. data/config/boot.rb +84 -16
  10. data/config/config.yml +10 -0
  11. data/config/connect.yml +6 -2
  12. data/create_project +19 -0
  13. data/examples/books.rb +86 -39
  14. data/examples/createTime.rb +91 -0
  15. data/examples/streets.rb +85 -84
  16. data/examples/test_commands.rb +92 -0
  17. data/examples/test_commands_2.rb +54 -0
  18. data/examples/test_commands_3.rb +48 -0
  19. data/examples/test_commands_4.rb +28 -0
  20. data/examples/time_graph/Gemfile +21 -0
  21. data/examples/time_graph/Guardfile +26 -0
  22. data/examples/time_graph/README.md +129 -0
  23. data/examples/time_graph/bin/active-orient-console +35 -0
  24. data/examples/time_graph/config/boot.rb +119 -0
  25. data/examples/time_graph/config/config.yml +8 -0
  26. data/examples/time_graph/config/connect.yml +17 -0
  27. data/examples/time_graph/config/init_db.rb +59 -0
  28. data/examples/time_graph/createTime.rb +51 -0
  29. data/examples/time_graph/lib/createTime.rb +82 -0
  30. data/examples/time_graph/model/day_of.rb +3 -0
  31. data/examples/time_graph/model/e.rb +6 -0
  32. data/examples/time_graph/model/edge.rb +53 -0
  33. data/examples/time_graph/model/monat.rb +19 -0
  34. data/examples/time_graph/model/stunde.rb +16 -0
  35. data/examples/time_graph/model/tag.rb +29 -0
  36. data/examples/time_graph/model/time_base.rb +6 -0
  37. data/examples/time_graph/model/time_of.rb +4 -0
  38. data/examples/time_graph/model/v.rb +3 -0
  39. data/examples/time_graph/model/vertex.rb +32 -0
  40. data/examples/time_graph/spec/lib/create_time_spec.rb +50 -0
  41. data/examples/time_graph/spec/rest_helper.rb +37 -0
  42. data/examples/time_graph/spec/spec_helper.rb +46 -0
  43. data/lib/active-orient.rb +56 -6
  44. data/lib/base.rb +149 -147
  45. data/lib/base_properties.rb +40 -41
  46. data/lib/class_utils.rb +301 -0
  47. data/lib/database_utils.rb +97 -0
  48. data/lib/init.rb +35 -0
  49. data/lib/java-api.rb +437 -0
  50. data/lib/jdbc.rb +211 -0
  51. data/lib/model/edge.rb +53 -0
  52. data/lib/model/model.rb +77 -0
  53. data/lib/model/the_class.rb +480 -0
  54. data/lib/model/the_record.rb +310 -0
  55. data/lib/model/vertex.rb +32 -0
  56. data/lib/orient.rb +113 -50
  57. data/lib/orientdb_private.rb +48 -0
  58. data/lib/other.rb +280 -0
  59. data/lib/query.rb +71 -73
  60. data/lib/rest/change.rb +124 -0
  61. data/lib/rest/create.rb +474 -0
  62. data/lib/rest/delete.rb +133 -0
  63. data/lib/rest/operations.rb +150 -0
  64. data/lib/rest/read.rb +150 -0
  65. data/lib/rest/rest.rb +111 -0
  66. data/lib/rest_disabled.rb +24 -0
  67. data/lib/support.rb +387 -296
  68. data/old_lib_functions/two_general_class.rb +139 -0
  69. data/usecase.md +49 -36
  70. data/usecase_oo.md +59 -0
  71. metadata +73 -9
  72. data/lib/model.rb +0 -461
  73. data/lib/rest.rb +0 -1036
  74. data/test.rb +0 -4
@@ -0,0 +1,24 @@
1
+ =begin #nodoc#
2
+ If properties are allocated on class-level, they can be preinitialized using
3
+ this method.
4
+ This is disabled for now, because it does not seem nessesary
5
+ =end
6
+
7
+ def preallocate_class_properties o_class
8
+ p= get_class_properties( o_class )['properties']
9
+ unless p.nil? || p.blank?
10
+ predefined_attributes = p.map do | property |
11
+ [ property['name'] ,
12
+ case property['type']
13
+ when 'LINKMAP'
14
+ Array.new
15
+ when 'STRING'
16
+ ''
17
+ else
18
+ nil
19
+ end ]
20
+ end.to_h
21
+ else
22
+ {}
23
+ end
24
+ end
@@ -1,347 +1,438 @@
1
- class String
2
- def to_classname
3
- if self[0] =='$'
4
- self[1..-1]
5
- else
6
- self.camelize
7
- end
8
- end
9
- def to_orient
10
- self.gsub /%/, '(percent)'
1
+ require 'active_support/inflector'
2
+ module OrientSupport
3
+ module Support
11
4
 
12
- end
13
- def rid?
14
- self =~ /\A[#]{,1}[0-9]{1,}:[0-9]{1,}\z/
15
- end
16
- def from_orient
17
- if rid?
18
- ActiveOrient::Model.autoload_object self
19
- else
20
- self
21
- end
5
+ =begin
6
+ supports
7
+ where: 'string'
8
+ where: { property: 'value', property: value, ... }
9
+ where: ['string, { property: value, ... }, ... ]
10
+ Used by update and select
11
+ =end
12
+
13
+ ## ORD.compose_where 'z=34', {u:6}
14
+ # => "where z=34 and u = 6"
15
+ #
16
+ def compose_where *arg
17
+ arg = arg.flatten
18
+ return "" if arg.blank? || arg.size == 1 && arg.first.blank?
19
+ "where " + arg.map do |issue|
20
+ case issue
21
+ when String
22
+ issue
23
+ else
24
+ generate_sql_list issue
25
+ end
26
+ end.join(' and ')
22
27
  end
23
- ## this enables the universal use of an rid-string as pseudonym for a ActiveOrient::Model
24
- alias :reload! from_orient
25
- end
26
- class NilClass
27
- def to_orient
28
- self
29
- end
30
- end
31
- class Symbol
32
- def to_orient
33
- self.to_s.to_orient
34
- end
35
- def from_orient
36
- self
37
- end
38
- end
39
28
 
40
- class Numeric
41
- def from_orient
42
- self
43
- end
44
- def to_orient
45
- self
29
+ =begin
30
+ designs a list of "Key = Value" pairs combined by "and" or the fillword provided by the block
31
+ ORD.generate_sql_list where: 25 , upper: '65'
32
+ => "where = 25 and upper = '65'"
33
+ ORD.generate_sql_list( con_id: 25 , symbol: :G) { ',' }
34
+ => "con_id = 25 , symbol = 'G'"
35
+ =end
36
+ def generate_sql_list attributes = {}
37
+ fill = block_given? ? yield : 'and'
38
+ attributes.map do |key, value|
39
+ case value
40
+ when ActiveOrient::Model
41
+ "#{key} = #{value.rrid}"
42
+ when Numeric
43
+ "#{key} = #{value}"
44
+ when Array
45
+ "#{key}= #{value.to_orient}"
46
+ when Date
47
+ "#{key} = date(\'#{value.to_s}\',\'yyyy-MM-dd\')"
48
+ else # String, Symbol, Time, Trueclass, Falseclass ...
49
+ "#{key} = \'#{value.to_s}\'"
50
+ end
51
+ end.join(" #{fill} ")
52
+ end
46
53
  end
47
- end
48
54
 
49
- class Time
50
- def from_orient
51
- self
52
- end
53
- def to_orient
54
- self
55
- end
56
- end
57
- class Date
58
- def from_orient
59
- self
60
- end
61
- def to_orient
62
- self
63
- end
64
- end
65
55
 
66
- class TrueClass
67
- def from_orient
68
- self
69
- end
70
- def to_orient
71
- self
72
- end
73
- end
74
- class FalseClass
75
- def from_orient
76
- self
77
- end
78
- def to_orient
79
- self
80
- end
81
- end
56
+ class MatchConnection
57
+ attr_accessor :as
58
+ def initialize edge: nil, direction: :both, as: nil, count: 1
59
+ @edge = edge
60
+ @direction = direction # may be :both, :in, :out
61
+ @as = as
62
+ @count = count
63
+ end
82
64
 
83
- class Array
84
- def to_orient
85
- map &:to_orient
65
+ def direction= dir
66
+ @direction = dir
86
67
  end
87
- def from_orient
88
- map &:from_orient
68
+
69
+
70
+ def direction
71
+ fillup = @edge.present? ? @edge : ''
72
+ case @direction
73
+ when :both
74
+ " -#{fillup}- "
75
+ when :in
76
+ " <-#{fillup}- "
77
+ when :out
78
+ " -#{fillup}-> "
79
+ end
80
+
89
81
  end
90
- end
91
- class Hash #WithIndifferentAccess
92
- def from_orient
93
- substitute_hash = HashWithIndifferentAccess.new
94
- keys.each{ |k| puts self[k].inspect }
95
- keys.each{| k | substitute_hash[k] = self[k].from_orient }
96
- substitute_hash
97
82
 
98
- end
99
- def to_orient
100
- substitute_hash = Hash.new
101
- keys.each{| k | substitute_hash[k] = self[k].to_orient }
102
- substitute_hash
83
+ def compose
84
+ ministatement = @as.present? ? "{ as: #{@as} } " : ""
85
+ (1 .. @count).map{|x| direction }.join("{}") << ministatement
103
86
 
87
+ end
88
+
104
89
  end
105
90
 
106
- def nested_under_indifferent_access
107
- HashWithIndifferentAccess.new self
91
+ class MatchStatement
92
+ include Support
93
+ attr_accessor :as
94
+ attr_accessor :where
95
+ def initialize match_class=nil, **args
96
+ @misc = []
97
+ @where = []
98
+ @while = []
99
+ @maxdepth = 0
100
+ @as = nil
101
+
102
+
103
+ @match_class = match_class
104
+ @as = match_class.pluralize if match_class.is_a? String
105
+
106
+ args.each do |k, v|
107
+ case k
108
+ when :as
109
+ @as = v
110
+ when :while
111
+ @while << v
112
+ when :where
113
+ @where << v
114
+ when :class
115
+ @match_class = v
116
+ @as = v.pluralize
117
+ else
118
+ self.send k, v
119
+ end
120
+ end
121
+ end
122
+
123
+ def while_s
124
+ compose_where( @while ).gsub( /where/, 'while:(' )<< ")" unless @while.blank?
125
+ end
126
+
127
+ def match_alias
128
+ "as: #{@as }"
129
+ end
130
+ def where_s
131
+ compose_where( @where ).gsub( /where/, 'where:(' )<< ")" unless @where.blank?
132
+ end
133
+
134
+ def maxdepth=x
135
+ @maxdepth = x
108
136
  end
109
- end
110
137
 
138
+ def method_missing method, *arg, &b
139
+ @misc << method.to_s << " " << arg.map(&:to_s).join(' ')
140
+ end
111
141
 
112
- module OrientSupport
142
+ def misc
143
+ @misc.join(' ') unless @misc.empty?
144
+ end
145
+ # used for the first compose-statement of a compose-query
146
+ def compose_simple
147
+ '{'+ [ "class: #{@match_class}",
148
+ "as: #{@as}" ,
149
+ where_s ].compact.join(', ') + '}'
150
+ end
113
151
 
114
- module Support
115
- =begin
116
- supports
152
+ def compose
153
+
154
+ '{'+ [ "class: #{@match_class}",
155
+ "as: #{@as}" ,
156
+ where_s,
157
+ while_s,
158
+ @maxdepth >0 ? "maxdepth: #{maxdepth}": nil ].compact.join(', ')+'}'
159
+ end
160
+ alias :to_s :compose
161
+ end
117
162
 
118
- where: 'string'
119
- where: { property: 'value', property: value, ... }
120
- where: ['string, { property: value, ... }, ... ]
163
+ class OrientQuery
164
+ include Support
121
165
 
166
+ =begin
167
+ Call where without a parameter to request the saved where-string
168
+ To create the where-part of the query a string, a hash or an Array is supported
122
169
 
123
- Used by update and select
170
+ where: "r > 9" --> where r > 9
171
+ where: {a: 9, b: 's'} --> where a = 9 and b = 's'
172
+ where:[{ a: 2} , 'b > 3',{ c: 'ufz' }] --> where a = 2 and b > 3 and c = 'ufz'
124
173
  =end
125
174
 
126
- def compose_where *arg
127
- arg=arg.flatten
128
- return "" if arg.blank? || arg.size == 1 && arg.first.blank?
129
- "where " + arg.map do |issue|
130
- case issue
131
- when String
132
- issue
133
- when Hash
134
- generate_sql_list issue
175
+ attr_accessor :where
176
+ attr_accessor :let
177
+ attr_accessor :projection
178
+ attr_accessor :order
179
+ attr_accessor :match_statements
180
+
181
+ def initialize **args
182
+ @projection = []
183
+ @misc = []
184
+ @let = []
185
+ @where = []
186
+ @order = []
187
+ @aliases = []
188
+ @match_statements = []
189
+ @class = nil
190
+ @kind = 'select'
191
+ args.each do |k, v|
192
+ case k
193
+ when :projection
194
+ @projection << v
195
+ when :let
196
+ @let << v
197
+ when :order
198
+ @order << v
199
+ when :where
200
+ @where << v
201
+ when :kind
202
+ @kind = v
203
+ when :start
204
+ @match_statements[0] = MatchStatement.new **v
205
+ # @match_statements[1] = MatchConnection.new
206
+ when :connection
207
+ @match_statements[1] = MatchConnection.new **v
208
+ when :return
209
+ @aliases << v
210
+ else
211
+ self.send k, v
212
+ end
135
213
  end
136
- end.join( ' and ' )
137
- end
138
- def generate_sql_list attributes={}
139
- attributes.map do | key, value |
140
- case value
141
- when Numeric
142
- key.to_s << " = " << value.to_s
143
- else # String, Symbol, Date, Time, Trueclass, Falseclass ...
144
- key.to_s << ' = ' << "\'#{ value }\'"
145
- end
146
- end.join( ' and ' )
147
214
  end
148
- end # module
149
215
 
216
+ def method_missing method, *arg, &b
217
+ @misc << method.to_s << " " << arg.map(&:to_s).join(' ')
218
+ end
219
+
220
+ def misc
221
+ @misc.join(' ') unless @misc.empty?
222
+ end
150
223
 
151
- class OrientQuery
224
+ def subquery
225
+ nil
226
+ end
152
227
 
153
- include Support
154
228
 
155
- def initialize **args
156
- @projection = []
157
- @misc = []
158
- @let = []
159
- @where = []
160
- @order = []
161
- args.each do | k,v|
162
- case k
163
- when :projection
164
- @projection << v
165
- when :let
166
- @let << v
167
- when :order
168
- @order << v
169
- when :where
170
- @where << v
171
- else
172
- self.send k, v
173
- end
174
- end
175
- end
176
229
 
177
- def method_missing method, *arg, &b
178
- @misc << method.to_s << " " << arg.map(&:to_s).join(' ')
179
- end
230
+ =begin
231
+ (only if kind == :match): connect
180
232
 
181
- def misc
182
- @misc.join(' ') unless @misc.empty?
183
- end
233
+ Add a connection to the match-query
184
234
 
185
- def subquery
186
- nil
187
- end
235
+ A Match-Query alwas has an Entry-Stratement and maybe other Statements.
236
+ They are connected via " -> " (outE), "<-" (inE) or "--" (both).
188
237
 
189
- def compose
190
- [ "select", projection_s, from, let_s, where_s , subquery, misc, order_s , group_by, unwind, skip ].compact.join(' ')
191
- end
238
+ The connection method adds a connection to the statement-stack.
192
239
 
193
- alias :to_s :compose
194
- =begin
195
- from can either be a Databaseclass to operate on or a Subquery providing data to query further
240
+ Parameters:
241
+ direction: :in, :out, :both
242
+ edge_class: to restrict the Query on a certain Edge-Class
243
+ count: To repeat the connection
244
+ as: Includes a micro-statement to finalize the Match-Query
245
+ as: defines a output-variablet, which is used later in the return-statement
246
+
247
+ The method returns the OrientSupport::MatchConnection object, which can be modified further.
248
+ It is compiled by calling compose
196
249
  =end
197
- def from arg=nil
198
- if arg.present?
199
- @database = case arg
200
- when Class
201
- arg.new.classname
202
- when ActiveOrient::Model
203
- classname
204
- when String
205
- arg
206
- when Symbol
207
- arg
208
- when OrientQuery
209
- arg
210
- end
211
- compose # return the complete query
212
- else # read from
213
- "from " << @database.to_s unless @database.nil?
214
- end
215
- end
216
- alias :from= :from
217
- def database_class= arg
218
- @database = arg if @database.present?
219
- if @from.is_a? OrientQuery
220
- @from.database_class= arg
221
- end
222
- end
223
- def database_class
224
- if @database.present?
225
- @database
226
- elsif @from.is_a? OrientQuery
227
- @from.database_class
228
- else
229
- nil
230
- end
231
- end
232
250
 
251
+ def connect direction, edge_class: nil, count: 1, as: nil
252
+ direction= :both unless [ :in, :out].include? direction
253
+ match_statements << m = OrientSupport::MatchConnection.new( direction: direction, count: count, as: as)
254
+ m
255
+ end
233
256
 
234
257
  =begin
235
- Call where without a parameter to request the saved where-string
258
+ (only if kind == :match): statement
236
259
 
237
- to create the where-part of the query a string, a hash or an Array is supported
260
+ A Match Query consists of a simple start-statement
261
+ ( classname and where-condition ), a connection followd by other Statement-connection-pairs.
262
+ It performs a sub-query starting at the given entry-point.
238
263
 
239
- where: "r > 9" --> where r > 9
240
- where: {a: 9, b: 's'} --> where a = 9 and b = 's'
241
- where:[{ a: 2} , 'b > 3',{ c: 'ufz' }] --> where a = 2 and b > 3 and c = 'ufz'
242
- =end
243
- attr_accessor :where
244
- def where_s
245
- compose_where @where
246
- end
264
+ Statement adds a statement to the statement-stack.
265
+ Statement returns the created OrientSupport::MatchStatement-record for further modifications.
266
+ It is compiled by calling »compose«.
247
267
 
268
+ OrientSupport::OrientQuery collects any "as"-directive for inclusion in the return-statement
248
269
 
249
- attr_accessor :let
250
- def let_s
251
- unless @let.empty?
252
- "let " << @let.map do |s|
253
- case s
254
- when Hash
255
- s.map{ |x,y| "$#{x} = ( #{y} )"}.join( ', ')
256
- when Array
257
- s.join(', ')
258
- else
259
- s
260
- end
261
- end.join(', ')
270
+ Parameter (all optional)
271
+ Class: classname, :where: {}, while: {}, as: string, maxdepth: >0 ,
272
+
273
+ =end
274
+ def statement match_class= nil, **args
275
+ match_statements << s = OrientSupport::MatchStatement.new( mattch_class, args )
276
+ s
277
+ end
278
+ =begin
279
+ Output the compiled query
280
+ Parameter: destination (rest, batch )
281
+ If the query is submitted via the REST-Interface (as get-command), the limit parameter is extracted.
282
+ =end
283
+
284
+ def compose(destination: :batch)
285
+ if @kind == :match
286
+ unless @match_statements.empty?
287
+ match_query = @kind.to_s.upcase + " "+ @match_statements[0].compose_simple
288
+ match_query << @match_statements[1..-1].map( &:compose ).join
289
+ match_query << " RETURN "<< (@match_statements.map( &:as ).compact | @aliases).join(', ')
262
290
  end
291
+ elsif destination == :rest
292
+ [@kind, projection_s, from, let_s, where_s, subquery, misc, order_s, group_by, unwind, skip].compact.join(' ')
293
+ else
294
+ [@kind, projection_s, from, let_s, where_s, subquery, misc, order_s, group_by, limit, unwind, skip].compact.join(' ')
263
295
  end
296
+ end
297
+ alias :to_s :compose
264
298
 
265
- def distinct d
266
- @projection << case d
267
- when String, Symbol
268
- "distinct( #{d.to_s} )"
269
- when Array
270
- "distinct( #{d.first} ) as #{d.last}"
271
- when Hash
272
- "distinct( #{d.first.first} ) as #{d.first.last}"
273
- else
274
- ""
275
- end
276
- compose # return the hole query
277
- end
278
- alias :distinct= :distinct
279
-
280
- attr_accessor :projection
281
- def projection_s
282
-
283
- @projection.map do | s |
284
- case s
285
- when Hash
286
- s.map{ |x,y| "#{x} as #{y}"}.join( ', ')
287
- when Array
288
- s.join(', ')
289
- else
290
- s
291
- end
292
- end.join( ', ' )
299
+ =begin
300
+ from can either be a Databaseclass to operate on or a Subquery providing data to query further
301
+ =end
293
302
 
303
+
304
+ def from arg = nil
305
+ if arg.present?
306
+ @database = case arg
307
+ when ActiveOrient::Model
308
+ arg.rrid
309
+ when OrientQuery
310
+ ' ( '+ arg.to_s + ' ) '
311
+ else
312
+ if arg.to_s.rid?
313
+ arg
314
+ else
315
+ ORD.classname(arg)
316
+ end
317
+ end
318
+ compose # return the complete query
319
+ else # read from
320
+ "from #{@database}" unless @database.nil?
294
321
  end
322
+ end
323
+ alias :from= :from
324
+
325
+ def database_class
326
+ if @database.present?
327
+ @database
328
+ elsif @from.is_a? OrientQuery
329
+ @from.database_class
330
+ else
331
+ nil
332
+ end
333
+ end
295
334
 
335
+ def database_class= arg
336
+ @database = arg if @database.present?
337
+ if @from.is_a? OrientQuery
338
+ @from.database_class= arg
339
+ end
340
+ end
296
341
 
297
- # def where= w
342
+ def where_s
343
+ compose_where @where
344
+ end
298
345
 
299
- # end
300
- # select_string = ("select " + select_string + distinct_string + ' from ' + class_name(o_class) ).squeeze(' ')
301
- # where_string = compose_where( where )
302
- def group_by g=nil
303
- @group = "group_by #{g.to_s}" if g.present?
304
- # only a string is allowed
305
- @group # return_value
306
- end
307
- def unwind u=nil
308
- @unwind = "unwind #{u.to_s}" if u.present?
309
- # only a string is allowed
310
- @unwind # return_value
311
- end
346
+ def let_s
347
+ unless @let.empty?
348
+ "let " << @let.map do |s|
349
+ case s
350
+ when String
351
+ s
352
+ when Array
353
+ s.join(', ')
354
+ # when Hash ### is not recognized in jruby
355
+ else
356
+ s.map{|x,y| "$#{x} = (#{y})"}.join(', ')
357
+ end
358
+ end.join(', ')
359
+ end
360
+ end
312
361
 
313
- def skip n=nil
314
- @skip= n if n.present?
315
- "skip #{@skip}" if @skip.present?
316
- end
362
+ def distinct d
363
+ @projection << case d
364
+ when String, Symbol
365
+ "distinct( #{d.to_s} )"
366
+ when Array
367
+ "distinct( #{d.first} ) as #{d.last}"
368
+ when Hash
369
+ "distinct( #{d.first.first} ) as #{d.first.last}"
370
+ else
371
+ ""
372
+ end
373
+ compose # return the hole query
374
+ end
375
+ alias :distinct= :distinct
376
+
377
+ def projection_s
378
+ @projection.map do | s |
379
+ case s
380
+ when Array
381
+ s.join(', ')
382
+ when String, Symbol
383
+ s.to_s
384
+ else
385
+ s.map{ |x,y| "#{x} as #{y}"}.join( ', ')
386
+ end
387
+ end.join( ', ' )
388
+ end
317
389
 
318
- attr_accessor :order
319
-
320
- def order_s
321
- unless @order.empty?
322
- # the [@order] is nessesary to enable query.order= "..." oder query.order= { a: :b }
323
- "order by " << [@order].flatten.map do | o |
324
- case o
325
- when Hash
326
- o.map{ |x,y| "#{x} #{y}" }.join( " " )
327
- else
328
- o.to_s
329
- end # case
330
- end.join(', ')
331
- else
332
- ''
333
- end
334
- end
335
- # misc_string = if skip > 0 && limit > 0
336
- # " skip: #{skip} "
337
- # else
338
- # ""
339
- # end
340
- # #
341
- #
342
- # def compose
343
- #
344
- # end
345
-
346
- end
347
- end # module
390
+ def limit l=nil
391
+ @limit = "limit #{l.to_s}" if l.present?
392
+ # only a string is allowed
393
+ @limit # return_value
394
+ end
395
+ alias :limit= :limit
396
+
397
+ def get_limit
398
+ @limit.nil? ? -1 : @limit.split(' ').last.to_i
399
+ end
400
+
401
+ def group_by g = nil
402
+ @group = "group by #{g.to_s}" if g.present?
403
+ # only a string is allowed
404
+ @group # return_value
405
+ end
406
+
407
+ def unwind u = nil
408
+ @unwind = "unwind #{u.to_s}" if u.present?
409
+ # only a string is allowed
410
+ @unwind # return_value
411
+ end
412
+
413
+ def skip n = nil
414
+ @skip = n if n.present?
415
+ "skip #{@skip}" if @skip.present?
416
+ end
417
+
418
+ def order_s
419
+ unless @order.empty?
420
+ # the [@order] is nessesary to enable query.order= "..." oder query.order= { a: :b }
421
+ "order by " << [@order].flatten.map do |o|
422
+ #puts "CLASS : "+o.class.to_s
423
+ #puts o.to_s
424
+ case o
425
+ when String, Symbol, Array
426
+ o.to_s
427
+ else
428
+ o.map{|x,y| "#{x} #{y}"}.join(" ")
429
+ end # case
430
+ end.join(', ')
431
+ else
432
+ ''
433
+ end # unless
434
+ end # def
435
+ end # class
436
+
437
+
438
+ end # module