Skip to content

Commit

Permalink
Merge 6867a35 into 5392cf0
Browse files Browse the repository at this point in the history
  • Loading branch information
subvertallchris committed Sep 21, 2014
2 parents 5392cf0 + 6867a35 commit 8d4652e
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Rakefile
@@ -1,6 +1,6 @@
require 'rake'
require "bundler/gem_tasks"
require 'neo4j/tasks/neo4j_server'
load 'neo4j/tasks/neo4j_server.rake'

desc "Generate YARD documentation"
task 'yard' do
Expand Down
85 changes: 85 additions & 0 deletions lib/neo4j/migration.rb
@@ -0,0 +1,85 @@
module Neo4j
class Migration
class AddIdProperty < Neo4j::Migration
attr_reader :models_filename

def initialize
@models_filename = File.join(Rails.root.join('db', 'neo4j-migrate'), 'add_id_property.yml')
end

def migrate
models = ActiveSupport::HashWithIndifferentAccess.new(YAML.load_file(models_filename))[:models]
puts "This task will add an ID Property every node in the given file."
puts "It may take a significant amount of time, please be patient."
models.each do |model|
puts
puts
puts "Adding IDs to #{model}"
add_ids_to model.constantize
end
end

def setup
FileUtils.mkdir_p("db/neo4j-migrate")
unless File.file?(models_filename)
File.open(models_filename, 'w') do |file|
file.write("# Provide models to which IDs should be added.\n# It will only modify nodes that do not have IDs. There is no danger of overwriting data.\n# models: [Student,Lesson,Teacher,Exam]\nmodels: []")
end
end
end

private

def add_ids_to(model)
require 'benchmark'

max_per_batch = (ENV['MAX_PER_BATCH'] || max_per_batch).to_i

label = model.mapped_label_name
property = model.primary_key
total = 1
last_time_taken = nil

until total == 0
total = Neo4j::Session.query.match(n: label).where("NOT has(n.#{property})").return("COUNT(n) AS ids").first.ids

time_per_node = last_time_taken / max_per_batch if last_time_taken
print "#{total} nodes left. Last batch: #{time_per_node && (time_per_node * 1000.0).round(1)}ms / node\r"

return if total == 0
to_set = total > max_per_batch ? max_per_batch : total
new_ids = [].tap do | ids_array|
to_set.times { ids_array.push "'#{new_id_for(model)}'" }
end
begin
last_time_taken = Benchmark.realtime do
Neo4j::Session.query("MATCH (n:`#{label}`) WHERE NOT has(n.#{property})
with COLLECT(n) as nodes, [#{new_ids.join(',')}] as ids
FOREACH(i in range(0,#{to_set - 1})|
FOREACH(node in [nodes[i]]|
SET node.#{property} = ids[i]))
RETURN distinct(true)
LIMIT #{to_set}")
end
rescue Neo4j::Server::CypherResponse::ResponseError, Net::ReadTimeout
new_max_per_batch = (max_per_batch * 0.8).round
puts "Error querying #{max_per_batch} nodes. Trying #{new_max_per_batch}"
max_per_batch = new_max_per_batch
end
end
end

def max_per_batch
900
end

def new_id_for(model)
if model.id_property_info[:type][:auto]
SecureRandom::uuid
else
model.new.send(model.id_property_info[:type][:on])
end
end
end
end
end
4 changes: 4 additions & 0 deletions lib/neo4j/railtie.rb
Expand Up @@ -56,6 +56,10 @@ def open_neo4j_session(session_opts)

end

rake_tasks do
load 'neo4j/tasks/neo4j_server.rake'
load 'neo4j/tasks/rails.rake'
end

# Starting Neo after :load_config_initializers allows apps to
# register migrations in config/initializers
Expand Down
23 changes: 23 additions & 0 deletions lib/neo4j/tasks/rails.rake
@@ -0,0 +1,23 @@
require 'neo4j/migration'

namespace :neo4j do
desc "Run a script against the database to perform system-wide changes"
task :migrate, [:task_name, :subtask] => :environment do |_, args|
migration_task = args[:task_name]
task_name_constant = migration_task.split('_').map { |word| word.capitalize }.join('')
begin
migration_class = "Neo4j::Migration::#{task_name_constant}".constantize
rescue NameError
load File.join(Rails.root.join('db', 'neo4j-migrate'), "#{migration_task}.rb")
migration_class = "#{task_name_constant}".constantize
end
migration = migration_class.new

subtask = args[:subtask]
if subtask
migration.send(subtask)
else
migration.migrate
end
end
end

0 comments on commit 8d4652e

Please sign in to comment.