active-orient 0.4 → 0.5

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.
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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d00a72ebc77faf7333a31a4b5c73f17554ccfc88
4
- data.tar.gz: 62cd8f3823a629dba2f10e8b91b7841c9359c29d
3
+ metadata.gz: 5968de1064555bed8ecadc417fbad4f4af9c78d1
4
+ data.tar.gz: 3f06f99417522ab20a776412f5b2eca1295664f2
5
5
  SHA512:
6
- metadata.gz: bdae72102cee0e3c39c07c74715e9167878e9be90f27d12da827dbae7419c0105adf77bb9cc43ecc6bcd5ae80c1f394bff8795865d3014d70758bc9f562a4d8b
7
- data.tar.gz: 54415683a7bda1bfac78d73cf668fc93be875f654de0257e67f9c2a85963ef1315e156c2517b795713a4067635b6269710294a1cc2d74f09069de011a751b5ef
6
+ metadata.gz: 05ae6ba2fd2e933661e6f36fc1db77bef5ecd944b90f490c4d8d49d737b97aaf82ac61c0bcdff4055ac393fde2fe70e54228a30afdbef28d61134f0081f84779
7
+ data.tar.gz: 854f1efe44dd9a4056b5a37d882ed887487f7b7d734447c5d289648b118444e126352da92d2bf74935ce304f4eeecc92faed329f80a54fb85fbdb0a2b0f394ef
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ *~
data/Gemfile CHANGED
@@ -1,15 +1,20 @@
1
1
  source "https://rubygems.org"
2
2
  gemspec
3
3
  gem 'activesupport' , "~>4.2"
4
- gem 'activemodel'
5
- gem 'rest-client', :git => 'git://github.com/rest-client/rest-client.git'
4
+ gem 'activemodel', "~>4.2"
5
+ gem 'rest-client' , :git => 'git://github.com/rest-client/rest-client.git'
6
6
  gem 'nokogiri', '~> 1.6.6' #, :git => 'git://github.com/sparklemotion/nokogiri.git'
7
+ gem 'orientdb' , :path => '/home/topo/orientdb-jruby' , :platforms => :jruby
8
+ #gem 'orientdb' , :git => 'git://github.com/topofocus/orientdb-jruby.git', :branch => '2.1.2', :platforms => :jruby
7
9
  group :development, :test do
10
+ gem "awesome_print"
8
11
  gem "rspec"
12
+ gem 'rspec-legacy_formatters'
9
13
  gem 'rspec-its'
10
14
  gem 'rspec-collection_matchers'
11
15
  gem 'rspec-context-private'
12
- gem 'guard'
16
+ gem 'guard-jruby-rspec', :platforms => :jruby, :git => 'git://github.com/jkutner/guard-jruby-rspec.git'
17
+ gem 'guard'#, :platforms => :ruby
13
18
  gem 'guard-rspec'
14
19
  ## gem 'database_cleaner'
15
20
  gem 'rb-inotify'
data/Guardfile CHANGED
@@ -1,7 +1,6 @@
1
1
  # A sample Guardfile
2
2
  # More info at https://github.com/guard/guard#readme
3
-
4
- guard :rspec, cmd: "bundle exec rspec" do
3
+ def fire
5
4
  require "ostruct"
6
5
 
7
6
  # Generic Ruby apps
@@ -12,10 +11,19 @@ guard :rspec, cmd: "bundle exec rspec" do
12
11
 
13
12
 
14
13
  watch(%r{^spec/.+_spec\.rb$})
15
- watch(%r{^spec/usecase/(.+).rb$})
14
+ # watch(%r{^spec/usecase/(.+)\.rb$})
16
15
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
16
+ # watch(%r{^examples/time_graph/spec/(.+)_spec\.rb$})
17
+ watch('examples/time_graph/spec/create_time_spec.rb')
17
18
  watch('spec/spec_helper.rb') { "spec" }
18
19
 
19
- watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
20
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
20
21
  end
21
22
 
23
+
24
+ interactor :simple
25
+ if RUBY_PLATFORM == 'java'
26
+ guard( 'jruby-rspec') {fire} #', :spec_paths => ["spec"]
27
+ else
28
+ guard( :rspec, cmd: "bundle exec rspec") { fire }
29
+ end
data/README.md CHANGED
@@ -2,324 +2,344 @@
2
2
  Use OrientDB to persistently store dynamic Ruby-Objects and use database queries to manage even very large
3
3
  datasets.
4
4
 
5
- The Package ist tested with Ruby 2.2.1 and Orientdb 2.1.
5
+ You need a ruby 2.3 or a jruby 9.1x Installation and a working OrientDB-Instance (Version 2.2 prefered).
6
+ The jruby-part is experimental.
6
7
 
7
-
8
- To start you need a ruby 2.x Installation and a working OrientDB-Instance.
9
- Install the Gem the usual way
10
-
11
- For a quick start, go to the home directory of the package and start an irb-session
12
-
13
- ```ruby
14
- require 'bundler/setup'
15
- require 'active-orient'
8
+ For a quick start, clone the project, run bundle install & bundle update, update config/connect.yml, create the documentation by calling »rdoc«
9
+ and start an irb-session:
10
+ ```
11
+ cd bin
12
+ ./active-orient-console test # or d)develpoment, p)roduction environment as defined in config/connect.yml
16
13
  ```
17
14
 
18
- First, the Database-Server has to be specified. Then we can connect to a database.
19
- Assuming, the server is located on localhost, we just define »default-server«
20
- ```ruby
21
- ActiveOrient::OrientDB.default_server= { user: 'your user', password: 'your password' }
15
+ »ORD« is the Database-Instance itself. If the Database noticed is not present, it is created on startup.
16
+ A simple SQL-Query is submitted by providing a Block to »execute«
17
+ ```ruby
18
+ result = ORD.execute { "select * from Stock" }
19
+ ```
20
+ Obviously, the class »Stock« has to exist.
21
+ Let's create some classes
22
+
23
+ ```ruby
24
+ ORD.create_class 'ClassDocumentName' # creates or opens a basic document-class
25
+ ORD.create_vertex_class 'ClassVertexName' # creates or opens a vertex-class
26
+ ORD.create_edge_class 'ClassEdgeName' # creates or opens an edge-class, providing bidirectional links between documents
27
+ {Classname}.delete_class # removes the class in the database and destroys the ruby-object
28
+ ```
22
29
 
30
+ Classnames appear unchanged as Database-Classes. Strings and Symbols are accepted. Depending on the namespace choosen in 'config/config.yml' Model-Classes are allocated and linked to database-classes. For simplicity, here we omit any namespace ( :namespace: :object in config.yml). Thus the Model-Obects are accessible directly.
23
31
 
24
- r = ActiveOrient::OrientDB.new database: 'First'
25
- => I, [2015-08-18T09:49:18.858758 #88831] INFO -- OrientDB#Connect: Connected to database First
26
- => #<ActiveOrient::OrientDB:0x000000048d0488 @res=#<RestClient::Resource:0x00000004927288
27
- @url="http://localhost:2480", @block=nil,
28
- @options={:user=>"xx", :password=>"***"}>, @database="First", @classes=[]>
29
- ```
30
32
 
31
- »r« is the Database-Instance itself. Obviously the database is empty.
33
+ **Naming-Convention:** The name given in the »create-class«-Statement becomes the Database-Classname.
34
+ In Ruby-Space its Camelized, ie: ORD.create_class(:hut_ab) generates a Ruby-Class »HutAb«.
32
35
 
36
+ This can be customized in the "naming_convention"-class-method, which has to be defined in 'config/boot.rb'. The naming_convention changes the ruby-view to the classes. The Database-Class-Name is derived from the argument to #CreateClass, ORD.create_class('HANDS_UP') creates a database-class "HANDS_UP' and a Ruby-Class "HandsUp".
33
37
 
34
- Let's create some classes
38
+ ActiveOrient::Model's can be customized through methods defined in the model-directory. These methods are
39
+ loaded automatically afert executing #CreateClass (and through the preallocation process). Further details in the Examples-Section.
35
40
 
36
- ```ruby
37
- M = r.open_class 'classname' #
38
- M = r.create_class 'classname' # creates or opens a basic document-class
39
- M = r.create_vertex_class 'classname' # creates or opens a vertex-class
40
- M = r.create_edge_class 'classname' # creates or opens an edge-class, providing bidirectional links between documents
41
+ #### CRUD
42
+ The CRUD-Process (create, read = query, update and remove) is performed as
43
+ ```ruby
44
+ ORD.create_class :M
45
+ M.create name: 'Hugo', age: 46, interests: [ 'swimming', 'biking', 'reading' ]
46
+ # or
47
+ new_record = M.new age: 46, interests: [ 'swimming', 'biking', 'reading' ]
48
+ new_record.save # alternative: new_record.update
49
+ ##
50
+ hugo = M.where( name: 'Hugo' ).first
51
+ hugo.update set: { :father => M.create( name: "Volker", age: 76 ) } # we create an internal link
52
+ hugo.father.name # --> volker
53
+ M.remove hugo
54
+ M.delete_class # removes the class from OrientDB and deletes the ruby-object-definition
55
+ ```
56
+
57
+ #### Inherence
41
58
 
42
- r.delete_class M # universal removal-of-the-class-method
59
+ Create a Tree of Objects with create_classes
60
+ ```ruby
61
+ ORD.create_classes sector: [ :industry, :category, :subcategory ]
62
+ => {Sector=>[Industry, Category, Subcategory]}
63
+ Industry.create name: 'Communications' #---> Create an Industry-Record with the attribute "name"
64
+ Sector.where name: 'Communications' #---> an Array with the Industry-Object
65
+ => [#<Industry:0x0000000225e098 @metadata= (...) ]
43
66
  ```
67
+ ***notice*** to create inherent Vertices use ORD.create_classes( sector: [ :industry, :category, :subcategory ]){ :V }
44
68
 
69
+ #### Preallocation of Model-Classes
70
+ All database-classes are preallocated after connecting to the database. Thus you can use Model-Classes from the start.
45
71
 
46
- »M« is the ActiveOrient::Model-Class itself, a constant pointing to the class-definition of the ruby-class.
47
- Its a shortcut for »ActiveOrient::Model::{Classname} and is reused if defined elsewhere.
72
+ If the "rid" is known, any Object can be retrieved and correctly allocated by
73
+ ```ruby
74
+ the_object = ActiveOrient::Model.autoload_object "xx:yy" # or "#xx:yy"
75
+ ---> {ActiveOrient::Model} Object
76
+ ```
48
77
 
49
- If a schema is used, properties can be created and retrieved as well
50
- ```ruby
51
- r.create_properties( M ) do
52
- { symbol: { propertyType: 'STRING' },
53
- con_id: { propertyType: 'INTEGER' },
54
- details: { propertyType: 'LINK', linkedClass: 'Contracts' }
55
- }
78
+ #### Properties
79
+ The schemaless mode has many limitations. ActiveOrient offers a Ruby way to define Properties and Indexes
56
80
 
57
- r.get_class_properties M
58
- ```
59
- or
60
81
  ```ruby
61
- M.create_property 'symbol'
62
- M.create_property 'con_id', type: 'integer'
63
- M.create_property 'details', type: 'link', other_class: 'Contracts'
82
+ ORD.create_class :M, :item
83
+ M.create_property :symbol # the default-case: type: :string, no index
84
+ M.create_property :con_id, type: :integer
85
+ M.create_property :details, type: :link, other_class: 'Contracts'
86
+ M.create_property :items, type: :linklist, :linklist: Item
87
+ M.create_property :name, index: :unique # or M.create_property( 'name' ){ :unique }
64
88
  ```
65
89
 
66
- #### Active Model interface
67
-
68
- Every OrientDB-Database-Class is mirrord as Ruby-Class. The Class itself is defined by
90
+ (Experimental) You can put restrictions on your properties with the command "alter_property":
91
+
69
92
  ```ruby
70
- M = r.create_class 'classname'
71
- M = r.create_class { superclass_name: 'classname' }
72
- Vertex = r.create_vertex_class 'classname'
73
- Edge = r.create_edge_class 'classname'
93
+ M.alter_property property: "value", attribute: "MIN", alteration: 0
94
+ M.alter_property property: "value", attribute: "MAX", alteration: 23
74
95
  ```
75
- and is of TYPE ActiveOrient::Model::{classname}
76
96
 
77
- As for ActiveRecord-Tables, the Class itself provides methods to inspect and to filter datasets form the database.
97
+ #### Active Model interface
98
+
99
+ As for ActiveRecord-Tables, the Model-class itself provides methods to inspect and filter datasets form the database.
78
100
 
79
101
  ```ruby
80
102
  M.all
81
103
  M.first
82
- M.last
83
- ```
84
- returns an Array containing all Documents/Edges of the Class; the first and the last Record.
85
- ```ruby
86
- M.where town: 'Berlin'
87
- ```
88
- performs a query on the class and returns the result as Array
104
+ M.last # notice: last does not work in orientdb version 2.2, because the sorting algorithm for rid's is damaged
105
+ M.all.last # or M.where( ... ).last walkaround for Orientdb V 2.2
106
+ M.where town: 'Berlin'
89
107
 
90
- ```ruby
91
108
  M.count where: { town: 'Berlin' }
92
109
  ```
93
- gets the number of datasets fullfilling the search-criteria. Any parameter defining a valid
94
- SQL-Query in Orientdb can be provided to the count, where, first and last-method.
110
+ »count« gets the number of datasets fulfilling the search-criteria. Any parameter defining a valid SQL-Query in Orientdb can be provided to the »count«, »where«, »first« and »last«-method.
95
111
 
96
- A »normal« Query is submitted via
112
+ A »normal« Query is submitted via
97
113
  ```ruby
98
- M.get_documents projection: { projection-parameter }
99
- distinct: { some parameters }
100
- where: { where-parameter }
101
- order: { sorting-parameters }
102
- group_by: { one grouping-parameter}
103
- unwind:
104
- skip:
105
- limit:
114
+ M.get_records projection: { projection-parameter },
115
+ distinct: { some parameters },
116
+ where: { where-parameter },
117
+ order: { sorting-parameters },
118
+ group_by: { one grouping-parameter},
119
+ unwind: ,
120
+ skip: ,
121
+ limit:
106
122
 
107
123
  # or
108
- query = OrientSupport::OrientQuery.new {paramter}
109
- M.get_documents query: query
124
+ query = OrientSupport::OrientQuery.new {paramter}
125
+ M.query_database query
110
126
 
111
127
  ```
112
128
 
113
- Basic graph-support:
114
-
115
-
129
+ Graph-support:
116
130
 
117
131
  ```ruby
118
- vertex_1 = Vertex.create color: "blue"
119
- vertex_2 = Vertex.create flower: "rose"
120
- Edge.create_edge attributes: { :birthday => Date.today }, from: vertex_1, to: vertex_2
132
+ ORD.create_vertex_class :the_vertex
133
+ ORD.create_edge_class :the_edge
134
+ vertex_1 = TheVertex.create color: "blue"
135
+ vertex_2 = TheVertex.create flower: "rose"
136
+ TheEdge.create_edge attributes: {:birthday => Date.today }, from: vertex_1, to: vertex_2
121
137
  ```
122
- connects the vertices and assigns the attributes to the edge
138
+ It connects the vertexes and assigns the attributes to the edge.
123
139
 
140
+ To query a graph, SQL-like-Queries and Match-statements can be used (see below).
124
141
 
125
- #### Links
126
142
 
127
- A record in a database-class is defined by a »rid«. Every Model-Object comes with a handy »link«-method.
143
+ #### Links and LinkLists
128
144
 
129
- In OrientDB links are used to realise unidirectional 1:1 and 1:n relationships.
145
+ A record in a database-class is defined by a »rid«. If this is stored in a class, a link is set.
146
+ In OrientDB links are used to realize unidirectional 1:1 and 1:n relationships.
130
147
 
131
- ActiveOrient autoloads Model-objects when they are accessed. As a consequence,
132
- if an Object is stored in Cluster 30 and id 2, then "#30:2" fully qualifies the ActiveOrient::Model object.
148
+ ActiveOrient autoloads Model-objects when they are accessed. Example:
149
+ If an Object is stored in Cluster 30 and id 2, then "#30:2" fully qualifies the ActiveOrient::Model object and sets the
150
+ link if stored somewhere.
133
151
 
134
152
  ```ruby
135
- TestLinks = r.create_class 'Test_link_class'
136
- TestBase = r.create_class 'Test_base_class'
153
+ ORD.create_class 'test_link'
154
+ ORD.create_class 'test_base'
137
155
 
138
- link_document = TestLinks.create att: 'one attribute'
139
- base_document = TestBase.create base: 'my_base', single_link: link_document
156
+ link_document = TestLink.create att: 'one attribute'
157
+ base_document = TestBase.create base: 'my_base', single_link: link_document
140
158
  ```
141
- base_document.single_link just contains the rid. When accessed, the ActiveOrient::Model::Testlinkclass-object is autoloaded and
159
+ base_document.single_link just contains the rid. When accessed, the ActiveOrient::Model::Testlinkclass-object is autoloaded and
160
+
142
161
  ``` ruby
143
162
  base_document.single_link.att
144
163
  ```
145
- reads the stored content of link_document.
164
+ reads the stored content of link_document.
146
165
 
147
- To store a list of links to other Database-Objects a simple Array is allocated
166
+ To store a list of links to other Database-Objects, a simple Array is allocated
148
167
  ``` ruby
149
168
  # predefined linkmap-properties
150
- base_document = TestBase.create links: []
151
- ( 0 .. 20 ).each{ |y| base_document.links << TestLinks.create nr: y }
152
- end
169
+ TestLink.create_property :links, type: :linklist, linkedClass: :test_links
170
+ base_document = TestBase.create links: []
171
+ (0 .. 20).each{|y| base_document.links << TestLink.create( nr: y )}
172
+
153
173
  #or in schemaless-mode
154
- base_document = TestBase.create links: (0..20).map{|y| TestLinks.create nr: y }
155
-
156
-
174
+ base_document = TestBase.create links: (0..20).map{|y| TestLink.create nr: y}
175
+ base_document.update
157
176
  ```
158
- base_document.links behaves like a ruby-array.
177
+ base_document.links behaves like a ruby-array.
159
178
 
160
179
  If you got an undirectional graph
161
180
 
162
181
  a --> b ---> c --> d
163
182
 
164
- the graphelements can be explored by joining the objects ( a.b.c.d ), or (a.b[5].c[9].d )
183
+ the graph elements can be explored by joining the objects (a[6].b[5].c[9].d)
165
184
 
166
- #### Edges
185
+ Refer to the "Time-Graph"-Example for an Implementation of an bidirectional Graph with the same Interface
167
186
 
168
- Edges are easily handled
187
+ #### Edges
188
+ Edges provide bidirectional Links. They are easily handled
169
189
  ```ruby
170
- Vertex = r.create_vertex_class 'd1'
171
- Eedge = r.create_edge_class 'e1'
190
+ ORD.create_vertex_class :the_vertex # --> TheVertex
191
+ ORD.create_edge_class :the_edge # --> TheEdge
172
192
 
173
- start = Vertex.create something: 'nice'
174
- the_end = Vertex.create something: 'not_nice'
175
- the_edge = Edge.create_edge attributes: { transform_to: 'very bad' },
193
+ start = TheVertex.create something: 'nice'
194
+ the_end = TheVertex.create something: 'not_nice'
195
+ the_edge = TheEdge.create attributes: {transform_to: 'very bad'},
176
196
  from: start,
177
197
  to: the_end
178
-
198
+
179
199
  (...)
180
- the_edge.delete
200
+ the_edge.delete # To delete the edge
201
+ ```
202
+ The create-Method od Edge-Classes takes a block. Then all statements are transmitted in batch-mode.
203
+ Assume, Vertex1 and Vertex2 are Vertex-Classes and TheEdge is an Edge-Class, then
204
+ ```ruby
205
+ record1 = (1 .. 100).map{|y| Vertex1.create testentry: y }
206
+ record2 = (:a .. :z).map{|y| Vertex2.create testentry: y }
207
+ edges = TheEdge.create attributes: { study: 'Experiment1'} do | attributes |
208
+ # map returns an array, which is further processed by #create_edge
209
+ ('a'.ord .. 'z'.ord).map do |o|
210
+ { from: record1.find{|x| x.testentry == o },
211
+ to: record2.find{ |x| x.testentry.ord == o },
212
+ attributes: attributes.merge( key: o.chr ) }
213
+ end
181
214
  ```
215
+ connects the vertices and provides a variable "key" and a common "study" attribute to each edge.
182
216
 
183
- There is a basic support for traversals throught a graph.
217
+ There is a basic support for traversals through a graph.
184
218
  The Edges are accessed by their names (downcase).
185
-
186
219
  ```ruby
187
- start.e1[0]
188
- --> #<ActiveOrient::Model::E1:0x000000041e4e30
189
- @metadata={"type"=>"d", "class"=>"E1", "version"=>60, "fieldTypes"=>"out=x,in=x",
190
- "cluster"=>16, "record"=>43},
191
- @attributes={"out"=>"#31:23", "in"=>"#31:15", "transform_to"=>"very bad" }>
220
+ start = TheVertex.where: {something: "nice"}
221
+ start[0].e1[0]
222
+ --> #<E1:0x000000041e4e30
223
+ @metadata={"type"=>"d", "class"=>"E1", "version"=>60, "fieldTypes"=>"out=x,in=x", "cluster"=>16, "record"=>43},
224
+ @attributes={"out"=>"#31:23", "in"=>"#31:15", "transform_to"=>"very bad" }>
192
225
  ```
226
+
193
227
  The Attributes "in" and "out" can be used to move across the graph
228
+
229
+ ```ruby
230
+ start[0].e1[0].out.something
231
+ # ---> "not_nice"
232
+ start[0].e1[0].in.something
233
+ # ---> "nice"
234
+ ```
235
+
236
+ (Experimental) In alternative you can "humanize" your code in the following way:
237
+
194
238
  ```ruby
195
- start.e1[0].out.something
196
- ---> "not_nice
197
- start.e1[0].in.something
198
- ---> "nice
239
+ Vertex.add_edge_link name: "ends", edge: TheEdge
240
+ start.ends.something # <-- Similar output as start[0].e1[0].out.something
199
241
  ```
242
+
200
243
  #### Queries
201
- Contrary to traditional SQL-based Databases OrientDB handles subqueries very efficient.
202
- In addition, OrientDB supports precompiled statements (let-Blocks).
203
244
 
204
- ActiveOrient is equipped with a simple QueryGenerator: ActiveSupport::OrientQuery.
205
- It works in two modi: a comprehensive and a subsequent one
245
+ Contrary to traditional SQL-based Databases OrientDB handles sub-queries very efficiently. In addition, OrientDB supports precompiled statements (let-Blocks).
246
+
247
+ ActiveOrient is equipped with a simple QueryGenerator: ActiveSupport::OrientQuery.
248
+ It works in two ways: a comprehensive and a subsequent one
249
+
206
250
  ```ruby
207
-
251
+
208
252
  q = OrientSupport::OrientQuery.new
209
- q.from = Vertex
253
+ q.from = Vertex # If a constant is used, then the correspending
254
+ # ActiveOrient::Model-class is refered
210
255
  q.where << a: 2
211
256
  q.where << 'b > 3 '
212
257
  q.distinct = :profession
213
- q.order = { :name => :asc }
258
+ q.order = {:name => :asc}
214
259
 
215
260
  ```
216
261
  is equivalent to
262
+
217
263
  ```ruby
218
- q = OrientSupport::OrientQuery.new from: Vertex ,
264
+ q = OrientSupport::OrientQuery.new from: Vertex ,
219
265
  where: [{ a: 2 }, 'b > 3 '],
220
266
  distinct: :profession,
221
267
  order: { :name => :asc }
222
268
  q.to_s
223
269
  => select distinct( profession ) from Vertex where a = 2 and b > 3 order by name asc
224
270
  ```
225
- Both modes can be mixed.
226
271
 
227
- If subqueries are nessesary, they can be introduced as OrientSupport::OrientQuery or as »let-block«.
272
+ Both eayss can be mixed.
273
+
274
+ If sub-queries are necessary, they can be introduced as OrientSupport::OrientQuery or as »let-block«.
275
+
228
276
  ```ruby
229
- q = OrientSupport::OrientQuery.new from: 'ModelQuery'
277
+ OQ = OrientSupport::OrientQuery
278
+ q = OQ.new from: 'ModelQuery'
230
279
  q.let << "$city = adress.city"
231
280
  q.where = "$city.country.name = 'Italy' OR $city.country.name = 'France'"
232
281
  q.to_s
233
- => select from ModelQuery let $city = adress.city where $city.country.name = 'Italy' OR $city.country.name = 'France'
282
+ # => select from ModelQuery let $city = adress.city where $city.country.name = 'Italy' OR $city.country.name = 'France'
234
283
  ```
284
+
235
285
  or
286
+
236
287
  ```ruby
237
- q = OrientSupport::OrientQuery.new
238
- q.let << { a: OrientSupport::OrientQuery.new( from: '#5:0' ) }
239
- q.let << { b: OrientSupport::OrientQuery.new( from: '#5:1' ) }
288
+ q = OQ.new
289
+ q.let << {a: OQ.new( from: '#5:0' ) }
290
+ q.let << {b: OQ.new( from: '#5:1' ) }
240
291
  q.let << '$c= UNIONALL($a,$b) '
241
292
  q.projection << 'expand( $c )'
242
- q.to_s
243
- => select expand( $c ) let $a = ( select from #5:0 ), $b = ( select from #5:1 ), $c= UNIONALL($a,$b)
293
+ q.to_s # => select expand( $c ) let $a = ( select from #5:0 ), $b = ( select from #5:1 ), $c= UNIONALL($a,$b)
244
294
  ```
245
295
 
246
-
247
-
248
-
249
- #### Execute SQL-Commands
250
- Sql-commands can be executed as batch
251
-
252
- The ActiveOrient::Query-Class provides a Query-Stack and an Records-Array which keeps the results.
253
- The ActiveOrient::Query-Class acts as Parent-Class for aggregated Records (without a @rid), which are ActiveOrient::Model::Myquery Objects. If a Query returns a database-record, the correct ActiveOrient::Model-Class is instantiated.
296
+ or
254
297
 
255
298
  ```ruby
256
- ach = ActiveOrient::Query.new
257
-
258
- ach.queries << 'create class Contracts ABSTRACT'
259
- ach.queries << 'create property Contracts.subcategory link'
260
- ach.queries << 'create property Contracts.details link'
261
- ach.queries << 'create class Stocks extends Contracts'
262
- ach.queries << 'create class Futures extends Contracts'
263
- result = ach.execute_queries transaction: false
264
-
265
-
299
+ last_12_open_interest_records = OQ.new from: OpenInterest,
300
+ order: { fetch_date: :desc } , limit: 12
301
+ bunch_of_contracts = OQ.new from: last_12_open_interest_records,
302
+ projection: 'expand( contracts )'
303
+ distinct_contracts = OQ.new from: bunch_of_contracts,
304
+ projection: 'expand( distinct(@rid) )'
305
+
306
+ distinct_contracts.to_s
307
+ => "select expand( distinct(@rid) ) from ( select expand( contracts ) from ( select from open_interest order by fetch_date desc limit 12 ) ) "
266
308
 
309
+ cq = ORD.get_documents query: distinct_contracts
267
310
  ```
268
- queries the database as demonstrated above. In addition, the generated query itself is added to the »queries«-Stack and the result can be found in sample_query.records.
269
-
270
- This feature can be used as a substitute for simple functions
311
+ this executes the query and returns the adressed rid's, which are eventually retrieved from the rid-cache.
312
+ #### Match
271
313
 
314
+ A Match-Query starts at the given ActiveOrient::Model-Class. The where-cause narrows the sample to certain
315
+ records. In the simplest version this can be returnd:
316
+
272
317
  ```ruby
273
- roq = ActiveOrient::Query.new
274
- roq.queries =["select name, categories.subcategories.contracts from Industries where name containstext …'ial'"]
275
- roq.execute_queries.each{|x| puts x.name, x.categories.inspect }
276
- --> Basic Materials [["#21:1"]]
277
- --> Financial [["#21:2"]]
278
- --> Industrial [["#23:0", "#23:1"]]
318
+ ORD.create_class :Industry
319
+ Industry.match where:{ name: "Communications" }
320
+ => #<ActiveOrient::Model::Query:0x00000004309608 @metadata={"type"=>"d", "class"=>nil, "version"=>0, "fieldTypes"=>"Industries=x"}, @attributes={"Industries"=>"#21:1", (...)}>
279
321
  ```
280
322
 
281
- OrientDB supports the execution of SQL-Batch-Commands.
282
- ( http://orientdb.com/docs/2.0/orientdb.wiki/SQL-batch.html )
283
- This is supported simply by using a Array as Argument for ActiveOrient::Query.queries
323
+ 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.
284
324
 
285
- Therefor complex queries can be simplified using database-variables
286
325
  ```ruby
287
- ach = ActiveOrient::Query.new
288
- ach.queries << [ "select expand( contracts ) from Openinterest"
289
- "let con = select expand( contracts ) from Openinterest; ",
290
- "...", ... ]
291
- result = ach.execute_queries
326
+ Industry.match where name: "Communications"
327
+ ## is equal to
328
+ Industry.match( where: { name: 'Communications' }).first.Industries
292
329
  ```
330
+ The Match-Query uses this result-set as start for subsequent queries on connected records.
331
+ If a linear graph: Industry <- Category <- Subcategory <- Stock is build, Subcategories can
332
+ accessed starting at Industry defining
293
333
 
294
- The contract-documents are accessible with
295
334
  ```ruby
296
- r.get_document '21:1'
297
- --><Stocks: con_id: 77680640 currency: EUR details: #18:1 exchange: SMART local_symbol: BAS
298
- primary_exchange: IBIS subcategory: #14:1 symbol: BAS>
299
- ```
300
- or
301
- ```ruby
302
- my_query = ActiveOrient::Query.new
303
- ['Contracts', 'Industries', 'Categories', 'Subcategories'].each do |table|
304
- my_query.queries = [ "select count(*) from #{table}"]
305
-
306
- count = my_query.execute_queries
307
- # count=> [#<ActiveOrient::Model::Myquery:0x00000003b317c8
308
- # @metadata={"type"=>"d", "class"=>nil, "version"=>0, "fieldTypes"=>"count=l"},
309
- # @attributes={"count"=>4 } ] --> an Array with one Element, therefor count.pop
310
- puts "Table #{table} \t #{count.pop.count} Datasets "
311
- end
312
- -->Table Contracts 56 Datasets
313
- -->Table Industries 8 Datasets
314
- -->Table Categories 22 Datasets
315
- -->Table Subcategories 35 Datasets
316
-
335
+ var = Industry.match( where: { name: 'Communications'}) do | query |
336
+ query.connect :in, count: 2, as: 'Subcategories'
337
+ puts query.to_s # print the query prior sending it to the database
338
+ query # important: block has to return the query
339
+ end
340
+ => MATCH {class: Industry, as: Industries} <-- {} <-- { as: Subcategories } RETURN Industries, Subcategories
317
341
  ```
318
342
 
319
- Note that the fetched Object is of type »Stocks« (ActiveOrient::Model::Stocks).
343
+ The result-set has two attributes: Industries and Subcategories, pointing to the filtered datasets.
320
344
 
321
- The ActiveOrient-API documentation can be found here: https://github.com/orientechnologies/orientdb-docs/wiki/OrientDB-ActiveOrient
322
- and the ActiveModel-documentation is here: http://www.rubydoc.info/gems/activemodel
323
-
324
-
325
-
345
+ By using subsequent »connect« and »statement« method-calls even complex Match-Queries can be constructed.