Class: ActiveOrient::OrientDB
- Inherits:
-
Object
- Object
- ActiveOrient::OrientDB
- Includes:
- OrientSupport::Support
- Defined in:
- lib/rest.rb
Overview
OrientDB performs queries to a OrientDB-Database
The communication is based on the ActiveOrient-API.
The OrientDB-Server is specified in config/connect.yml
A Sample:
:orientdb:
:server: localhost
:port: 2480
:database: working-database
:admin:
:user: admin-user
:pass: admin-password
Instance Method Summary collapse
-
#call_function(*args) ⇒ Object
Execute a predefined Function.
-
#change_database(name) ⇒ Object
changes the working-database to name.
-
#class_hierachie(base_class: '', requery: false) ⇒ Object
returns the class_hierachie.
-
#class_name(name_or_class) ⇒ Object
Converts a given name to the camelized database-classname.
- #connect ⇒ Object
- #count_documents(**args) ⇒ Object
-
#create_class(newclass) ⇒ Object
(also: #open_class)
creates a class and returns the a ActiveOrient::Model:Newclass-Class- (Constant) which is designed to take any documents stored in this class.
-
#create_classes(classes) ⇒ Object
Creates classes and class-hierachies in OrientDB and in Ruby.
-
#create_database(type: 'plocal', database: @database) ⇒ Object
Creates a database with the given name and switches to this database as working-database Types are either ‘plocal’ or ‘memory’ .
-
#create_document(o_class, attributes: {}) ⇒ Object
Creates an Object in the Database and returns this as ActuveOrient::Model-Instance.
- #create_edge_class(name, superclass: 'E') ⇒ Object
- #create_index(o_class, name:, on: :automatic, type: :unique) ⇒ Object
-
#create_or_update_document(o_class, **args, &b) ⇒ Object
Creating a new Database-Entry ( where is omitted ).
-
#create_properties(o_class, all_properties, &b) ⇒ Object
creates properties and optional an associated index as defined in the provided block .
-
#create_property(o_class, field, index: nil, **args) ⇒ Object
create a single property on class-level.
- #create_vertex_class(name, superclass: 'V') ⇒ Object
-
#database_classes(include_system_classes: false, requery: false) ⇒ Object
(also: #inspect_classes)
returns an array with all names of the classes of the database caches the result.
-
#delete_class(o_class) ⇒ Object
deletes the specified class and returns true on success.
-
#delete_database(database:) ⇒ Object
deletes the database and returns true on success.
- #delete_document(record_id) ⇒ Object
-
#delete_documents(o_class, where: {}) ⇒ Object
Deletes documents.
-
#delete_edge(*rid) ⇒ Object
Deletes a single edge when providing a single rid-link (#00:00) Deletes multible edges when providing a list of rid-links Todo: implement delete_edges after querying the database in one statement.
- #delete_property(o_class, field) ⇒ Object
-
#execute(classname = 'Myquery', transaction: true) ⇒ Object
Executes a list of commands and returns the result-array (if present).
-
#fv(s) ⇒ Object
:nodoc:.
-
#fx(v) ⇒ Object
:nodoc:.
-
#get_class_properties(o_class) ⇒ Object
:nodoc:.
-
#get_classes(*attributes) ⇒ Object
returns an Array with (unmodified) Class-attribute-hash-Elements.
-
#get_databases ⇒ Object
returns an Array with available Database-Names as Elements.
-
#get_document(rid) ⇒ Object
Retrieves a Document from the Database as ActiveOrient::Model::class The argument can either be a rid (#[x}:y) or a link(x:y) If no Document is found, nil is returned.
-
#get_documents(raw: false, query: nil, **args) ⇒ Object
retrieves documents from a query.
-
#get_ressource ⇒ Object
called in the beginning or after a 404-Error.
-
#initialize(database: nil, connect: true) ⇒ OrientDB
constructor
A new instance of OrientDB.
-
#logger ⇒ Object
borrowed from active_support.
-
#nexus_edge(o_class, attributes: {}, from:, to:, unique: false) ⇒ Object
nexus_edge connects two documents/vertexes The parameter o_class can be either a class or a string.
-
#patch_document(rid) ⇒ Object
Lazy Updating of the given Document.
-
#preallocate_class_properties(o_class) ⇒ Object
If properties are allocated on class-level, they can be preinitialized using this method.
- #print_class_properties(o_class) ⇒ Object
-
#ressource ⇒ Object
included for development , should be removed in production release.
- #update_documents(o_class, set:, where: {}) ⇒ Object
-
#update_or_create_documents(o_class, set: {}, where: {}, **args, &b) ⇒ Object
Based on the query specified in :where records are updated according to :set.
Methods included from OrientSupport::Support
#compose_where, #generate_sql_list
Constructor Details
#initialize(database: nil, connect: true) ⇒ OrientDB
Returns a new instance of OrientDB.
49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/rest.rb', line 49 def initialize database: nil, connect: true self.default_server = { :server => 'localhost', :port => 2480, :protocol => 'http', :user => 'root', :password => 'root', :database => 'temp' }.merge default_server @res = get_ressource @database = database.presence || default_server[:database] self.logger = Logger.new('/dev/stdout') unless logger.present? # @database=@database#.camelcase connect() if connect # save existing classes @classes = [] ActiveOrient::Model.orientdb = self end |
Instance Method Details
#call_function(*args) ⇒ Object
Execute a predefined Function
906 907 908 909 910 911 |
# File 'lib/rest.rb', line 906 def call_function *args #puts "uri:#{function_uri { args.join('/') } }" @res[ function_uri { args.join('/') } ].post '' rescue RestClient::InternalServerError => e puts JSON.parse(e.http_body) end |
#change_database(name) ⇒ Object
changes the working-database to name
146 147 148 149 150 |
# File 'lib/rest.rb', line 146 def change_database name @classes = [] @database = name end |
#class_hierachie(base_class: '', requery: false) ⇒ Object
returns the class_hierachie
to fetch all Vertices
class_hiearchie( base_class: 'V').flatten
to fetch all Edges
class_hierachie( base_class: 'E').flatten
Notice: base_class has to be noted as String! There is no implicit conversion from Symbol or Class
238 239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/rest.rb', line 238 def class_hierachie base_class: '', requery: false @all_classes = get_classes( 'name', 'superClass') if requery || @all_classes.blank? def fv s # :nodoc: @all_classes.find_all{ |x| x[ 'superClass' ]== s }.map{| v| v[ 'name' ]} #.camelize } end def fx v # :nodoc: fv(v).map{ |x| ar = fx( x ) ; ar.empty? ? x : [ x , ar ] } end fx base_class end |
#class_name(name_or_class) ⇒ Object
Converts a given name to the camelized database-classname
Converts a given class-constant to the corresponding database-classname
returns a valid database-class name, nil if the class not exists
975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 |
# File 'lib/rest.rb', line 975 def class_name name_or_class name= if name_or_class.is_a? Class name_or_class.to_s.split('::').last elsif name_or_class.is_a? ActiveOrient::Model name_or_class.classname else name_or_class.to_s.camelize end if database_classes.include?(name) name elsif database_classes.include?(name.underscore) name.underscore else logger.progname = 'OrientDB#ClassName' logger.info{ "Classname #{name} not present in active Database" } nil end end |
#connect ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/rest.rb', line 75 def connect i = 0 begin logger.progname = 'OrientDB#Connect' r= @res["/connect/#{ @database }" ].get if r.code == 204 logger.info{ "Connected to database #{@database} " } true else logger.error{ "Connection to database #{@database} could NOT be established" } nil end rescue RestClient:: => e if i.zero? logger.info{ "Database #{@database} NOT present --> creating" } i=i+1 create_database retry else Kernel.exit end end end |
#count_documents(**args) ⇒ Object
736 737 738 739 740 741 742 743 744 745 |
# File 'lib/rest.rb', line 736 def count_documents **args logger.progname = 'OrientDB#count_documents' query = OrientSupport::OrientQuery.new args query.projection << 'COUNT (*)' result = get_documents raw: true, query: query result.first['COUNT'] end |
#create_class(newclass) ⇒ Object Also known as: open_class
creates a class and returns the a ActiveOrient::Model:Newclass-Class- (Constant) which is designed to take any documents stored in this class
Predefined attributes: version, cluster, record
Other attributes are assigned dynamically upon reading documents
The classname is Camelized by default, eg: classnames are always Capitalized, underscores (‘_’) indicate that the following letter is capitalized, too.
Other class-names can be used if a “$” is placed at the begining of the name-string. However, most of the model-based methods will not work in this case.
342 343 344 |
# File 'lib/rest.rb', line 342 def create_class newclass create_classes( [ newclass ] ).first end |
#create_classes(classes) ⇒ Object
Creates classes and class-hierachies in OrientDB and in Ruby.
Takes an Array or a Hash as argument and returns an Array of successfull allocated Ruby-Classes
If the argument is an array, Basic-Classes are build.
Otherwise key/value pairs are assumend to follow this terminology
{ SuperClass => [ class, class, ...], SuperClass => [] , ... }
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
# File 'lib/rest.rb', line 282 def create_classes classes # rebuild cashed classes-array # first the classes-string is camelized (this is used to allocate the ruby-class) # Then the database is queried for this string or the underscored string-variant # the name-building process is independend from the method »class_name« database_classes requery: true consts = Array.new execute transaction: false do class_cmd = ->(s,n) do n = n.to_s.camelize consts << ActiveOrient::Model.orientdb_class( name: n) unless database_classes.include?(n) || database_classes.include?(n.underscore) { type: "cmd", language: 'sql', command: "create class #{n} extends #{s}" } end end ## class_cmd if classes.is_a?(Array) classes.map do | n | n = n.to_s.camelize # capitalize consts << ActiveOrient::Model.orientdb_class( name: n) unless database_classes.include?( n ) || database_classes.include?(n.underscore) { type: "cmd", language: 'sql', command: "create class #{n} " } end end elsif classes.is_a?(Hash) classes.keys.map do | superclass | items = Array.new superClass = superclass.to_s.camelize items << { type: "cmd", language: 'sql', command: "create class #{superClass} abstract" } unless database_classes.flatten.include?( superClass ) || database_classes.flatten.include?( superClass.underscore ) items << if classes[superclass].is_a?( String ) || classes[superclass].is_a?( Symbol ) class_cmd[superClass, classes[superclass] ] elsif classes[superclass].is_a?( Array ) classes[superclass].map{|n| class_cmd[superClass, n] } end #puts items.flatten.map{|x| x[:command]} items # returnvalue end.flatten end.compact # erase nil-entries, in case the class is already allocated end # refresh cached class-informations database_classes requery: true # returns an array of allocated Constants/Classes consts end |
#create_database(type: 'plocal', database: @database) ⇒ Object
Creates a database with the given name and switches to this database as working-database Types are either ‘plocal’ or ‘memory’
returns the name of the working-database
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/rest.rb', line 123 def create_database type: 'plocal' , database: @database logger.progname = 'OrientDB#CreateDatabase' old_d = @database @classes = [] @database = database begin response = @res[database_uri{ type }].post "" if response.code == 200 logger.info{ "Database #{@database} successfully created and stored as working database"} else @database = old_d logger.error{ "Database #{name} was NOT created. Working Database is still #{@database} "} end rescue RestClient::InternalServerError => e @database = old_d logger.error{ "Database #{name} was NOT created. Working Database is still #{@database} "} end @database end |
#create_document(o_class, attributes: {}) ⇒ Object
Creates an Object in the Database and returns this as ActuveOrient::Model-Instance
653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 |
# File 'lib/rest.rb', line 653 def create_document o_class, attributes: {} attributes = yield if attributes.empty? && block_given? post_argument = { '@class' => class_name(o_class) }.merge(attributes).to_orient begin logger.progname = 'OrientDB#CreateDocument' response = @res[ document_uri ].post post_argument.to_json data= JSON.parse( response.body ) ActiveOrient::Model.orientdb_class( name: data['@class']).new data rescue RestClient::InternalServerError => e response = JSON.parse( e.response)['errors'].pop logger.error { response['content'].split(':')[1..-1].join(':') } logger.error { "No Object allocated" } nil # return_value end end |
#create_edge_class(name, superclass: 'E') ⇒ Object
352 353 354 |
# File 'lib/rest.rb', line 352 def create_edge_class name , superclass: 'E' create_classes( { superclass => name } ).first end |
#create_index(o_class, name:, on: :automatic, type: :unique) ⇒ Object
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 |
# File 'lib/rest.rb', line 482 def create_index o_class , name:, on: :automatic, type: :unique execute transaction: false do c = class_name o_class command = if on == :automatic "create index #{c}.#{name} #{type.to_s.upcase}" elsif on.is_a? Array "create index #{name} on #{class_name(o_class)}( #{on.join(', ')}) #{type.to_s.upcase}" else nil end [ { type: "cmd", language: 'sql', command: command } ] end end |
#create_or_update_document(o_class, **args, &b) ⇒ Object
Creating a new Database-Entry ( where is omitted )
otherwise updating the Database-Entry (if present)
The optional Block should provide a hash with attributes(properties). These are used if a new dataset is created.
783 784 785 786 787 788 789 790 |
# File 'lib/rest.rb', line 783 def create_or_update_document o_class , **args, &b logger.progname = 'Rest#CreateOrUpdateDocument' r= update_or_create_documents o_class, **args, &b if r.size > 1 logger.error { "multible documents updated by #{ generate_sql_list( where )}" } end r.first # return_value end |
#create_properties(o_class, all_properties, &b) ⇒ Object
creates properties and optional an associated index as defined in the provided block
create_properties( classname or class, properties as hash ) { index }
The default-case
create_properties( :my_high_sophisticated_database_class,
con_id: { type: :integer }, details: { type: :link, linked_class: ‘Contracts’ } ) do contract_idx: :notunique end
A composite index
create_properties( :my_high_sophisticated_database_class,
con_id: { type: :integer }, symbol: { type: :string } ) do { name: ‘indexname’, on: [ :con_id , :details ] # default: all specified properties type: :notunique # default: :unique } end
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 |
# File 'lib/rest.rb', line 547 def create_properties o_class, all_properties, &b all_properties_in_a_hash = HashWithIndifferentAccess.new all_properties.each{| field, args | all_properties_in_a_hash.merge! translate_property_hash( field, args ) } begin count = if all_properties_in_a_hash.is_a?( Hash ) response = @res[ property_uri(class_name(o_class)) ].post all_properties_in_a_hash.to_json if response.code == 201 response.body.to_i else 0 end end rescue RestClient::InternalServerError => e response = JSON.parse( e.response)['errors'].pop = response['content'].split(':').last # if error_message ~= /Missing linked class/ logger.progname= 'OrientDB#CreatePropertes' logger.error { "Properties in #{class_name(o_class)} were NOT created" } logger.error { "Error-code #{response['code']} --> #{response['content'].split(':').last }" } nil end ### index if block_given? && count == all_properties_in_a_hash.size index = yield if index.is_a?( Hash ) if index.size == 1 create_index o_class, name: index.keys.first, on: all_properties_in_a_hash.keys, type: index.values.first else index_hash = HashWithIndifferentAccess.new( type: :unique, on: all_properties_in_a_hash.keys ).merge index create_index o_class, index_hash # i [:name], on: index_hash[:on], type: index_hash[:type] end end end count # return_value end |
#create_property(o_class, field, index: nil, **args) ⇒ Object
create a single property on class-level.
supported types: orientdb.com/docs/last/SQL-Create-Property.html
if index is to be specified, it’s defined in the optional block
create_property(class, field){ :unique | :notunique } --> creates an automatic-Index on the given field
create_property( class, field){ {
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 |
# File 'lib/rest.rb', line 462 def create_property o_class, field, index: nil, **args logger.progname= 'OrientDB#CreateProperty' c= create_properties o_class, {field => args} # translate_property_hash( field, args ) if index.nil? && block_given? index = yield end if c==1 && index.present? if index.is_a?( String ) || index.is_a?( Symbol ) create_index o_class, name: field, type: index elsif index.is_a? Hash bez= index.keys.first # puts "index: #{index.inspect}" # puts "bez: #{bez} ---> #{index.keys.inspect}" create_index o_class, name: bez, type: index[bez], on: [ field ] end end end |
#create_vertex_class(name, superclass: 'V') ⇒ Object
348 349 350 |
# File 'lib/rest.rb', line 348 def create_vertex_class name , superclass: 'V' create_classes( { superclass => name } ).first end |
#database_classes(include_system_classes: false, requery: false) ⇒ Object Also known as: inspect_classes
returns an array with all names of the classes of the database caches the result.
parameter: include_system_classes: false|true, requery: false|true
256 257 258 259 260 261 262 263 264 265 |
# File 'lib/rest.rb', line 256 def database_classes include_system_classes: false, requery: false requery = true if @classes.empty? if requery class_hierachie requery: true system_classes = ["OFunction", "OIdentity", "ORIDs", "ORestricted", "ORole", "OSchedule", "OTriggered", "OUser", "_studio"] all_classes = get_classes( 'name' ).map( &:values).flatten @classes = include_system_classes ? all_classes : all_classes - system_classes end @classes end |
#delete_class(o_class) ⇒ Object
deletes the specified class and returns true on success
todo: remove all instances of the class
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 |
# File 'lib/rest.rb', line 425 def delete_class o_class cl= class_name(o_class) logger.progname = 'OrientDB#DeleteClass' if database_classes.include? cl begin response = @res[class_uri{ cl } ].delete if response.code == 204 # return_value: sussess of the removal !database_classes( requery: true ).include?(cl) # don't delete the ruby-class # ActiveOrient::Model.send :remove_const, cl.to_sym if o_class.is_a?(Class) end rescue RestClient::InternalServerError => e if database_classes( requery: true).include?( cl ) logger.error{ "Class #{cl} still present" } logger.error{ e.inspect } false else true end end else logger.info { "Class #{cl} not present. "} end end |
#delete_database(database:) ⇒ Object
deletes the database and returns true on success
after the removal of the database, the working-database might be empty
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/rest.rb', line 156 def delete_database database: @classes = [] logger.progname = 'OrientDB#DropDatabase' old_ds = @database change_database database begin response = @res[database_uri].delete if database == old_ds change_database "" logger.info{ "Working database deleted" } else change_database old_ds logger.info{ "Database #{database} deleted, working database is still #{@database} "} end rescue RestClient::InternalServerError => e logger.info{ "Database #{database} NOT deleted" } change_database old_ds end !response.nil? && response.code == 204 ? true : false end |
#delete_document(record_id) ⇒ Object
671 672 673 674 675 676 677 678 679 680 681 |
# File 'lib/rest.rb', line 671 def delete_document record_id logger.progname = 'OrientDB#DeleteDocument' begin response = @res[document_uri{ record_id } ].delete true if response.code == 204 rescue RestClient::InternalServerError => e logger.error{ "Document #{ record_id } NOT deleted" } false end end |
#delete_documents(o_class, where: {}) ⇒ Object
Deletes documents. They are defined by a query. All records which match the attributes are deleted. An Array with freed index-values is returned
826 827 828 829 830 831 832 833 834 835 836 |
# File 'lib/rest.rb', line 826 def delete_documents o_class, where: {} get_documents( from: o_class, where: where).map do |doc| if doc['@type']=='d' # document index = doc['@rid'][1,doc['@rid'].size] # omit the first character ('#') r=@res[ document_uri{ index }].delete index if r.code==204 && r.body.empty? # return_value end end end |
#delete_edge(*rid) ⇒ Object
Deletes a single edge when providing a single rid-link (#00:00) Deletes multible edges when providing a list of rid-links Todo: implement delete_edges after querying the database in one statement
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 |
# File 'lib/rest.rb', line 398 def delete_edge *rid rid = rid.map do |mm| if mm.is_a?(String) if mm.rid? mm elsif mm.is_a?(Rest::Model) mm.rid else nil end end end.compact response= execute transaction: false do [ { type: "cmd", language: 'sql', command: CGI.escapeHTML("delete edge #{rid.join(',') }")} ] end if response.is_a?( Array ) && response.size == 1 response.pop # RETURN_VALUE else response end end |
#delete_property(o_class, field) ⇒ Object
585 586 587 588 589 590 591 592 593 594 595 |
# File 'lib/rest.rb', line 585 def delete_property o_class, field logger.progname = 'OrientDB#DeleteProperty' begin response = @res[property_uri( class_name(o_class)){ field } ].delete true if response.code == 204 rescue RestClient::InternalServerError => e logger.error{ "Property #{ field } in class #{ class_name(o_class) } NOT deleted" } false end end |
#execute(classname = 'Myquery', transaction: true) ⇒ Object
Executes a list of commands and returns the result-array (if present)
structure of the provided block: [{ type: “cmd”,
language: "sql",
command: "create class Person extends V"
},
(...)
]
It was first used by ActiveOrient::Query.execute_queries
Later I discovered that some Queries are not interpretated correctly by #GetDocuments
but are submitted without Error via batch-processing.
For Instance, this valid query
> 'select expand( first_list[5].second_list[9] ) from base where label = 9 ' <
can only be submitted via batch
933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 |
# File 'lib/rest.rb', line 933 def execute classname = 'Myquery', transaction: true #puts "classname##execute:: #{classname}" batch = { transaction: transaction, operations: yield } unless batch[:operations].blank? # puts "post: #{batch.to_json}" response = @res[ batch_uri ].post batch.to_json # puts "response: #{JSON.parse(response.body)['result'].inspect}" if response.code == 200 if response.body['result'].present? result= JSON.parse(response.body)['result'] result.map do |x| if x.is_a? Hash if x.has_key?('@class') ActiveOrient::Model.orientdb_class( name: x['@class']).new x elsif x.has_key?( 'value' ) x['value'] else # puts "ActiveOrient::Execute" # puts "o_class: #{o_class.inspect}" ActiveOrient::Model.orientdb_class( name: classname).new x end end end.compact # return_value else response.body end else nil end end rescue RestClient::InternalServerError => e raise end |
#fv(s) ⇒ Object
:nodoc:
240 241 242 |
# File 'lib/rest.rb', line 240 def fv s # :nodoc: @all_classes.find_all{ |x| x[ 'superClass' ]== s }.map{| v| v[ 'name' ]} #.camelize } end |
#fx(v) ⇒ Object
:nodoc:
244 245 246 |
# File 'lib/rest.rb', line 244 def fx v # :nodoc: fv(v).map{ |x| ar = fx( x ) ; ar.empty? ? x : [ x , ar ] } end |
#get_class_properties(o_class) ⇒ Object
:nodoc:
597 598 599 |
# File 'lib/rest.rb', line 597 def get_class_properties o_class # :nodoc: JSON.parse( @res[ class_uri{ class_name(o_class) } ].get ) end |
#get_classes(*attributes) ⇒ Object
returns an Array with (unmodified) Class-attribute-hash-Elements
get_classes 'name', 'superClass'
returns
[ {"name"=>"E", "superClass"=>""},
{"name"=>"OFunction", "superClass"=>""},
{"name"=>"ORole", "superClass"=>"OIdentity"}
(...)
]
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/rest.rb', line 200 def get_classes *attributes i = 0 begin #puts "database_uri #{database_uri}" response = @res[database_uri].get if response.code == 200 classes= JSON.parse( response.body )['classes' ] unless attributes.empty? classes.map{|y| y.select{| v,_| attributes.include?(v) } } else classes end #.map{ |y| y.name } else [] end rescue JSON::ParserError if i.zero? i = i + 1 retry else raise end end end |
#get_databases ⇒ Object
returns an Array with available Database-Names as Elements
113 114 115 |
# File 'lib/rest.rb', line 113 def get_databases JSON.parse( @res["/listDatabases"].get.body)['databases'] end |
#get_document(rid) ⇒ Object
Retrieves a Document from the Database as ActiveOrient::Model::class The argument can either be a rid (#[x}:y) or a link(x:y) If no Document is found, nil is returned
In the optional block, a subset of properties can be defined (as array of names)
844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 |
# File 'lib/rest.rb', line 844 def get_document rid rid = rid[1 .. rid.length] if rid[0]=='#' response = @res[ document_uri { rid } ].get raw_data = JSON.parse( response.body) #.merge( "#no_links" => "#no_links" ) ActiveOrient::Model.orientdb_class( name: raw_data['@class']).new raw_data rescue RestClient::InternalServerError => e if e.http_body.split(':').last =~ /was not found|does not exist in database/ nil else logger.progname 'OrientDB#GetDocument' logger.error "something went wrong" logger.error e.http_body.inspect raise end end |
#get_documents(raw: false, query: nil, **args) ⇒ Object
retrieves documents from a query
If raw is specified, the JSON-Array is returned, eg
{ "@type"=>"d",
"@rid"=>"#15:1",
"@version"=>1,
"@class"=>"DocumebntKlasse10",
"con_id"=>343,
"symbol"=>"EWTZ"
}
otherwise a ActiveModel-Instance of o_class is created and returned
695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 |
# File 'lib/rest.rb', line 695 def get_documents raw: false, query: nil, **args query = OrientSupport::OrientQuery.new( args ) if query.nil? i=0 begin logger.progname = 'OrientDB#GetDocuments' url = query_sql_uri + query.compose( destination: :rest) + "/#{query.get_limit}" response = @res[URI.encode(url) ].get r=JSON.parse( response.body )['result'].map do |document | # parameter: raw is set --> don't initilize a model object if raw document # query returns an anonymus class: Use the provided Block or the Dummy-Model MyQuery elsif document['@class'].blank? block_given? ? yield.new( document ) : ActiveOrient::Model::MyQuery.new( document ) else ActiveOrient::Model.orientdb_class( name: document['@class']).new document end end rescue RestClient::InternalServerError => e response = JSON.parse( e.response)['errors'].pop logger.error { response['content'].split(':').last } i=i+1 if i > 1 raise else query.dataset_name = query.database_class.underscore logger.info { "trying to query using #{o_class}" } retry end rescue URI::InvalidURIError => e logger.error "Invalid URI detected" logger.error query.to_s logger.info "trying batch processing " sql_cmd = -> (command) { { type: "cmd", language: "sql", command: command } } response= execute { [ sql_cmd[ query.to_s ] ] } logger.info "success: to avoid this delay use ActiveOrient::Model#query_database insteed" response end end |
#get_ressource ⇒ Object
called in the beginning or after a 404-Error
69 70 71 72 73 |
# File 'lib/rest.rb', line 69 def get_ressource login = [ default_server[:user].to_s , default_server[:password].to_s ] server_adress = [ default_server[:protocol] ,"://" , default_server[ :server ], ":" , default_server[ :port ]].map(&:to_s).join('') RestClient::Resource.new( server_adress, *login ) end |
#logger ⇒ Object
borrowed from active_support
27 |
# File 'lib/rest.rb', line 27 mattr_accessor :logger |
#nexus_edge(o_class, attributes: {}, from:, to:, unique: false) ⇒ Object
nexus_edge connects two documents/vertexes The parameter o_class can be either a class or a string
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 |
# File 'lib/rest.rb', line 361 def nexus_edge o_class , attributes: {}, from:, to:, unique: false logger.progname = "ActiveOrient::OrientDB#NexusEdge" if from.is_a? Array from.map{|f| nexus_edge o_class, attributes: attributes, from: f, to: to, unique: unique } elsif to.is_a? Array to.map{|t| nexus_edge o_class, attributes: attributes, from: from, to: t, unique: unique } else if unique wwhere = { out: from.to_orient, in: to.to_orient }.merge(attributes.to_orient) existing_edge = get_documents( from: o_class, where: wwhere ) if existing_edge.first.is_a?( ActiveOrient::Model ) logger.debug { "reusing edge #{class_name(o_class)} from #{from.to_orient} to #{to.to_orient} " } return existing_edge.first end end logger.debug { "creating edge #{class_name(o_class)} from #{from.to_orient} to #{to.to_orient} " } response= execute( o_class, transaction: false) do #[ { type: "cmd", language: 'sql', command: CGI.escapeHTML("create edge #{class_name(o_class)} from #{translate_to_rid[m]} to #{to.to_orient}; ")} ] attr_string = attributes.blank? ? "" : "set #{ generate_sql_list attributes.to_orient }" [ { type: "cmd", language: 'sql', command: "create edge #{class_name(o_class)} from #{from.to_orient} to #{to.to_orient} #{attr_string}"} ] end if response.is_a?(Array) && response.size == 1 response.pop # RETURN_VALUE else response end end end |
#patch_document(rid) ⇒ Object
Lazy Updating of the given Document.
866 867 868 869 870 871 872 873 874 875 876 877 878 |
# File 'lib/rest.rb', line 866 def patch_document rid logger.progname = 'Rest#PatchDocument' content = yield if content.is_a? Hash content.each do | key, value | # puts "content: #{key}, #{value.class}" # content[key]= value.to_orient #if value.is_a? ActiveOrient::Model end @res[ document_uri { rid } ].patch content.to_orient.to_json else logger.error { "FAILED: The Block must provide an Hash with properties to be updated"} end end |
#preallocate_class_properties(o_class) ⇒ Object
If properties are allocated on class-level, they can be preinitialized using this method. This is disabled for now, because it does not seem nessesary
630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 |
# File 'lib/rest.rb', line 630 def preallocate_class_properties o_class p= get_class_properties( o_class )['properties'] unless p.nil? || p.blank? predefined_attributes = p.map do | property | [ property['name'] , case property['type'] when 'LINKMAP' Array.new when 'STRING' '' else nil end ] end.to_h else {} end end |
#print_class_properties(o_class) ⇒ Object
601 602 603 604 605 606 607 608 |
# File 'lib/rest.rb', line 601 def print_class_properties o_class puts "Detected Properties for class #{class_name(o_class)}" rp = get_class_properties o_class n= rp['name'] puts rp['properties'].map{|x| [ n+'.'+x['name'], x['type'],x['linkedClass'] ].compact.join(' -> ' )}.join("\n") end |
#ressource ⇒ Object
included for development , should be removed in production release
63 64 65 |
# File 'lib/rest.rb', line 63 def ressource @res end |
#update_documents(o_class, set:, where: {}) ⇒ Object
891 892 893 894 |
# File 'lib/rest.rb', line 891 def update_documents o_class, set: , where: {} url = "update #{class_name(o_class)} set "<< generate_sql_list(set) << compose_where(where) response = @res[ URI.encode( command_sql_uri << url) ].post '' #url.to_json end |
#update_or_create_documents(o_class, set: {}, where: {}, **args, &b) ⇒ Object
Based on the query specified in :where records are updated according to :set
Returns an Array of updated documents
The optional Block should provide a hash with attributes(properties). These are used if a new dataset is created.
### das ist noch nicht rund. #
802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 |
# File 'lib/rest.rb', line 802 def update_or_create_documents o_class , set: {}, where: {} , **args , &b logger.progname = 'Rest#UpdateOrCreateDocuments' if where.blank? [ create_document( o_class, attributes: set ) ] else set.extract!( where.keys ) # removes any keys from where in set possible_documents = get_documents from: class_name( o_class ), where: where, **args if possible_documents.empty? if block_given? more_where = yield # do Preparations prior to the creation of the dataset # if the block returns a Hash , it is merged into the insert_query. where.merge! more_where if more_where.is_a?(Hash) end [ create_document( o_class, attributes: set.merge(where) ) ] else possible_documents.map{| doc | doc.update( set: set ) } end end end |