class Neo4j::Migration::AddIdProperty
Attributes
models_filename[R]
Public Class Methods
new(path = default_path)
click to toggle source
# File lib/neo4j/migration.rb 28 def initialize(path = default_path) 29 @models_filename = File.join(joined_path(path), 'add_id_property.yml') 30 end
Public Instance Methods
migrate()
click to toggle source
# File lib/neo4j/migration.rb 32 def migrate 33 models = ActiveSupport::HashWithIndifferentAccess.new(YAML.load_file(models_filename))[:models] 34 output 'This task will add an ID Property every node in the given file.' 35 output 'It may take a significant amount of time, please be patient.' 36 models.each do |model| 37 output 38 output 39 output "Adding IDs to #{model}" 40 add_ids_to model.constantize 41 end 42 end
setup()
click to toggle source
# File lib/neo4j/migration.rb 44 def setup 45 FileUtils.mkdir_p('db/neo4j-migrate') 46 47 return if File.file?(models_filename) 48 49 File.open(models_filename, 'w') do |file| 50 message = <<MESSAGE 51 # Provide models to which IDs should be added. 52 # # It will only modify nodes that do not have IDs. There is no danger of overwriting data. 53 # # models: [Student,Lesson,Teacher,Exam]\nmodels: [] 54 MESSAGE 55 file.write(message) 56 end 57 end
Private Instance Methods
add_ids_to(model)
click to toggle source
# File lib/neo4j/migration.rb 61 def add_ids_to(model) 62 max_per_batch = (ENV['MAX_PER_BATCH'] || default_max_per_batch).to_i 63 64 label = model.mapped_label_name 65 last_time_taken = nil 66 67 until (nodes_left = idless_count(label, model.primary_key)) == 0 68 print_status(last_time_taken, max_per_batch, nodes_left) 69 70 count = [nodes_left, max_per_batch].min 71 last_time_taken = Benchmark.realtime do 72 max_per_batch = id_batch_set(label, model.primary_key, count.times.map { new_id_for(model) }, count) 73 end 74 end 75 end
default_max_per_batch()
click to toggle source
# File lib/neo4j/migration.rb 114 def default_max_per_batch 115 900 116 end
id_batch_set(label, id_property, new_ids, count)
click to toggle source
# File lib/neo4j/migration.rb 94 def id_batch_set(label, id_property, new_ids, count) 95 tx = Neo4j::Transaction.new 96 97 Neo4j::Session.query("MATCH (n:`#{label}`) WHERE NOT EXISTS(n.#{id_property}) 98 with COLLECT(n) as nodes, #{new_ids} as ids 99 FOREACH(i in range(0,#{count - 1})| 100 FOREACH(node in [nodes[i]]| 101 SET node.#{id_property} = ids[i])) 102 RETURN distinct(true) 103 LIMIT #{count}") 104 105 count 106 rescue Neo4j::Server::CypherResponse::ResponseError, Faraday::TimeoutError 107 new_max_per_batch = (max_per_batch * 0.8).round 108 output "Error querying #{max_per_batch} nodes. Trying #{new_max_per_batch}" 109 new_max_per_batch 110 ensure 111 tx.close 112 end
idless_count(label, id_property)
click to toggle source
# File lib/neo4j/migration.rb 77 def idless_count(label, id_property) 78 Neo4j::Session.query.match(n: label).where("NOT EXISTS(n.#{id_property})").pluck('COUNT(n) AS ids').first 79 end
new_id_for(model)
click to toggle source
# File lib/neo4j/migration.rb 118 def new_id_for(model) 119 if model.id_property_info[:type][:auto] 120 SecureRandom.uuid 121 else 122 model.new.send(model.id_property_info[:type][:on]) 123 end 124 end
print_status(last_time_taken, max_per_batch, nodes_left)
click to toggle source
# File lib/neo4j/migration.rb 81 def print_status(last_time_taken, max_per_batch, nodes_left) 82 time_per_node = last_time_taken / max_per_batch if last_time_taken 83 message = if time_per_node 84 eta_seconds = (nodes_left * time_per_node).round 85 "#{nodes_left} nodes left. Last batch: #{(time_per_node * 1000.0).round(1)}ms / node (ETA: #{eta_seconds / 60} minutes)\r" 86 else 87 "Running first batch...\r" 88 end 89 90 print_output message 91 end