neo4j 7.2.3 → 8.0.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -46
  3. data/Gemfile +15 -14
  4. data/README.md +21 -14
  5. data/bin/neo4j-jars +1 -1
  6. data/lib/neo4j.rb +12 -1
  7. data/lib/neo4j/active_base.rb +68 -0
  8. data/lib/neo4j/active_base/session_registry.rb +12 -0
  9. data/lib/neo4j/active_node.rb +13 -21
  10. data/lib/neo4j/active_node/dependent/query_proxy_methods.rb +6 -6
  11. data/lib/neo4j/active_node/enum.rb +3 -6
  12. data/lib/neo4j/active_node/has_n.rb +24 -19
  13. data/lib/neo4j/active_node/has_n/association.rb +6 -2
  14. data/lib/neo4j/active_node/has_n/association/rel_factory.rb +1 -1
  15. data/lib/neo4j/active_node/has_n/association/rel_wrapper.rb +1 -1
  16. data/lib/neo4j/active_node/has_n/association_cypher_methods.rb +1 -1
  17. data/lib/neo4j/active_node/id_property.rb +52 -15
  18. data/lib/neo4j/active_node/labels.rb +32 -10
  19. data/lib/neo4j/active_node/labels/index.rb +5 -55
  20. data/lib/neo4j/active_node/node_list_formatter.rb +13 -0
  21. data/lib/neo4j/active_node/node_wrapper.rb +39 -37
  22. data/lib/neo4j/active_node/persistence.rb +27 -13
  23. data/lib/neo4j/active_node/query/query_proxy.rb +11 -9
  24. data/lib/neo4j/active_node/query/query_proxy_eager_loading.rb +4 -4
  25. data/lib/neo4j/active_node/query/query_proxy_enumerable.rb +1 -0
  26. data/lib/neo4j/active_node/query/query_proxy_link.rb +13 -9
  27. data/lib/neo4j/active_node/query/query_proxy_methods.rb +76 -8
  28. data/lib/neo4j/active_node/query/query_proxy_methods_of_mass_updating.rb +1 -1
  29. data/lib/neo4j/active_node/query_methods.rb +3 -3
  30. data/lib/neo4j/active_node/scope.rb +24 -7
  31. data/lib/neo4j/active_rel.rb +21 -3
  32. data/lib/neo4j/active_rel/initialize.rb +2 -2
  33. data/lib/neo4j/active_rel/persistence.rb +32 -6
  34. data/lib/neo4j/active_rel/persistence/query_factory.rb +3 -3
  35. data/lib/neo4j/active_rel/property.rb +9 -9
  36. data/lib/neo4j/active_rel/query.rb +6 -4
  37. data/lib/neo4j/active_rel/rel_wrapper.rb +24 -16
  38. data/lib/neo4j/active_rel/related_node.rb +5 -1
  39. data/lib/neo4j/active_rel/types.rb +2 -2
  40. data/lib/neo4j/config.rb +0 -1
  41. data/lib/neo4j/errors.rb +3 -0
  42. data/lib/neo4j/migration.rb +90 -71
  43. data/lib/neo4j/migrations.rb +10 -0
  44. data/lib/neo4j/migrations/base.rb +44 -0
  45. data/lib/neo4j/migrations/helpers.rb +101 -0
  46. data/lib/neo4j/migrations/helpers/id_property.rb +75 -0
  47. data/lib/neo4j/migrations/helpers/relationships.rb +66 -0
  48. data/lib/neo4j/migrations/helpers/schema.rb +53 -0
  49. data/lib/neo4j/migrations/migration_file.rb +24 -0
  50. data/lib/neo4j/migrations/runner.rb +110 -0
  51. data/lib/neo4j/migrations/schema_migration.rb +9 -0
  52. data/lib/neo4j/model_schema.rb +100 -0
  53. data/lib/neo4j/railtie.rb +29 -110
  54. data/lib/neo4j/schema/operation.rb +24 -13
  55. data/lib/neo4j/session_manager.rb +137 -0
  56. data/lib/neo4j/shared.rb +20 -11
  57. data/lib/neo4j/shared/attributes.rb +10 -16
  58. data/lib/neo4j/shared/callbacks.rb +3 -3
  59. data/lib/neo4j/shared/cypher.rb +1 -1
  60. data/lib/neo4j/shared/declared_properties.rb +1 -1
  61. data/lib/neo4j/shared/declared_property.rb +1 -1
  62. data/lib/neo4j/shared/enum.rb +6 -18
  63. data/lib/neo4j/shared/identity.rb +27 -21
  64. data/lib/neo4j/shared/persistence.rb +26 -17
  65. data/lib/neo4j/shared/property.rb +5 -2
  66. data/lib/neo4j/shared/query_factory.rb +4 -5
  67. data/lib/neo4j/shared/type_converters.rb +8 -9
  68. data/lib/neo4j/shared/validations.rb +1 -5
  69. data/lib/neo4j/tasks/migration.rake +83 -2
  70. data/lib/neo4j/version.rb +1 -1
  71. data/lib/rails/generators/neo4j/migration/migration_generator.rb +14 -0
  72. data/lib/rails/generators/neo4j/migration/templates/migration.erb +9 -0
  73. data/lib/rails/generators/neo4j/model/model_generator.rb +1 -3
  74. data/lib/rails/generators/neo4j_generator.rb +1 -0
  75. data/neo4j.gemspec +3 -3
  76. metadata +58 -65
  77. data/bin/rake +0 -17
  78. data/lib/neo4j/shared/permitted_attributes.rb +0 -28
@@ -27,7 +27,7 @@ module Neo4j
27
27
  query_with_target(identifier) do |target|
28
28
  begin
29
29
  self.query.with(target).optional_match("(#{target})-[#{target}_rel]-()").delete("#{target}, #{target}_rel").exec
30
- rescue Neo4j::Session::CypherError
30
+ rescue Neo4j::Core::CypherSession::CypherError # <=- Seems hacky
31
31
  self.query.delete(target).exec
32
32
  end
33
33
  clear_source_object_cache
@@ -27,14 +27,14 @@ module Neo4j
27
27
  self.query_as(:n).return("count(#{q}) AS count").first.count
28
28
  end
29
29
 
30
- alias_method :size, :count
31
- alias_method :length, :count
30
+ alias size count
31
+ alias length count
32
32
 
33
33
  def empty?
34
34
  !self.all.exists?
35
35
  end
36
36
 
37
- alias_method :blank?, :empty?
37
+ alias blank? empty?
38
38
 
39
39
  def find_in_batches(options = {})
40
40
  self.query_as(:n).return(:n).find_in_batches(:n, primary_key, options) do |batch|
@@ -64,7 +64,7 @@ module Neo4j::ActiveNode
64
64
  end
65
65
 
66
66
  def full_scopes
67
- scopes.merge(self.superclass.respond_to?(:scopes) ? self.superclass.scopes : {})
67
+ self.superclass.respond_to?(:scopes) ? self.superclass.scopes.merge(scopes) : scopes
68
68
  end
69
69
 
70
70
  def _call_scope_context(eval_context, query_params, proc)
@@ -100,13 +100,30 @@ module Neo4j::ActiveNode
100
100
  @target = target
101
101
  end
102
102
 
103
+ def identity
104
+ query_proxy_or_target.identity
105
+ end
106
+
103
107
  Neo4j::ActiveNode::Query::QueryProxy::METHODS.each do |method|
104
- module_eval(%{
105
- def #{method}(params={})
106
- @target.all.scoping do
107
- (@query_proxy || @target).#{method}(params)
108
- end
109
- end}, __FILE__, __LINE__)
108
+ define_method(method) do |*args|
109
+ @target.all.scoping do
110
+ query_proxy_or_target.public_send(method, *args)
111
+ end
112
+ end
113
+ end
114
+
115
+ def method_missing(name, *params, &block)
116
+ if query_proxy_or_target.respond_to?(name)
117
+ query_proxy_or_target.public_send(name, *params, &block)
118
+ else
119
+ super
120
+ end
121
+ end
122
+
123
+ private
124
+
125
+ def query_proxy_or_target
126
+ @query_proxy_or_target ||= @query_proxy || @target
110
127
  end
111
128
  end
112
129
 
@@ -18,14 +18,13 @@ module Neo4j
18
18
  include Neo4j::ActiveRel::Query
19
19
  include Neo4j::ActiveRel::Types
20
20
  include Neo4j::Shared::Enum
21
- include Neo4j::Shared::PermittedAttributes
22
21
 
23
22
  class FrozenRelError < Neo4j::Error; end
24
23
 
25
24
  def initialize(from_node = nil, to_node = nil, args = nil)
26
25
  load_nodes(node_or_nil(from_node), node_or_nil(to_node))
27
26
  resolved_args = hash_or_nil(from_node, args)
28
- symbol_args = sanitize_input_parameters(resolved_args)
27
+ symbol_args = resolved_args.is_a?(Hash) ? resolved_args.symbolize_keys : resolved_args
29
28
  super(symbol_args)
30
29
  end
31
30
 
@@ -61,7 +60,26 @@ module Neo4j
61
60
  end
62
61
 
63
62
  def hash_or_nil(node_or_hash, hash_or_nil)
64
- hash_or_parameter?(node_or_hash) ? node_or_hash : hash_or_nil
63
+ node_or_hash.is_a?(Hash) ? node_or_hash : hash_or_nil
64
+ end
65
+
66
+ module ClassMethods
67
+ [:create, :create!].each do |meth|
68
+ define_method(meth) do |from_node_or_args = nil, to_node = nil, args = nil|
69
+ return super(from_node_or_args) if from_node_or_args.is_a?(Hash)
70
+ args_hash = args || {}
71
+ args_with_node!(:from_node, from_node_or_args, args_hash)
72
+ args_with_node!(:to_node, to_node, args_hash)
73
+ super(args_hash)
74
+ end
75
+ end
76
+
77
+ private
78
+
79
+ def args_with_node!(key, node, args)
80
+ args[key] = node if node.is_a?(Neo4j::ActiveNode)
81
+ args
82
+ end
65
83
  end
66
84
  end
67
85
  end
@@ -19,8 +19,8 @@ module Neo4j::ActiveRel
19
19
  def init_on_reload(unwrapped_reloaded)
20
20
  @attributes = nil
21
21
  init_on_load(unwrapped_reloaded,
22
- unwrapped_reloaded._start_node_id,
23
- unwrapped_reloaded._end_node_id,
22
+ unwrapped_reloaded.start_node_id,
23
+ unwrapped_reloaded.end_node_id,
24
24
  unwrapped_reloaded.rel_type)
25
25
  self
26
26
  end
@@ -40,8 +40,7 @@ module Neo4j::ActiveRel
40
40
  # @param [Symbol, String] name of the attribute to increment
41
41
  # @param [Integer, Float] amount to increment
42
42
  def concurrent_increment!(attribute, by = 1)
43
- query_rel = Neo4j::Session.query.match('()-[n]-()').where(n: {neo_id: neo_id})
44
- increment_by_query! query_rel, attribute, by
43
+ increment_by_query! query_as(:n), attribute, by
45
44
  end
46
45
 
47
46
  def create_model
@@ -52,16 +51,35 @@ module Neo4j::ActiveRel
52
51
  true
53
52
  end
54
53
 
54
+ def query_as(var)
55
+ # This should query based on the nodes, not the rel neo_id, I think
56
+ # Also, picky point: Should the var be `n`?
57
+ self.class.query_as(neo_id, var)
58
+ end
59
+
55
60
  module ClassMethods
56
61
  # Creates a new relationship between objects
57
62
  # @param [Hash] props the properties the new relationship should have
58
- def create(*args)
59
- new(*args).tap(&:save)
63
+ def create(props = {})
64
+ relationship_props = extract_association_attributes!(props) || {}
65
+ new(props).tap do |obj|
66
+ relationship_props.each do |prop, value|
67
+ obj.send("#{prop}=", value)
68
+ end
69
+ obj.save
70
+ end
60
71
  end
61
72
 
62
73
  # Same as #create, but raises an error if there is a problem during save.
63
74
  def create!(*args)
64
- new(*args).tap(&:save!)
75
+ props = args[0] || {}
76
+ relationship_props = extract_association_attributes!(props) || {}
77
+ new(props).tap do |obj|
78
+ relationship_props.each do |prop, value|
79
+ obj.send("#{prop}=", value)
80
+ end
81
+ obj.save!
82
+ end
65
83
  end
66
84
 
67
85
  def create_method
@@ -69,7 +87,11 @@ module Neo4j::ActiveRel
69
87
  end
70
88
 
71
89
  def load_entity(id)
72
- Neo4j::Relationship.load(id)
90
+ query_as(id).pluck(:r).first
91
+ end
92
+
93
+ def query_as(neo_id, var = :r)
94
+ Neo4j::ActiveBase.new_query.match("()-[#{var}]-()").where(var => {neo_id: neo_id})
73
95
  end
74
96
  end
75
97
 
@@ -79,6 +101,10 @@ module Neo4j::ActiveRel
79
101
 
80
102
  private
81
103
 
104
+ def destroy_query
105
+ query_as(:r).delete(:r)
106
+ end
107
+
82
108
  def validate_node_classes!
83
109
  [from_node, to_node].each do |node|
84
110
  type = from_node == node ? :_from_class : :_to_class
@@ -15,9 +15,9 @@ module Neo4j::ActiveRel::Persistence
15
15
  # TODO: This feels like it should also wrap the rel, but that is handled in Neo4j::ActiveRel::Persistence at the moment.
16
16
  # Builds and executes the query using the objects giving during init.
17
17
  # It holds the process:
18
- # * Execute node callbacks if needed
19
- # * Create and execute the query
20
- # * Mix the query response into the unpersisted objects given during init
18
+ # * Execute node callbacks if needed
19
+ # * Create and execute the query
20
+ # * Mix the query response into the unpersisted objects given during init
21
21
  def build!
22
22
  node_before_callbacks! do
23
23
  res = query_factory(rel, rel_id, iterative_query).query.unwrapped.return(*unpersisted_return_ids).first
@@ -6,27 +6,27 @@ module Neo4j::ActiveRel
6
6
  include Neo4j::Shared::Property
7
7
 
8
8
  %w(to_node from_node).each do |direction|
9
- define_method("#{direction}") { instance_variable_get("@#{direction}") }
9
+ define_method(direction.to_s) { instance_variable_get("@#{direction}") }
10
10
  define_method("#{direction}=") do |argument|
11
11
  fail FrozenRelError, 'Relationship start/end nodes cannot be changed once persisted' if _persisted_obj
12
12
  instance_variable_set("@#{direction}", argument)
13
13
  end
14
14
  end
15
15
 
16
- alias_method :start_node, :from_node
17
- alias_method :end_node, :to_node
16
+ alias start_node from_node
17
+ alias end_node to_node
18
18
 
19
19
  %w(start_node end_node).each do |direction|
20
20
  define_method("#{direction}_neo_id") { send(direction).neo_id if direction }
21
21
  end
22
- alias_method :from_node_neo_id, :start_node_neo_id
23
- alias_method :to_node_neo_id, :end_node_neo_id
22
+ alias from_node_neo_id start_node_neo_id
23
+ alias to_node_neo_id end_node_neo_id
24
24
 
25
25
  # @return [String] a string representing the relationship type that will be created
26
26
  def type
27
27
  self.class.type
28
28
  end
29
- alias_method :rel_type, :type
29
+ alias rel_type type
30
30
 
31
31
  def initialize(attributes = nil)
32
32
  super(attributes)
@@ -55,7 +55,7 @@ module Neo4j::ActiveRel
55
55
  end
56
56
 
57
57
  %w(to_class from_class).each do |direction|
58
- define_method("#{direction}") do |argument = nil|
58
+ define_method(direction.to_s) do |argument = nil|
59
59
  if !argument.nil?
60
60
  Neo4j::ClassArguments.validate_argument!(argument, direction)
61
61
 
@@ -73,8 +73,8 @@ module Neo4j::ActiveRel
73
73
  (class_argument.is_a?(Array) && class_argument.all? { |c| [String, Symbol].include?(c.class) })
74
74
  end
75
75
 
76
- alias_method :start_class, :from_class
77
- alias_method :end_class, :to_class
76
+ alias start_class from_class
77
+ alias end_class to_class
78
78
 
79
79
  def load_entity(id)
80
80
  Neo4j::Node.load(id)
@@ -12,8 +12,10 @@ module Neo4j::ActiveRel
12
12
  end
13
13
 
14
14
  # Loads the relationship using its neo_id.
15
- def find_by_id(key, session = Neo4j::Session.current!)
16
- session.query.match('()-[r]-()').where('ID(r)' => key.to_i).limit(1).return(:r).first.r
15
+ def find_by_id(key, session = nil)
16
+ options = session ? {session: session} : {}
17
+ query ||= Neo4j::ActiveBase.new_query(options)
18
+ query.match('()-[r]-()').where('ID(r)' => key.to_i).limit(1).return(:r).first.r
17
19
  end
18
20
 
19
21
  # Performs a very basic match on the relationship.
@@ -47,12 +49,12 @@ module Neo4j::ActiveRel
47
49
 
48
50
  def where_query
49
51
  deprecation_warning!
50
- Neo4j::Session.query.match("#{cypher_string(:outbound)}-[r1:`#{self._type}`]->#{cypher_string(:inbound)}")
52
+ Neo4j::ActiveBase.new_query.match("#{cypher_string(:outbound)}-[r1:`#{self._type}`]->#{cypher_string(:inbound)}")
51
53
  end
52
54
 
53
55
  def all_query
54
56
  deprecation_warning!
55
- Neo4j::Session.query.match("#{cypher_string}-[r1:`#{self._type}`]->#{cypher_string(:inbound)}")
57
+ Neo4j::ActiveBase.new_query.match("#{cypher_string}-[r1:`#{self._type}`]->#{cypher_string(:inbound)}")
56
58
  end
57
59
 
58
60
  def cypher_string(dir = :outbound)
@@ -1,22 +1,30 @@
1
- class Neo4j::Relationship
2
- module Wrapper
3
- def wrapper
4
- props.symbolize_keys!
5
- begin
6
- most_concrete_class = class_from_type
7
- wrapped_rel = most_concrete_class.constantize.new
8
- rescue NameError
9
- return self
10
- end
1
+ require 'neo4j/core/relationship'
11
2
 
12
- wrapped_rel.init_on_load(self, self._start_node_id, self._end_node_id, self.rel_type)
13
- wrapped_rel
14
- end
3
+ wrapping_proc = proc do |relationship|
4
+ Neo4j::RelWrapping.wrapper(relationship)
5
+ end
6
+ Neo4j::Core::Relationship.wrapper_callback(wrapping_proc)
15
7
 
16
- private
8
+ module Neo4j
9
+ module RelWrapping
10
+ class << self
11
+ def wrapper(rel)
12
+ rel.props.symbolize_keys!
13
+ begin
14
+ most_concrete_class = class_from_type(rel.rel_type)
15
+ most_concrete_class.constantize.new
16
+ rescue NameError => e
17
+ raise e unless e.message =~ /(uninitialized|wrong) constant/
17
18
 
18
- def class_from_type
19
- Neo4j::ActiveRel::Types::WRAPPED_CLASSES[rel_type] || Neo4j::ActiveRel::Types::WRAPPED_CLASSES[rel_type] = rel_type.camelize
19
+ return rel
20
+ end.tap do |wrapped_rel|
21
+ wrapped_rel.init_on_load(rel, rel.start_node_id, rel.end_node_id, rel.type)
22
+ end
23
+ end
24
+
25
+ def class_from_type(rel_type)
26
+ Neo4j::ActiveRel::Types::WRAPPED_CLASSES[rel_type] || Neo4j::ActiveRel::Types::WRAPPED_CLASSES[rel_type] = rel_type.to_s.camelize
27
+ end
20
28
  end
21
29
  end
22
30
  end
@@ -29,7 +29,11 @@ module Neo4j::ActiveRel
29
29
  # Loads a node from the database or returns the node if already laoded
30
30
  def loaded
31
31
  fail UnsetRelatedNodeError, 'Node not set, cannot load' if @node.nil?
32
- @node = @node.respond_to?(:neo_id) ? @node : Neo4j::Node.load(@node)
32
+ @node = if @node.respond_to?(:neo_id)
33
+ @node
34
+ else
35
+ Neo4j::ActiveBase.new_query.match(:n).where(n: {neo_id: @node}).pluck(:n).first
36
+ end
33
37
  end
34
38
 
35
39
  # @param [String, Symbol, Array] clazz An alternate label to use in the event the node is not present or loaded
@@ -42,8 +42,8 @@ module Neo4j
42
42
  assign_type!(namespaced_model_name, true)
43
43
  end
44
44
  end
45
- alias_method :rel_type, :type
46
- alias_method :_type, :type # should be deprecated
45
+ alias rel_type type
46
+ alias _type type # should be deprecated
47
47
 
48
48
  def namespaced_model_name
49
49
  case Neo4j::Config[:module_handling]
@@ -4,7 +4,6 @@ module Neo4j
4
4
  # == Configurations keys
5
5
  class Config
6
6
  DEFAULT_FILE = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'config', 'neo4j', 'config.yml'))
7
- CLASS_NAME_PROPERTY_KEY = 'class_name_property'
8
7
 
9
8
  class << self
10
9
  # In keeping with the Rails convention, this class writer lets you globally configure
@@ -25,4 +25,7 @@ module Neo4j
25
25
 
26
26
  class DangerousAttributeError < ScriptError; end
27
27
  class UnknownAttributeError < NoMethodError; end
28
+ class MigrationError < Error; end
29
+ class IrreversibleMigration < MigrationError; end
30
+ class UnknownMigrationVersionError < MigrationError; end
28
31
  end
@@ -1,4 +1,5 @@
1
1
  require 'benchmark'
2
+ require 'neo4j/migrations/helpers/id_property'
2
3
 
3
4
  module Neo4j
4
5
  class Migration
@@ -7,11 +8,11 @@ module Neo4j
7
8
  end
8
9
 
9
10
  def output(string = '')
10
- puts string unless !!ENV['silenced']
11
+ puts string unless !!ENV['MIGRATIONS_SILENCED']
11
12
  end
12
13
 
13
14
  def print_output(string)
14
- print string unless !!ENV['silenced']
15
+ print string unless !!ENV['MIGRATIONS_SILENCED']
15
16
  end
16
17
 
17
18
  def default_path
@@ -22,7 +23,15 @@ module Neo4j
22
23
  File.join(path.to_s, 'db', 'neo4j-migrate')
23
24
  end
24
25
 
26
+ def setup
27
+ FileUtils.mkdir_p('db/neo4j-migrate')
28
+ end
29
+
30
+ delegate :query, to: Neo4j::Session
31
+
25
32
  class AddIdProperty < Neo4j::Migration
33
+ include Neo4j::Migrations::Helpers::IdProperty
34
+
26
35
  attr_reader :models_filename
27
36
 
28
37
  def initialize(path = default_path)
@@ -30,6 +39,8 @@ module Neo4j
30
39
  end
31
40
 
32
41
  def migrate
42
+ ActiveSupport::Deprecation.warn '`AddIdProperty` task is deprecated and may be removed from future releases. '\
43
+ 'Create a new migration and use the `populate_id_property` helper.', caller
33
44
  models = ActiveSupport::HashWithIndifferentAccess.new(YAML.load_file(models_filename))[:models]
34
45
  output 'This task will add an ID Property every node in the given file.'
35
46
  output 'It may take a significant amount of time, please be patient.'
@@ -37,13 +48,20 @@ module Neo4j
37
48
  output
38
49
  output
39
50
  output "Adding IDs to #{model}"
40
- add_ids_to model.constantize
51
+ populate_id_property model
41
52
  end
42
53
  end
43
54
 
44
- def setup
45
- FileUtils.mkdir_p('db/neo4j-migrate')
55
+ def query(*args)
56
+ ActiveBase.magic_query(*args)
57
+ end
58
+
59
+ def execute(*args)
60
+ ActiveBase.query(*args)
61
+ end
46
62
 
63
+ def setup
64
+ super
47
65
  return if File.file?(models_filename)
48
66
 
49
67
  File.open(models_filename, 'w') do |file|
@@ -56,72 +74,73 @@ MESSAGE
56
74
  end
57
75
  end
58
76
 
59
- private
60
-
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
76
-
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
80
-
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
92
-
93
-
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
113
-
114
- def default_max_per_batch
115
- 900
116
- end
117
-
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
77
+ # Might need some of this...
78
+ # private
79
+
80
+ # def add_ids_to(model)
81
+ # max_per_batch = (ENV['MAX_PER_BATCH'] || default_max_per_batch).to_i
82
+
83
+ # label = model.mapped_label_name
84
+ # last_time_taken = nil
85
+
86
+ # until (nodes_left = idless_count(label, model.primary_key)) == 0
87
+ # print_status(last_time_taken, max_per_batch, nodes_left)
88
+
89
+ # count = [nodes_left, max_per_batch].min
90
+ # last_time_taken = Benchmark.realtime do
91
+ # max_per_batch = id_batch_set(label, model.primary_key, Array.new(count) { new_id_for(model) }, count)
92
+ # end
93
+ # end
94
+ # end
95
+
96
+ # def idless_count(label, id_property)
97
+ # Neo4j::ActiveBase.new_query.match(n: label).where("NOT EXISTS(n.#{id_property})").pluck('COUNT(n) AS ids').first
98
+ # end
99
+
100
+ # def print_status(last_time_taken, max_per_batch, nodes_left)
101
+ # time_per_node = last_time_taken / max_per_batch if last_time_taken
102
+ # message = if time_per_node
103
+ # eta_seconds = (nodes_left * time_per_node).round
104
+ # "#{nodes_left} nodes left. Last batch: #{(time_per_node * 1000.0).round(1)}ms / node (ETA: #{eta_seconds / 60} minutes)\r"
105
+ # else
106
+ # "Running first batch...\r"
107
+ # end
108
+
109
+ # print_output message
110
+ # end
111
+
112
+
113
+ # def id_batch_set(label, id_property, new_ids, count)
114
+ # tx = Neo4j::ActiveBase.new_transaction
115
+
116
+ # Neo4j::ActiveBase.current_session.query("MATCH (n:`#{label}`) WHERE NOT EXISTS(n.#{id_property})
117
+ # with COLLECT(n) as nodes, #{new_ids} as ids
118
+ # FOREACH(i in range(0,#{count - 1})|
119
+ # FOREACH(node in [nodes[i]]|
120
+ # SET node.#{id_property} = ids[i]))
121
+ # RETURN distinct(true)
122
+ # LIMIT #{count}")
123
+
124
+ # count
125
+ # rescue Neo4j::Server::CypherResponse::ResponseError, Faraday::TimeoutError
126
+ # new_max_per_batch = (max_per_batch * 0.8).round
127
+ # output "Error querying #{max_per_batch} nodes. Trying #{new_max_per_batch}"
128
+ # new_max_per_batch
129
+ # ensure
130
+ # tx.close
131
+ # end
132
+
133
+ # def default_max_per_batch
134
+ # 900
135
+ # end
136
+
137
+ # def new_id_for(model)
138
+ # if model.id_property_info[:type][:auto]
139
+ # SecureRandom.uuid
140
+ # else
141
+ # model.new.send(model.id_property_info[:type][:on])
142
+ # end
143
+ # end
125
144
  end
126
145
  end
127
146
  end