active-orient 0.42 → 0.79
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/Gemfile +13 -5
- data/Guardfile +12 -4
- data/README.md +67 -280
- data/VERSION +1 -1
- data/active-orient.gemspec +6 -5
- data/bin/active-orient-0.6.gem +0 -0
- data/bin/active-orient-console +85 -0
- data/config/boot.rb +72 -1
- data/config/config.yml +10 -0
- data/config/connect.yml +9 -4
- data/examples/books.rb +92 -40
- data/examples/streets.rb +89 -85
- data/examples/test_commands.rb +97 -0
- data/examples/test_commands_2.rb +59 -0
- data/examples/test_commands_3.rb +55 -0
- data/examples/test_commands_4.rb +33 -0
- data/examples/time_graph.md +162 -0
- data/lib/active-orient.rb +75 -9
- data/lib/base.rb +238 -169
- data/lib/base_properties.rb +68 -60
- data/lib/class_utils.rb +226 -0
- data/lib/database_utils.rb +98 -0
- data/lib/init.rb +79 -0
- data/lib/java-api.rb +442 -0
- data/lib/jdbc.rb +211 -0
- data/lib/model/custom.rb +26 -0
- data/lib/model/edge.rb +70 -0
- data/lib/model/model.rb +134 -0
- data/lib/model/the_class.rb +607 -0
- data/lib/model/the_record.rb +266 -0
- data/lib/model/vertex.rb +236 -0
- data/lib/orientdb_private.rb +48 -0
- data/lib/other.rb +371 -0
- data/lib/railtie.rb +68 -0
- data/lib/rest/change.rb +147 -0
- data/lib/rest/create.rb +279 -0
- data/lib/rest/delete.rb +134 -0
- data/lib/rest/operations.rb +211 -0
- data/lib/rest/read.rb +171 -0
- data/lib/rest/rest.rb +112 -0
- data/lib/rest_disabled.rb +24 -0
- data/lib/support/logging.rb +38 -0
- data/lib/support/orient.rb +196 -0
- data/lib/support/orientquery.rb +469 -0
- data/rails.md +154 -0
- data/rails/activeorient.rb +32 -0
- data/rails/config.yml +10 -0
- data/rails/connect.yml +17 -0
- metadata +65 -24
- data/active-orient-0.4.gem +0 -0
- data/active-orient-0.41.gem +0 -0
- data/lib/model.rb +0 -468
- data/lib/orient.rb +0 -98
- data/lib/query.rb +0 -88
- data/lib/rest.rb +0 -1059
- data/lib/support.rb +0 -372
- data/test.rb +0 -4
- data/usecase.md +0 -91
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.79
|
data/active-orient.gemspec
CHANGED
@@ -8,10 +8,10 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.email = ["topofocus@gmail.com"]
|
9
9
|
s.homepage = 'https://github.com/topofocus/active-orient'
|
10
10
|
s.licenses = ['MIT']
|
11
|
-
s.summary = 'Pure ruby client for OrientDB based on ActiveModel'
|
12
|
-
s.description = 'Persistent ORM for OrientDB, based on ActiveModel'
|
11
|
+
s.summary = 'Pure ruby client for OrientDB(V.3) based on ActiveModel'
|
12
|
+
s.description = 'Persistent ORM for OrientDB(V.3), based on ActiveModel. Rails 5 compatible'
|
13
13
|
s.platform = Gem::Platform::RUBY
|
14
|
-
s.required_ruby_version = '>= 2.
|
14
|
+
s.required_ruby_version = '>= 2.5'
|
15
15
|
s.date = Time.now.strftime "%Y-%m-%d"
|
16
16
|
s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
|
17
17
|
s.require_paths = ["lib"]
|
@@ -21,7 +21,8 @@ Gem::Specification.new do |s|
|
|
21
21
|
|
22
22
|
s.add_development_dependency "bundler", "~> 1.8"
|
23
23
|
s.add_development_dependency "rake", "~> 10.0"
|
24
|
-
s.add_dependency 'activesupport'
|
25
|
-
s.add_dependency '
|
24
|
+
s.add_dependency 'activesupport'#, "~> 4.2"
|
25
|
+
s.add_dependency 'activemodel'#, "~> 4.2"
|
26
|
+
s.add_dependency 'rest-client'
|
26
27
|
|
27
28
|
end
|
Binary file
|
@@ -0,0 +1,85 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
## loads the active-orient environment
|
3
|
+
## and starts an interactive shell
|
4
|
+
##
|
5
|
+
## Parameter:
|
6
|
+
## production (p)
|
7
|
+
## development (d) [default]
|
8
|
+
## test (t)
|
9
|
+
require 'bundler/setup'
|
10
|
+
require 'yaml'
|
11
|
+
require 'logger'
|
12
|
+
require 'active-orient'
|
13
|
+
config_file = File.expand_path('../../config/connect.yml', __FILE__)
|
14
|
+
connectyml = if File.exist?(config_file)
|
15
|
+
YAML.load_file( config_file )[:orientdb]
|
16
|
+
else
|
17
|
+
puts "config/connect.yml not found "
|
18
|
+
puts "using defaults"
|
19
|
+
{ server: 'localhost', port: 2480,
|
20
|
+
database: { development: 'GratefulDeadConcerts',
|
21
|
+
production: 'hcn_data',
|
22
|
+
test: 'temp'},
|
23
|
+
admin: { user: 'root', pass: 'root' } }
|
24
|
+
end
|
25
|
+
|
26
|
+
e= ARGV.present? ? ARGV.last.downcase : 'development'
|
27
|
+
env = if e =~ /^p/
|
28
|
+
:production
|
29
|
+
elsif e =~ /^t/
|
30
|
+
:test
|
31
|
+
else
|
32
|
+
:development
|
33
|
+
end
|
34
|
+
begin
|
35
|
+
ORD = ActiveOrient::Init.connect database: connectyml[:database][env].to_s,
|
36
|
+
user: connectyml[:admin][:user].to_s,
|
37
|
+
password: connectyml[:admin][:pass].to_s,
|
38
|
+
server: connectyml[:server].to_s
|
39
|
+
ActiveOrient::Base.logger.level = Logger::INFO
|
40
|
+
ActiveOrient::Model.keep_models_without_file = true
|
41
|
+
ActiveOrient::OrientDB.new model_dir: 'lib/model'
|
42
|
+
rescue RestClient::Unauthorized
|
43
|
+
puts "Cannot connect to the server. Wrong credentials"
|
44
|
+
Kernel.exit
|
45
|
+
rescue Errno::ECONNREFUSED
|
46
|
+
puts "Database Server is not running on #{connectyml[:server]} "
|
47
|
+
Kernel.exit
|
48
|
+
end
|
49
|
+
|
50
|
+
class Array
|
51
|
+
# Method missing enables fancy stuff like
|
52
|
+
# Jahr[2000 .. 2005].monat(5..7).value
|
53
|
+
#
|
54
|
+
# its included only in the console, for inspection purposes
|
55
|
+
|
56
|
+
# def method_missing(method, *key)
|
57
|
+
# unless method == :to_hash || method == :to_str #|| method == :to_int
|
58
|
+
# return self.map{|x| x.public_send(method, *key)}
|
59
|
+
# end
|
60
|
+
|
61
|
+
# end
|
62
|
+
end # Array
|
63
|
+
|
64
|
+
|
65
|
+
puts "ORD points to the REST-Instance, Database: #{ActiveOrient.database}"
|
66
|
+
#puts "DB is the API-Instance of the database, DB.db gets the DB-Api-base " if RUBY_PLATFORM == 'java'
|
67
|
+
|
68
|
+
puts '-'* 45
|
69
|
+
ns= case ActiveOrient::Model.namespace
|
70
|
+
when Object
|
71
|
+
"No Prefix, just ClassName#CamelCase"
|
72
|
+
else
|
73
|
+
ActiveOrient::Model.namespace.to_s + "{ClassName.camelcase}"
|
74
|
+
end
|
75
|
+
puts "Namespace for model-classes : #{ns}"
|
76
|
+
puts "Present Classes (Hierarchy) "
|
77
|
+
|
78
|
+
puts ORD.class_hierarchy.to_yaml
|
79
|
+
puts ActiveOrient::show_classes
|
80
|
+
|
81
|
+
include OrientDB
|
82
|
+
|
83
|
+
require 'irb'
|
84
|
+
ARGV.clear
|
85
|
+
IRB.start(__FILE__)
|
data/config/boot.rb
CHANGED
@@ -1,6 +1,77 @@
|
|
1
|
+
#### sample boot file ####
|
2
|
+
|
3
|
+
|
4
|
+
|
1
5
|
require 'bundler/setup'
|
2
6
|
require 'yaml'
|
7
|
+
if RUBY_VERSION == 'java'
|
8
|
+
require 'orientdb'
|
9
|
+
end
|
10
|
+
require "active-orient"
|
3
11
|
project_root = File.expand_path('../..', __FILE__)
|
4
|
-
|
12
|
+
begin
|
13
|
+
connect_file = File.expand_path('../../config/connect.yml', __FILE__)
|
14
|
+
config_file = File.expand_path('../../config/config.yml', __FILE__)
|
15
|
+
connectyml = YAML.load_file( connect_file )[:orientdb][:admin] if connect_file.present?
|
16
|
+
configyml = YAML.load_file( config_file )[:active_orient] if config_file.present?
|
17
|
+
databaseyml = YAML.load_file( connect_file )[:orientdb][:database] if connect_file.present?
|
18
|
+
rescue Errno::ENOENT
|
19
|
+
puts "config/connectyml not present"
|
20
|
+
puts "Using defaults to connect database-server"
|
21
|
+
end
|
22
|
+
|
23
|
+
e= ARGV.present? ? ARGV.last.downcase : 'development'
|
24
|
+
env = if e =~ /^p/
|
25
|
+
:production
|
26
|
+
elsif e =~ /^t/
|
27
|
+
:test
|
28
|
+
else
|
29
|
+
:development
|
30
|
+
end
|
31
|
+
puts "Using #{env}-environment"
|
32
|
+
|
33
|
+
log_file = if File.exist?(config_file)
|
34
|
+
dev = YAML.load_file( connect_file )[:orientdb][:logger]
|
35
|
+
if dev.blank? || dev== 'stdout'
|
36
|
+
'/dev/stdout'
|
37
|
+
else
|
38
|
+
project_root+'/log/'+env+'.log'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
logger = Logger.new(log_file)
|
44
|
+
logger.level = case env
|
45
|
+
when :production
|
46
|
+
Logger::ERROR
|
47
|
+
when :development
|
48
|
+
Logger::WARN
|
49
|
+
else
|
50
|
+
Logger::INFO
|
51
|
+
end
|
52
|
+
logger.formatter = proc do |severity, datetime, progname, msg|
|
53
|
+
"#{datetime.strftime("%d.%m.(%X)")}#{"%5s" % severity}->#{msg}\n"
|
54
|
+
end
|
55
|
+
|
56
|
+
ORD = ActiveOrient::Init.connect database: databaseyml[env],
|
57
|
+
user: connectyml[:user].to_s,
|
58
|
+
password: connectyml[:pass].to_s,
|
59
|
+
server: '172.28.50.25',
|
60
|
+
logger: logger
|
61
|
+
|
62
|
+
|
63
|
+
|
64
|
+
ActiveOrient::Model.keep_models_without_file = true
|
65
|
+
ActiveOrient::Init.define_namespace yml: configyml, namespace: @namespace
|
66
|
+
ActiveOrient::OrientDB.new preallocate: true,
|
67
|
+
model_dir: "#{project_root}/#{ configyml.present? ? configyml[:model_dir] : "model" }"
|
68
|
+
|
69
|
+
if RUBY_PLATFORM == 'java'
|
70
|
+
DB = ActiveOrient::API.new preallocate: false
|
71
|
+
else
|
72
|
+
DB = ORD
|
73
|
+
end
|
74
|
+
|
75
|
+
|
5
76
|
|
6
77
|
|
data/config/config.yml
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
---
|
2
|
+
:active_orient:
|
3
|
+
## Namespace: Prefix of Model-Objects. :self -> ActiveOrient::Model::{name}
|
4
|
+
## :object => No Prefix
|
5
|
+
## :active_orient => ActiveOrient::{name}
|
6
|
+
:namespace: :object
|
7
|
+
## model_dir: Path to model-files relative to the root of the application
|
8
|
+
## ie. app/model or model
|
9
|
+
:model_dir: 'lib/model'
|
10
|
+
|
data/config/connect.yml
CHANGED
@@ -1,13 +1,18 @@
|
|
1
1
|
---
|
2
2
|
:orientdb:
|
3
|
-
:server:
|
3
|
+
:server: 172.28.50.25
|
4
|
+
# localhost # 172.28.50.109 # localhost #mailout.halfgarten-capital.de
|
4
5
|
:port: 2480
|
5
|
-
:
|
6
|
+
:logger: stdout # 'file' or 'stdout'
|
7
|
+
:database:
|
8
|
+
:development: GratefulDeadConcerts
|
9
|
+
:production: hcn_data
|
10
|
+
:test: temp
|
6
11
|
:admin:
|
7
12
|
:user: hctw
|
8
|
-
:pass:
|
13
|
+
:pass: hc
|
9
14
|
:auth:
|
10
15
|
:user: topo
|
11
|
-
:pass:
|
16
|
+
:pass: focus
|
12
17
|
|
13
18
|
# hfx: 101
|
data/examples/books.rb
CHANGED
@@ -5,74 +5,126 @@ There are several Books. And there is a Table with Keywords. These are our Verte
|
|
5
5
|
|
6
6
|
The Keywords are associated to the books, this is realized via an Edge »has_content«
|
7
7
|
|
8
|
-
This Example demonstrates how
|
8
|
+
This Example demonstrates how create a simple graph:
|
9
|
+
|
10
|
+
Book --> HasContent --> KeyWord
|
11
|
+
|
12
|
+
and to query it dynamically using OrientSupport::OrientQuery
|
13
|
+
|
14
|
+
REQUIREMENT: Configurate config/connectyml (admin/user+pass)
|
15
|
+
|
16
|
+
There are 3 default search items provided. They are used if no parameter is given.
|
17
|
+
However, any parameter given is transmitted as serach-criteria, ie.
|
18
|
+
ruby books.rb Juli August
|
19
|
+
defines two search criteria.
|
20
|
+
|
9
21
|
=end
|
22
|
+
|
10
23
|
class BooksExample
|
11
24
|
|
12
|
-
def initialize
|
25
|
+
def initialize rebuild: true
|
13
26
|
if rebuild
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
27
|
+
print "\n === REBUILD === \n"
|
28
|
+
## check wether the database tables exist. Then delete Database-Class and preallocated ruby-Object
|
29
|
+
database_classes = [ :book, :keyword, :has_content ]
|
30
|
+
puts "allocated-database-classes: #{ORD.database_classes.join(" , ")} "
|
31
|
+
if database_classes.map{|c| ORD.database_classes.include?( c.to_s ) ? c : nil }.compact.size == 3
|
32
|
+
print " deleting database tables \n"
|
33
|
+
database_classes.each{ | c | d_class= c.to_s.classify.constantize # works if namespace=Object
|
34
|
+
d_class.delete_class if d_class.present? }
|
35
|
+
else
|
36
|
+
puts " omitting deletion of database-classes "
|
37
|
+
end
|
38
|
+
print " creating Book and Keyword as Vertex; HasContent as Edge \n"
|
39
|
+
ORD.create_vertex_class :book, :keyword
|
40
|
+
ORD.create_edge_class :has_content
|
41
|
+
print "\n === PROPERTY === \n"
|
42
|
+
Keyword.create_property :item, type: :string, index: :unique
|
43
|
+
Book.create_property :title, type: :string, index: :unique
|
44
|
+
print "\n === Unique Edges === \n"
|
45
|
+
HasContent.uniq_index
|
22
46
|
end
|
23
47
|
end
|
24
48
|
|
25
49
|
|
26
50
|
def read_samples
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
51
|
+
print "\n === READ SAMPLES === \n"
|
52
|
+
## Lambda fill databasea
|
53
|
+
# Anaylse a sentence
|
54
|
+
# Split into words and upsert them to Word-Class.
|
55
|
+
# The Block is only performed, if a new Word is inserted.
|
56
|
+
fill_database = ->(sentence, this_book ) do
|
57
|
+
|
58
|
+
sentence.split(' ').map do | word |
|
59
|
+
Keyword.upsert where: { item: word } do | new_keyword |
|
60
|
+
HasContent.create from: this_book, to: new_keyword
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
32
64
|
end
|
33
|
-
|
65
|
+
## Lambda end
|
66
|
+
words = 'Die Geschäfte in der Industrie im wichtigen US-Bundesstaat New York sind im August so schlecht gelaufen wie seit mehr als sechs Jahren nicht mehr Der entsprechende Empire-State-Index fiel überraschend von plus Punkten im Juli auf minus 14,92 Zähler Dies teilte die New Yorker Notenbank Fed heute mit. Bei Werten im positiven Bereich signalisiert das Barometer ein Wachstum Ökonomen hatten eigentlich mit einem Anstieg auf 5,0 Punkte gerechnet'
|
34
67
|
this_book = Book.create title: 'first'
|
35
68
|
fill_database[ words, this_book ]
|
36
69
|
|
37
70
|
words2 = 'Das Bruttoinlandsprodukt BIP in Japan ist im zweiten Quartal mit einer aufs Jahr hochgerechneten Rate von Prozent geschrumpft Zu Jahresbeginn war die nach den USA und China drittgrößte Volkswirtschaft der Welt noch um Prozent gewachsen Der Schwächeanfall wird auch als Rückschlag für Ministerpräsident Shinzo Abe gewertet der das Land mit einem Mix aus billigem Geld und Konjunkturprogramm aus der Flaute bringen will Allerdings wirkte sich die heutige Veröffentlichung auf die Märkten nur wenig aus da Ökonomen mit einem schwächeren zweiten Quartal gerechnet hatten'
|
38
71
|
this_book = Book.create title: 'second'
|
39
72
|
fill_database[ words2, this_book ]
|
73
|
+
puts "#{Keyword.count} keywords inserted into Database"
|
40
74
|
end
|
41
|
-
|
75
|
+
|
42
76
|
def display_books_with *desired_words
|
43
|
-
|
44
|
-
|
77
|
+
|
78
|
+
## Each serach criteria becomes a subquery
|
79
|
+
## This is integrated into the main_query using 'let'.
|
80
|
+
## Subquery: let ${a-y} = select expand(in('has_content')) from keyword where item = {search_word}
|
81
|
+
## combine with intercect: $z = Intercect( $a ... $y )
|
82
|
+
## Main Query is just
|
83
|
+
## select expand( $z ) followed by all let-statements and finalized by "intercect"
|
84
|
+
#
|
85
|
+
print("\n === display_books_with » #{ desired_words.join "," } « === \n")
|
86
|
+
main_query = OrientSupport::OrientQuery.new projection: 'expand( $z )'
|
45
87
|
|
46
88
|
intersects = Array.new
|
47
89
|
desired_words.each_with_index do | word, i |
|
48
|
-
symbol = ( i+97 ).chr # convert 1 -> 'a'
|
49
|
-
|
50
|
-
|
51
|
-
|
90
|
+
symbol = ( i+97 ).chr # convert 1 -> 'a', 2 -> 'b' ...
|
91
|
+
subquery = OrientSupport::OrientQuery.new from: Keyword, projection: "expand(in('has_content'))"
|
92
|
+
subquery.where = { item: word }
|
93
|
+
main_query.let << { symbol => subquery }
|
94
|
+
intersects << "$#{symbol}"
|
52
95
|
end
|
53
|
-
|
96
|
+
main_query.let << "$z = Intersect(#{intersects.join(', ')}) "
|
54
97
|
puts "generated Query:"
|
55
|
-
puts
|
56
|
-
result = Keyword.query_database
|
98
|
+
puts main_query.compose
|
99
|
+
result = Keyword.query_database main_query, set_from: false
|
100
|
+
puts '-' * 23
|
57
101
|
puts "found books: "
|
58
|
-
puts result.map( &:title ).join("; ")
|
59
|
-
|
102
|
+
puts result.map( &:title ).join("; ")
|
103
|
+
if result.empty?
|
104
|
+
puts " -- None -- "
|
105
|
+
puts " try » ruby books.rb japan flaute « for a positive search in one of the two sentences"
|
106
|
+
else
|
107
|
+
puts '-_' * 23
|
108
|
+
puts "that's it folks"
|
109
|
+
end
|
60
110
|
end
|
61
111
|
end
|
62
112
|
|
63
113
|
if $0 == __FILE__
|
64
114
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
115
|
+
search_items = ARGV.empty? ? ['China', 'aus', 'Flaute'] : ARGV
|
116
|
+
ARGV = [ 'd' ] # development-mode
|
117
|
+
@configDatabase = 'BookTest'
|
118
|
+
|
119
|
+
require '../config/boot'
|
120
|
+
|
121
|
+
# search_items = ARGV.empty? ? ['China', 'aus', 'Flaute'] : ARGV
|
122
|
+
b = BooksExample.new rebuild: true
|
123
|
+
|
124
|
+
# ORD.create_vertex_class "Book", "Keyword"
|
125
|
+
# ORD.create_edge_class 'has_content'
|
126
|
+
|
76
127
|
b.read_samples if Keyword.count.zero?
|
77
|
-
b.display_books_with
|
128
|
+
b.display_books_with *search_items
|
129
|
+
|
78
130
|
end
|
data/examples/streets.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
=begin
|
2
|
-
Streets Example
|
2
|
+
---> The Streets Example does not work as the structure of external data used changed!
|
3
3
|
|
4
|
+
Streets Example
|
4
5
|
|
5
6
|
We load german cities from wikipedia and parse the document for cities and countries(states).
|
6
7
|
Further we load a collection of popular streetnames from a web-side called »strassen-in-deutschland«
|
@@ -15,115 +16,118 @@ At last we print the connected cities.
|
|
15
16
|
module DataImport
|
16
17
|
def read_german_street_names
|
17
18
|
doc = Nokogiri::HTML(open('http://www.strassen-in-deutschland.de/die-haeufigsten-strassennamen-in-deutschland.html'))
|
18
|
-
strassen = doc.css('
|
19
|
+
strassen = doc.css("td[data-header='Straßenname: '] a") # identified via css-inspector in browser
|
19
20
|
# search for the css and include only links, then display the text-part
|
20
21
|
strassen.children.map( &:to_s )[3..-1] # omit the first three (strassen in deutschland, straßenverzeichnis, straßen)
|
21
22
|
end
|
22
23
|
|
23
|
-
def read_german_cities_from_wikipedia
|
24
|
-
# we extract <li> -elements and use the text until "("
|
24
|
+
def read_german_cities_from_wikipedia
|
25
|
+
# we extract <li> -elements and use the text until "("
|
25
26
|
#doc.xpath("//li").at(80)
|
26
|
-
# => #<Nokogiri::XML::Element:0x1ba551c name="li" children=[#<Nokogiri::XML::Element:0x1ba533c name="a" attributes=[#<Nokogiri::XML::Attr:0x1ba52d8 name="href" value="/wiki/Angerm%C3%BCnde">, #<Nokogiri::XML::Attr:0x1ba52c4 name="title" value="Angermünde">] children=[#<Nokogiri::XML::Text:0x1ba4c84 "Angermünde">]>, #<Nokogiri::XML::Text:0x1ba4ae0 " (Brandenburg)">]>
|
27
|
+
# => #<Nokogiri::XML::Element:0x1ba551c name="li" children=[#<Nokogiri::XML::Element:0x1ba533c name="a" attributes=[#<Nokogiri::XML::Attr:0x1ba52d8 name="href" value="/wiki/Angerm%C3%BCnde">, #<Nokogiri::XML::Attr:0x1ba52c4 name="title" value="Angermünde">] children=[#<Nokogiri::XML::Text:0x1ba4c84 "Angermünde">]>, #<Nokogiri::XML::Text:0x1ba4ae0 " (Brandenburg)">]>
|
27
28
|
|
28
29
|
doc = Nokogiri::HTML(open('https://en.wikipedia.org/wiki/List_of_cities_and_towns_in_Germany'))
|
30
|
+
print doc
|
29
31
|
doc.xpath("//li").map{|x| x.text[0 .. x.text.index('(')-2] if x.text.index('(').present? }.compact
|
30
32
|
end
|
31
33
|
|
32
|
-
def
|
34
|
+
def read_german_cities_and_states_from_wikipedia
|
33
35
|
doc =
|
34
|
-
|
35
|
-
doc.xpath("//li").map do |x|
|
36
|
-
if x.text.index('(').present?
|
37
|
-
|
36
|
+
Nokogiri::HTML(open('https://en.wikipedia.org/wiki/List_of_cities_and_towns_in_Germany'))
|
37
|
+
doc.xpath("//li").map do |x|
|
38
|
+
if x.text.index('(').present?
|
39
|
+
[ x.text[0 .. x.text.index('(')-2] , x.text[ x.text.index('(')+1 .. x.text.index(')')-1] ]
|
38
40
|
end
|
39
41
|
end.compact
|
40
|
-
end
|
42
|
+
end
|
41
43
|
|
42
44
|
end # module
|
43
45
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
ActiveOrient::Model::Connects.create_property :distance, type: :integer, index: :notunique
|
66
|
-
ActiveOrient::OrientDB.logger.info { "Vertex- and Edge-Classes rebuilded" }
|
67
|
-
end
|
46
|
+
class StreetExample
|
47
|
+
|
48
|
+
include DataImport
|
49
|
+
def initialize db, rebuild: true
|
50
|
+
if rebuild
|
51
|
+
db.delete_class :State
|
52
|
+
db.delete_class :City
|
53
|
+
db.delete_class :Street
|
54
|
+
db.delete_class :CONNECTS
|
55
|
+
db.create_vertex_class :state, :city, :street
|
56
|
+
db.create_edge_class :CONNECTS
|
57
|
+
State.create_property( :name, type: :string, index: :unique )
|
58
|
+
City.create_properties( { name: { type: :string },
|
59
|
+
state: { type: :link, :linked_class => 'State' } }
|
60
|
+
) do
|
61
|
+
{ citi_idx: :unique }
|
62
|
+
end
|
63
|
+
Street.create_property :name , type: :string, index: :notunique
|
64
|
+
CONNECTS.create_property :distance, type: :integer, index: :notunique
|
65
|
+
logger.progname = "StreetsExample#Initialize"
|
66
|
+
logger.info { "Vertex- and Edge-Classes rebuilded" }
|
68
67
|
end
|
68
|
+
end
|
69
69
|
|
70
70
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
end
|
88
|
-
C.create_edge :from => street_record, :to => cities
|
71
|
+
def read_from_web
|
72
|
+
read_german_cities_and_states_from_wikipedia.each do |city,state|
|
73
|
+
state = State.update_or_create( where: { name: state }).first
|
74
|
+
City.create name: city, state: "##{state.rid}"
|
75
|
+
end
|
76
|
+
logger.progname = "StreetsExample#ReadFromWeb"
|
77
|
+
logger.info { "#{City.count} Cities imported from Wikipedia " }
|
78
|
+
|
79
|
+
cities_rids = City.all.map &:rid
|
80
|
+
read_german_street_names.each_with_index do |street, i|
|
81
|
+
street_record = Street.create name: street
|
82
|
+
count = i
|
83
|
+
cities = Array.new
|
84
|
+
while count < cities_rids.size && cities.size < 5 do
|
85
|
+
cities << cities_rids[count]
|
86
|
+
count = count + i
|
89
87
|
end
|
90
|
-
|
88
|
+
CONNECTS.create_edge :from => street_record, :to => cities
|
91
89
|
end
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
90
|
+
logger.progname = "StreetsExample#ReadFromWeb"
|
91
|
+
logger.info { "#{CONNECTS.count} Edges between Streets and Cities created " }
|
92
|
+
end
|
93
|
+
|
94
|
+
def display_streets_per_state
|
95
|
+
State.all.each do |state|
|
96
|
+
streets= Street.all.map do |street |
|
97
|
+
if street.connects.in.detect{|x| x.state == state }
|
98
|
+
street.name + " connects " + street.connects.in.map( &:name ).join('; ')
|
99
|
+
end
|
100
|
+
end.compact
|
101
|
+
unless streets.empty?
|
102
|
+
puts "..................................."
|
103
|
+
puts state.name
|
104
|
+
puts "..................................."
|
105
|
+
puts streets.join("\n")
|
106
106
|
end
|
107
107
|
end
|
108
|
-
|
108
|
+
end
|
109
|
+
end
|
109
110
|
|
110
111
|
if $0 == __FILE__
|
111
112
|
|
112
|
-
require '../config/boot'
|
113
|
-
require 'open-uri'
|
114
|
-
require 'nokogiri'
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
113
|
+
require '../config/boot'
|
114
|
+
require 'open-uri'
|
115
|
+
require 'nokogiri'
|
116
|
+
|
117
|
+
ActiveOrient::OrientDB.default_server= { user: 'root', password: 'tretretre' }
|
118
|
+
r = ActiveOrient::OrientDB.new database: 'StreetTest'
|
119
|
+
ActiveOrient::OrientDB.logger.level = Logger::INFO
|
120
|
+
s= StreetExample.new r, rebuild: true
|
121
|
+
|
122
|
+
def to_orient
|
123
|
+
#puts "here hash"
|
124
|
+
substitute_hash = Hash.new
|
125
|
+
keys.each{|k| substitute_hash[k] = self[k].to_orient}
|
126
|
+
substitute_hash
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
s.read_from_web if City.count.zero?
|
131
|
+
s.display_streets_per_state
|
128
132
|
|
129
133
|
end
|