neo4j 7.2.3 → 8.0.0.alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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