diff --git a/app/builders/collection_builder.rb b/app/builders/collection_builder.rb index 0f20a1eda60a95922eccd3ad00b0744bb106b09f..ad218588d8e2534485a29626169ebee8d002706e 100644 --- a/app/builders/collection_builder.rb +++ b/app/builders/collection_builder.rb @@ -14,8 +14,9 @@ class CollectionBuilder < Builder def self.build_from_orientdb(args = {}) super(args) do type = (args['name'] == 'Bookmarks') ? Bookmarks : Collection + learning_objects = args['learning_objects'].nil? ? [] : LearningObjectBuilder.build(map_rid_to_object(args['learning_objects'])) obj = type.new( - learning_objects: LearningObjectBuilder.build(map_rid_to_object(args['learning_objects']) || []), + learning_objects: learning_objects, privacy: args['privacy'], id: args['@rid'] ) diff --git a/app/builders/generic_builder.rb b/app/builders/generic_builder.rb index bceb357b03baa1def65232acfd01008a6093bae8..99bf26934c4459c54d3c0697e98897b0a502e086 100644 --- a/app/builders/generic_builder.rb +++ b/app/builders/generic_builder.rb @@ -18,14 +18,14 @@ class GenericBuilder < Builder if cache && !object[last_modified].blank? o = Rails.cache.fetch(cache_key(object[id], object[last_modified])) end - - o = repository(object['@class']).find object[id] if o.nil? + p object.inspect + o = repository(object['class']).find object[id] if o.nil? array << o end array end - def repository(klass) + def self.repository(klass) case klass when 'Attribute' then attribute_repository when 'Collection' then collection_repository diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index 771952d3ae2a5b7fa338796aeaf07587b41305bd..7fdb6e339c359fad57e25a7a2a4cf600631b14ad 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -32,7 +32,7 @@ class SearchController < ApplicationController @last_page = (@result.num_pages <= page) ? true : false; # build objects from one page only - @objects = LearningObjectBuilder.build(@result) + @objects = GenericBuilder.build(@result) render partial: 'search/fetch' end diff --git a/app/repositories/orient_db/learning_object_repository.rb b/app/repositories/orient_db/learning_object_repository.rb index 2fc251cbcda964bf80c68441178d655b335a06a2..2dc9cb19cae4d7b8951b931e273f2e0292fdccc9 100644 --- a/app/repositories/orient_db/learning_object_repository.rb +++ b/app/repositories/orient_db/learning_object_repository.rb @@ -76,7 +76,7 @@ module OrientDb def types Rails.cache.fetch("learning_object/types", expires_in: 1.days) do - query = "select type from LearningObject GROUP BY type" + query = "SELECT DISTINCT(type) FROM LearningObject GROUP BY type" types_hash = connection.query query, limit: 100 # return array with types types_hash.map do |e| @@ -85,22 +85,6 @@ module OrientDb end end - ## - # To create "index:learningobject_search" on OrientDB, use the following command: - # CREATE INDEX learningobject_search - # ON LearningObject (name, description) - # FULLTEXT ENGINE LUCENE - # METADATA {"analyzer":"org.apache.lucene.analysis.br.BrazilianAnalyzer"} - def search(params) - cache_key = build_search_cache_key params - - # get results in cache or search - Rails.cache.fetch(cache_key, expires_in: 10.minutes) do - query = build_search_query params - connection.query query, limit: 10000 - end - end - def build_hash(object) hash = super(object) # Remove relation attributes @@ -113,77 +97,5 @@ module OrientDb hash end - def fetch_year(years) - if years.size() == 1 - year = years[0] - qry = "created_at.format('yyyy') = '#{year}'" - elsif years.size() == 2 - begin_year = years[0] - end_year = years[1] - qry = "created_at.format('yyyy') >= '#{begin_year}' AND created_at.format('yyyy') <= '#{end_year}'" - end - end - - def fetch_types(types) - qry = '' - types.each do |type| - qry = qry + "type = '#{type}' " if type == types.first - qry = qry + "OR type = '#{type}' " if type != types.first - end - qry - end - - private - - def order_by(order) - case order - when 'author' - 'author' - when 'publicationasc' - 'published_at' - when 'publicationdesc' - 'published_at DESC' - when 'title' - 'name ASC' - else - 'score DESC' - end - end - - def accepted_properties - ['thumbnail', 'score'] - end - - def build_search_query(params={}) - query = "SELECT FROM LearningObject WHERE [name, description, author] LUCENE '#{params[:query]}'" - query += " AND out('IsAbout') CONTAINS (name in ['" + params[:subject].join("','") + "'])" unless params[:subject].blank? - unless params[:school_level].blank? - params[:school_level] << 'Ensino Fundamental Inicial' << 'Ensino Fundamental Final' if params[:school_level].include? 'Ensino Fundamental' - query += " AND out('IsAbout') CONTAINS (name in ['" + params[:school_level].join("','") + "'])" - end - query = "SELECT * FROM (" + query + ") WHERE " + fetch_types(params[:type]) unless params[:type].blank? - query = "SELECT * FROM (" + query + ") WHERE " + fetch_year(params[:year]) unless params[:year].blank? - query = "SELECT * FROM (" + query + ") ORDER BY #{order_by(params[:order])}" - query = "SELECT @rid.asString(), last_modified FROM (" + query + ")" - query - end - - def search_params - %w(query order subject type school_level year) - end - - def build_search_cache_key(params={}) - cache_key = "search_result/" - search_params.each do |param| - if params[param].class == Array - cache_key += params[param].join('-') - else - cache_key += params[param].to_s - end - cache_key += '/' unless (param == search_params.last) - end - cache_key - end - end end diff --git a/app/repositories/orient_db/user_repository.rb b/app/repositories/orient_db/user_repository.rb index 30bccb7f1b14f488ce802b167fdd3ab6ade5fd77..b68cfda529e28bb84d0803fff37fdc5516165609 100644 --- a/app/repositories/orient_db/user_repository.rb +++ b/app/repositories/orient_db/user_repository.rb @@ -2,6 +2,7 @@ module OrientDb class UserRepository < Base include OrientDb::Methods::FinderMethods include RepositoriesProxy + include Log::Logging def create_graph_node(user) begin @@ -18,6 +19,13 @@ module OrientDb raise NotPersistedRecordError, 'The user wasn`t persisted yet.' end + def update_graph_node(user) + avatar = user.avatar_file_name.nil? ? "" : ", avatar = '"+user.avatar_file_name+"'" + qry = "UPDATE User SET p_id = "+user.id.to_s+", name = '"+user.name+"', email = '"+user.email+avatar+"' UPSERT WHERE p_id = "+user.id.to_s + logger.update qry + connection.command qry + end + def destroy_graph_node(user) connection.command sprintf("delete vertex User WHERE p_id = %d", user.id) end diff --git a/app/repositories/user_repository_proxy.rb b/app/repositories/user_repository_proxy.rb index 4fa3f253aef1c082fb4ab50aa18b29d81298f773..4a3fd889f118efe1e0cebc860a8796f8dd31651f 100644 --- a/app/repositories/user_repository_proxy.rb +++ b/app/repositories/user_repository_proxy.rb @@ -16,6 +16,10 @@ class UserRepositoryProxy end end + def update_graph_node(user) + orientdb_user_repository.update_graph_node user + end + def get_by_rid(rid) User.find_by_rid rid end diff --git a/app/services/search_service.rb b/app/services/search_service.rb new file mode 100644 index 0000000000000000000000000000000000000000..93189fc9071fc76107fba3a68f1d91a2fb516308 --- /dev/null +++ b/app/services/search_service.rb @@ -0,0 +1,124 @@ +class SearchService + include RepositoriesProxy + + def initialize(orientdb_connection) + @connection = orientdb_connection + end + + def search(params) + cache_key = build_search_cache_key params + + # get results in cache or search + Rails.cache.fetch(cache_key, expires_in: 10.minutes) do + query = build_search_query params + @connection.query query, limit: 10000 + end + end + + private + + def build_search_query(params={}) + "SELECT @rid.asString(), last_modified, @class FROM ("+main_query(params)+") ORDER BY #{order_by(params[:order])}" + end + + def main_query(params={}) + "SELECT EXPAND($c) LET $a = ("+collection_query(params)+"), $b = ("+learning_object_query(params)+"), $c = UNIONALL($a, $b)" + end + + def collection_query(params={}) + qry = "SELECT *, created_at as published_at, out('BelongsTo')[0].name as author FROM Collection" + qry += " WHERE name LUCENE '#{params[:query]}' OR description LUCENE '#{params[:query]}'" unless params[:query].blank? + qry_filter = params[:query].blank? ? " WHERE " : " AND " + filter = collection_learning_objects_filter(params) + qry += qry_filter+filter unless filter.blank? + qry + end + + def learning_object_query(params={}) + qry = "SELECT FROM LearningObject" + qry +=" WHERE name LUCENE '#{params[:query]}' OR description LUCENE '#{params[:query]}' OR author LUCENE '#{params[:query]}'" unless params[:query].blank? + qry_filter = params[:query].blank? ? " WHERE " : " AND " + filter = learning_object_filters(params) + qry += qry_filter+filter unless filter.blank? + qry + end + + def collection_learning_objects_filter(params={}) + qry = learning_object_filters(params) + qry = "learning_objects contains(#{qry})" unless qry.blank? + qry + end + + def learning_object_filters(params={}) + qry = "" + qry = " AND ("+subject_filter(params[:subject])+")" unless params[:subject].blank? + unless params[:school_level].blank? + params[:school_level] << 'Ensino Fundamental Inicial' << 'Ensino Fundamental Final' if params[:school_level].include? 'Ensino Fundamental' + qry += " AND ("+subject_filter(params[:school_level])+")" + end + qry += " AND ("+type_filter(params[:type])+")" unless params[:type].blank? + qry += " AND ("+year_filter(params[:year])+")" unless params[:year].blank? + qry[3..-1] + end + + def subject_filter(subjects) + "out('IsAbout') CONTAINS (name in ['"+subjects.join("','")+"'])" + end + + def year_filter(years) + if years.size() == 1 + year = years[0] + qry = "created_at.format('yyyy') = '#{year}'" + elsif years.size() == 2 + begin_year = years[0] + end_year = years[1] + qry = "created_at.format('yyyy') >= '#{begin_year}' AND created_at.format('yyyy') <= '#{end_year}'" + end + end + + def type_filter(types) + qry = '' + types.each do |type| + qry = qry + "type = '#{type}' " if type == types.first + qry = qry + "OR type = '#{type}' " if type != types.first + end + qry + end + + def order_by(order) + case order + when 'author' + 'author' + when 'publicationasc' + 'published_at' + when 'publicationdesc' + 'published_at DESC' + when 'title' + 'name ASC' + else + 'score DESC' + end + end + + def accepted_properties + ['thumbnail', 'score'] + end + + def search_params + %w(query order subject type school_level year) + end + + def build_search_cache_key(params={}) + cache_key = "search_result/" + search_params.each do |param| + if params[param].class == Array + cache_key += params[param].join('-') + else + cache_key += params[param].to_s + end + cache_key += '/' unless (param == search_params.last) + end + cache_key + end + +end \ No newline at end of file diff --git a/lib/orient_db/migrations/create_collection.rb b/lib/orient_db/migrations/create_collection.rb index 545fca8708ae4c72299d88b09f5cedd5b87d2291..4e065f52ed32a133a66d2462f1858986c54495f1 100644 --- a/lib/orient_db/migrations/create_collection.rb +++ b/lib/orient_db/migrations/create_collection.rb @@ -7,7 +7,8 @@ class OrientDb::Migrations::CreateCollection < OrientDb::Migration c.link 'learning_objects', :linkset, 'LearningObject' end metadata = {:analyzer => "org.apache.lucene.analysis.br.BrazilianAnalyzer"} - add_index 'Collection', ['name', 'description'], "FULLTEXT", "collection_search", "LUCENE", metadata.to_json + add_index 'Collection', ['name'], "FULLTEXT", nil, "LUCENE", metadata.to_json + add_index 'Collection', ['description'], "FULLTEXT", nil, "LUCENE", metadata.to_json end def down diff --git a/lib/orient_db/migrations/create_learning_object.rb b/lib/orient_db/migrations/create_learning_object.rb index 69fc736890ca84499c35f8c7f4a96757ab5398a8..69ca684e946822c8170cbd4c18e44b91f500818d 100644 --- a/lib/orient_db/migrations/create_learning_object.rb +++ b/lib/orient_db/migrations/create_learning_object.rb @@ -16,7 +16,9 @@ class OrientDb::Migrations::CreateLearningObject < OrientDb::Migration end add_index 'LearningObject', ['id_dspace'], "UNIQUE_HASH_INDEX" metadata = {:analyzer => "org.apache.lucene.analysis.br.BrazilianAnalyzer"} - add_index 'LearningObject', ['name', 'description', 'author'], "FULLTEXT", "learningobject_search", "LUCENE", metadata.to_json + add_index 'LearningObject', ['name'], "FULLTEXT", nil, "LUCENE", metadata.to_json + add_index 'LearningObject', ['description'], "FULLTEXT", nil, "LUCENE", metadata.to_json + add_index 'LearningObject', ['author'], "FULLTEXT", nil, "LUCENE", metadata.to_json end def down diff --git a/lib/orient_db/migrations/create_user.rb b/lib/orient_db/migrations/create_user.rb index 3c7406f4338f4b8cdebfd5355cebc217ece45bc4..5e1a367b7337f371281cd1e626cefc93ecaf0441 100644 --- a/lib/orient_db/migrations/create_user.rb +++ b/lib/orient_db/migrations/create_user.rb @@ -3,6 +3,9 @@ class OrientDb::Migrations::CreateUser < OrientDb::Migration def up create_class 'User', 'V' do |c| c.property 'p_id', :integer, :mandatory => true, :notnull => true + c.property 'name', :string + c.property 'email', :string + c.property 'avatar', :string end add_index 'User', ['p_id'], "UNIQUE_HASH_INDEX" end diff --git a/lib/search_engine/orientdb_lucene.rb b/lib/search_engine/orientdb_lucene.rb index b260e81c3dccb944681136db64c4fb1ca0513e0d..6ee7746a5372b43fa8a3754931995d0a51ce51ce 100644 --- a/lib/search_engine/orientdb_lucene.rb +++ b/lib/search_engine/orientdb_lucene.rb @@ -1,8 +1,12 @@ module SearchEngine module OrientdbLucene + def search_service + @search_service ||= SearchService.new(OrientDb::Client.instance) + end + def search(params) - learning_object_repository.search(params) + search_service.search(params) end end diff --git a/lib/tasks/dspace.rake b/lib/tasks/dspace.rake index be9a17f1426eba0cf47be1d800055d6ee1bb2616..6fb81cd19eff72d7b5f5cc8cfa206d0f521efb96 100644 --- a/lib/tasks/dspace.rake +++ b/lib/tasks/dspace.rake @@ -158,13 +158,13 @@ namespace :dspace do :last_modified => current_date, :created_at => current_date, :id_dspace => item.id, - :type => item.type, :thumbnail => nil, :bitstreams => bitstreams, :metadata => metadata ) lo.author = lo.get_metadata_values_of("dc.contributor.author").join(', ') lo.description = lo.get_metadata_value_of("dc.description") + lo.type = lo.get_metadata_value_of("dc.type") date = lo.get_metadata_value_of("dc.date.issued") lo.published_at = Time.iso8601(date) unless date.nil? lo diff --git a/lib/tasks/orientdb.rake b/lib/tasks/orientdb.rake index b5f09e9782a38504d9b5efe28ea59c9ebe6cddcb..3508f153293b0c501b66b8c9b9744b0979b50d39 100644 --- a/lib/tasks/orientdb.rake +++ b/lib/tasks/orientdb.rake @@ -113,4 +113,22 @@ namespace :orientdb do logger.close end + task :sync_with_psql, [:log] => [:environment] do |t, args| + desc "Synchronize OrientDB with PostgreSQL data" + + include RepositoriesProxy + include Log::Logging + + args.with_defaults(:log => STDOUT) + Log::Logging.logger = Log::DatabaseLogger.new(args.log) + logger.level = Log::DatabaseLogger::UPDATE + + users = user_repository.all + users.each do |user| + logger.info "User p_id = "+user.id.to_s + user_repository.update_graph_node(user) + end + + logger.close + end end