neo4j 2.0.0.alpha.5-java → 2.0.0.alpha.6-java

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 (97) hide show
  1. data/CHANGELOG +12 -0
  2. data/Gemfile +0 -4
  3. data/README.rdoc +106 -62
  4. data/lib/neo4j.rb +7 -33
  5. data/lib/neo4j/performance.rb +43 -0
  6. data/lib/neo4j/rails/accept_id.rb +19 -18
  7. data/lib/neo4j/rails/attributes.rb +366 -120
  8. data/lib/neo4j/rails/finders.rb +41 -15
  9. data/lib/neo4j/rails/has_n.rb +203 -0
  10. data/lib/neo4j/rails/identity.rb +25 -0
  11. data/lib/neo4j/rails/model.rb +65 -242
  12. data/lib/neo4j/rails/nested_attributes.rb +108 -0
  13. data/lib/neo4j/rails/node_persistance.rb +56 -0
  14. data/lib/neo4j/rails/observer.rb +0 -2
  15. data/lib/neo4j/rails/persistence.rb +32 -154
  16. data/lib/neo4j/rails/rack_middleware.rb +26 -2
  17. data/lib/neo4j/rails/rails.rb +9 -6
  18. data/lib/neo4j/rails/railtie.rb +1 -2
  19. data/lib/neo4j/rails/relationship.rb +18 -125
  20. data/lib/neo4j/rails/relationship_persistence.rb +107 -0
  21. data/lib/neo4j/rails/relationships/node_dsl.rb +72 -44
  22. data/lib/neo4j/rails/relationships/relationships.rb +187 -59
  23. data/lib/neo4j/rails/relationships/rels_dsl.rb +18 -17
  24. data/lib/neo4j/rails/relationships/storage.rb +19 -17
  25. data/lib/neo4j/rails/timestamps.rb +53 -51
  26. data/lib/neo4j/rails/transaction.rb +9 -1
  27. data/lib/neo4j/rails/validations/uniqueness.rb +1 -1
  28. data/lib/neo4j/rails/versioning/versioning.rb +2 -2
  29. data/lib/neo4j/version.rb +1 -1
  30. data/lib/orm_adapter/adapters/neo4j.rb +47 -46
  31. data/neo4j.gemspec +1 -1
  32. metadata +10 -69
  33. data/lib/neo4j/algo/algo.rb +0 -294
  34. data/lib/neo4j/batch/batch.rb +0 -4
  35. data/lib/neo4j/batch/indexer.rb +0 -109
  36. data/lib/neo4j/batch/inserter.rb +0 -179
  37. data/lib/neo4j/batch/rule_inserter.rb +0 -24
  38. data/lib/neo4j/batch/rule_node.rb +0 -72
  39. data/lib/neo4j/config.rb +0 -177
  40. data/lib/neo4j/core_ext/class/inheritable_attributes.rb +0 -12
  41. data/lib/neo4j/core_ext/class/rewrite_inheritable_attributes.rb +0 -170
  42. data/lib/neo4j/database.rb +0 -158
  43. data/lib/neo4j/equal.rb +0 -21
  44. data/lib/neo4j/event_handler.rb +0 -263
  45. data/lib/neo4j/has_list/class_methods.rb +0 -11
  46. data/lib/neo4j/has_list/has_list.rb +0 -3
  47. data/lib/neo4j/has_list/mapping.rb +0 -133
  48. data/lib/neo4j/has_n/class_methods.rb +0 -119
  49. data/lib/neo4j/has_n/decl_relationship_dsl.rb +0 -246
  50. data/lib/neo4j/has_n/has_n.rb +0 -3
  51. data/lib/neo4j/has_n/mapping.rb +0 -98
  52. data/lib/neo4j/identity_map.rb +0 -140
  53. data/lib/neo4j/index/class_methods.rb +0 -108
  54. data/lib/neo4j/index/index.rb +0 -39
  55. data/lib/neo4j/index/indexer.rb +0 -341
  56. data/lib/neo4j/index/indexer_registry.rb +0 -68
  57. data/lib/neo4j/index/lucene_query.rb +0 -256
  58. data/lib/neo4j/load.rb +0 -25
  59. data/lib/neo4j/migrations/class_methods.rb +0 -110
  60. data/lib/neo4j/migrations/extensions.rb +0 -58
  61. data/lib/neo4j/migrations/lazy_node_mixin.rb +0 -41
  62. data/lib/neo4j/migrations/migration.rb +0 -112
  63. data/lib/neo4j/migrations/migrations.rb +0 -6
  64. data/lib/neo4j/migrations/node_mixin.rb +0 -80
  65. data/lib/neo4j/migrations/ref_node_wrapper.rb +0 -32
  66. data/lib/neo4j/model.rb +0 -4
  67. data/lib/neo4j/neo4j.rb +0 -216
  68. data/lib/neo4j/node.rb +0 -270
  69. data/lib/neo4j/node_mixin/class_methods.rb +0 -51
  70. data/lib/neo4j/node_mixin/node_mixin.rb +0 -141
  71. data/lib/neo4j/paginated.rb +0 -23
  72. data/lib/neo4j/property/class_methods.rb +0 -79
  73. data/lib/neo4j/property/property.rb +0 -111
  74. data/lib/neo4j/rails/mapping/property.rb +0 -183
  75. data/lib/neo4j/rails/rel_persistence.rb +0 -237
  76. data/lib/neo4j/relationship.rb +0 -239
  77. data/lib/neo4j/relationship_mixin/class_methods.rb +0 -36
  78. data/lib/neo4j/relationship_mixin/relationship_mixin.rb +0 -142
  79. data/lib/neo4j/relationship_set.rb +0 -58
  80. data/lib/neo4j/rels/rels.rb +0 -110
  81. data/lib/neo4j/rels/traverser.rb +0 -102
  82. data/lib/neo4j/rule/class_methods.rb +0 -201
  83. data/lib/neo4j/rule/event_listener.rb +0 -66
  84. data/lib/neo4j/rule/functions/count.rb +0 -43
  85. data/lib/neo4j/rule/functions/function.rb +0 -74
  86. data/lib/neo4j/rule/functions/functions.rb +0 -3
  87. data/lib/neo4j/rule/functions/sum.rb +0 -29
  88. data/lib/neo4j/rule/rule.rb +0 -150
  89. data/lib/neo4j/rule/rule_node.rb +0 -217
  90. data/lib/neo4j/to_java.rb +0 -31
  91. data/lib/neo4j/transaction.rb +0 -73
  92. data/lib/neo4j/traversal/filter_predicate.rb +0 -25
  93. data/lib/neo4j/traversal/prune_evaluator.rb +0 -14
  94. data/lib/neo4j/traversal/rel_expander.rb +0 -31
  95. data/lib/neo4j/traversal/traversal.rb +0 -141
  96. data/lib/neo4j/traversal/traverser.rb +0 -284
  97. data/lib/neo4j/type_converters/type_converters.rb +0 -288
@@ -1,3 +0,0 @@
1
- require 'neo4j/has_n/class_methods'
2
- require 'neo4j/has_n/decl_relationship_dsl'
3
- require 'neo4j/has_n/mapping'
@@ -1,98 +0,0 @@
1
- require 'neo4j/has_n/class_methods'
2
- require 'neo4j/has_n/decl_relationship_dsl'
3
- require 'neo4j/has_n/mapping'
4
-
5
- module Neo4j
6
- module HasN
7
-
8
- # The object created by a has_n or has_one Neo4j::NodeMixin class method which enables creating and traversal of nodes.
9
- #
10
- # Includes the Enumerable mixin.
11
- # The Neo4j::Mapping::ClassMethods::Relationship#has_n and Neo4j::Mapping::ClassMethods::Relationship#one
12
- # methods returns an object of this type.
13
- #
14
- # ==== See Also
15
- # Neo4j::HasN::ClassMethods
16
- #
17
- class Mapping
18
- include Enumerable
19
- include ToJava
20
-
21
- def initialize(node, dsl) # :nodoc:
22
- @node = node
23
- @dsl = dsl
24
- end
25
-
26
- def to_s
27
- "HasN::Mapping [#{@dsl.dir}, id: #{@node.neo_id} type: #{@dsl && @dsl.rel_type} dsl:#{@dsl}]"
28
- end
29
-
30
- def size
31
- self.to_a.size # TODO: Optimise this
32
- end
33
-
34
- alias_method :length, :size
35
-
36
-
37
- def [](index)
38
- i = 0
39
- each{|x| return x if i == index; i += 1}
40
- nil # out of index
41
- end
42
-
43
- # Pretend we are an array - this is necessarily for Rails actionpack/actionview/formhelper to work with this
44
- def is_a?(type)
45
- # ActionView requires this for nested attributes to work
46
- return true if Array == type
47
- super
48
- end
49
-
50
- # Required by the Enumerable mixin.
51
- def each
52
- @dsl.each_node(@node) {|n| yield n} # Should use yield here as passing &block through doesn't always work (why?)
53
- end
54
-
55
- # returns none wrapped nodes, you may get better performance using this method
56
- def _each
57
- @dsl._each_node(@node) {|n| yield n}
58
- end
59
-
60
- # Returns an real ruby array.
61
- def to_ary
62
- self.to_a
63
- end
64
-
65
- # Returns true if there are no node in this type of relationship
66
- def empty?
67
- first == nil
68
- end
69
-
70
-
71
- # Creates a relationship instance between this and the other node.
72
- # Returns the relationship object
73
- def new(other)
74
- @dsl.create_relationship_to(@node, other)
75
- end
76
-
77
-
78
- # Creates a relationship between this and the other node.
79
- #
80
- # ==== Example
81
- #
82
- # n1 = Node.new # Node has declared having a friend type of relationship
83
- # n2 = Node.new
84
- # n3 = Node.new
85
- #
86
- # n1 << n2 << n3
87
- #
88
- # ==== Returns
89
- # self
90
- #
91
- def <<(other)
92
- @dsl.create_relationship_to(@node, other)
93
- self
94
- end
95
- end
96
-
97
- end
98
- end
@@ -1,140 +0,0 @@
1
- module Neo4j
2
-
3
- # = Neo4j Identity Map
4
- #
5
- # Ensures that each object gets loaded only once by keeping every loaded
6
- # object in a map. Looks up objects using the map when referring to them.
7
- #
8
- # More information on Identity Map pattern:
9
- # http://www.martinfowler.com/eaaCatalog/identityMap.html
10
- #
11
- # == Configuration
12
- #
13
- # In order to enable IdentityMap, set <tt>config.neo4j.identity_map = true</tt>
14
- # in your <tt>config/application.rb</tt> file. If used outside rails, set Neo4j::Config[:identity_map] = true.
15
- #
16
- # IdentityMap is disabled by default and still in development (i.e. use it with care).
17
- #
18
- module IdentityMap
19
-
20
- class << self
21
- def enabled=(flag)
22
- Thread.current[:neo4j_identity_map] = flag
23
- end
24
-
25
- def enabled
26
- Thread.current[:neo4j_identity_map]
27
- end
28
-
29
- alias enabled? enabled
30
-
31
- def node_repository
32
- Thread.current[:node_identity_map] ||= java.util.HashMap.new
33
- end
34
-
35
- def rel_repository
36
- Thread.current[:rel_identity_map] ||= java.util.HashMap.new
37
- end
38
-
39
- def repository_for(neo_entity)
40
- return nil unless enabled?
41
- if neo_entity.class == Neo4j::Node
42
- node_repository
43
- elsif neo_entity.class == Neo4j::Relationship
44
- rel_repository
45
- else
46
- nil
47
- end
48
- end
49
-
50
- def use
51
- old, self.enabled = enabled, true
52
- yield if block_given?
53
- ensure
54
- self.enabled = old
55
- clear
56
- end
57
-
58
- def without
59
- old, self.enabled = enabled, false
60
- yield if block_given?
61
- ensure
62
- self.enabled = old
63
- end
64
-
65
- def get(neo_entity)
66
- r = repository_for(neo_entity)
67
- r && r.get(neo_entity.neo_id)
68
- end
69
-
70
- def add(neo_entity, wrapped_entity)
71
- r = repository_for(neo_entity)
72
- r && r.put(neo_entity.neo_id, wrapped_entity)
73
- end
74
-
75
- def remove(neo_entity)
76
- r = repository_for(neo_entity)
77
- r && r.remove(neo_entity.neo_id)
78
- end
79
-
80
- def remove_node_by_id(node_id)
81
- node_repository.remove(node_id)
82
- end
83
-
84
- def remove_rel_by_id(rel_id)
85
- rel_repository.remove(rel_id)
86
- end
87
-
88
- def clear
89
- node_repository.clear
90
- rel_repository.clear
91
- end
92
-
93
- def on_after_commit(*)
94
- clear
95
- end
96
-
97
- def on_neo4j_started(db)
98
- if not Neo4j::Config[:identity_map]
99
- db.event_handler.remove(self)
100
- end
101
- end
102
-
103
- end
104
-
105
-
106
- class Middleware
107
- class Body #:nodoc:
108
- def initialize(target, original)
109
- @target = target
110
- @original = original
111
- end
112
-
113
- def each(&block)
114
- @target.each(&block)
115
- end
116
-
117
- def close
118
- @target.close if @target.respond_to?(:close)
119
- ensure
120
- IdentityMap.enabled = @original
121
- IdentityMap.clear
122
- end
123
- end
124
-
125
- def initialize(app)
126
- @app = app
127
- end
128
-
129
- def call(env)
130
- enabled = IdentityMap.enabled
131
- IdentityMap.enabled = Neo4j::Config[:identity_map]
132
- status, headers, body = @app.call(env)
133
- [status, headers, Body.new(body, enabled)]
134
- end
135
- end
136
- end
137
- end
138
-
139
- Neo4j.unstarted_db.event_handler.add(Neo4j::IdentityMap)
140
-
@@ -1,108 +0,0 @@
1
- module Neo4j
2
- module Index
3
- module ClassMethods
4
- attr_reader :_indexer
5
-
6
- extend Forwardable
7
-
8
- def wp_query(options, pager, args, &block) #:nodoc:
9
- params = {}
10
- params[:page] = pager.current_page
11
- params[:per_page] = pager.per_page
12
- query = if args.empty?
13
- find(options, params, &block)
14
- else
15
- args << params.merge(options)
16
- find(*args, &block)
17
- end
18
-
19
- pager.replace [*query]
20
- pager.total_entries = query.size
21
- end
22
-
23
-
24
- ##
25
- # See Neo4j::Index::Indexer#index
26
- # Forwards to the indexer that should be used.
27
- # It is possible to share the same index for several different classes, see #node_indexer.
28
- # :singleton-method: index
29
-
30
- ##
31
- # See Neo4j::Index::Indexer#find
32
- # Forwards to the indexer that should be used.
33
- # It is possible to share the same index for several different classes, see #node_indexer.
34
- # :singleton-method: find
35
-
36
- ##
37
- # Specifies the location on the filesystem of the lucene index for the given index type.
38
- #
39
- # If not specified it will have the default location:
40
- #
41
- # Neo4j.config[:storage_path]/index/lucene/node|relationship/ParentModuleName_SubModuleName_ClassName-indextype
42
- #
43
- # Forwards to the Indexer#index_names class
44
- #
45
- # ==== Example
46
- # module Foo
47
- # class Person
48
- # include Neo4j::NodeMixin
49
- # index :name
50
- # index_names[:fulltext] = 'my_location'
51
- # end
52
- # end
53
- #
54
- # Person.index_names[:fulltext] => 'my_location'
55
- # Person.index_names[:exact] => 'Foo_Person-exact' # default Location
56
- #
57
- # The index can be prefixed, see Neo4j#threadlocal_ref_node= and multi dendency.
58
- #
59
- # :singleton-method: index_names
60
-
61
-
62
- ##
63
- # Returns a hash of which indexes has been defined and the type of index (:exact or :fulltext)
64
- #
65
- # :singleton-method: index_types
66
-
67
-
68
- def_delegators :@_indexer, :index, :find, :index?, :index_type?, :delete_index_type, :rm_field_type, :add_index, :rm_index, :index_type_for, :index_names, :index_types
69
-
70
- # Sets which indexer should be used for the given node class.
71
- # You can share an indexer between several different classes.
72
- #
73
- # ==== Example
74
- # class Contact
75
- # include Neo4j::NodeMixin
76
- # index :name
77
- # has_one :phone
78
- # end
79
- #
80
- # class Phone
81
- # include Neo4j::NodeMixin
82
- # property :phone
83
- # node_indexer Contact # put index on the Contact class instead
84
- # index :phone
85
- # end
86
- #
87
- # # Find an contact with a phone number, this works since they share the same index
88
- # Contact.find('phone: 12345').first #=> a phone object !
89
- #
90
- # ==== Returns
91
- # The indexer that should be used to index the given class
92
- def node_indexer(clazz)
93
- indexer(clazz, :node)
94
- end
95
-
96
- # Sets which indexer should be used for the given relationship class
97
- # Same as #node_indexer except that it indexes relationships instead of nodes.
98
- #
99
- def rel_indexer(clazz)
100
- indexer(clazz, :rel)
101
- end
102
-
103
- def indexer(clazz, type) #:nodoc:
104
- @_indexer ||= IndexerRegistry.create_for(self, clazz, type)
105
- end
106
- end
107
- end
108
- end
@@ -1,39 +0,0 @@
1
- require 'neo4j/index/class_methods'
2
- require 'neo4j/index/indexer_registry'
3
- require 'neo4j/index/indexer'
4
- require 'neo4j/index/lucene_query'
5
-
6
- module Neo4j
7
-
8
- module Index
9
-
10
- # Adds an index on the given property
11
- # Notice that you normally don't have to do that since you simply can declare
12
- # that the property and index should be updated automatically by using the class method #index.
13
- #
14
- # The index operation will take place immediately unlike when using the Neo4j::Index::ClassMethods::index
15
- # method which instead will guarantee that the neo4j database and the lucene database will be consistent.
16
- # It uses a two phase commit when the transaction is about to be committed.
17
- #
18
- # ==== See also
19
- # Neo4j::Index::ClassMethods::index
20
- #
21
- def add_index(field, value=self[field])
22
- converted_value = Neo4j::TypeConverters.convert(value, field, self.class)
23
- self.class.add_index(wrapped_entity, field.to_s, converted_value)
24
- end
25
-
26
- # Removes an index on the given property.
27
- # Just like #add_index this is normally not needed since you instead can declare it with the
28
- # #index class method instead.
29
- #
30
- # ==== See also
31
- # Neo4j::Index::ClassMethods::index
32
- # Neo4j::Index#add_index
33
- #
34
- def rm_index(field, value=self[field])
35
- self.class.rm_index(wrapped_entity, field.to_s, value)
36
- end
37
-
38
- end
39
- end
@@ -1,341 +0,0 @@
1
- module Neo4j
2
- module Index
3
- class Indexer
4
- attr_reader :indexer_for, :field_types, :via_relationships, :entity_type, :parent_indexers, :via_relationships
5
- alias_method :index_types, :field_types # public method accessible from node.index_types
6
-
7
- def initialize(clazz, type) #:nodoc:
8
- # part of the unique name of the index
9
- @indexer_for = clazz
10
-
11
- # do we want to index nodes or relationships ?
12
- @entity_type = type
13
-
14
- @indexes = {} # key = type, value = java neo4j index
15
- @field_types = {} # key = field, value = type (e.g. :exact or :fulltext)
16
- @via_relationships = {} # key = field, value = relationship
17
-
18
- # to enable subclass indexing to work properly, store a list of parent indexers and
19
- # whenever an operation is performed on this one, perform it on all
20
- @parent_indexers = []
21
- end
22
-
23
- def inherit_fields_from(parent_index) #:nodoc:
24
- return unless parent_index
25
- @field_types.reverse_merge!(parent_index.field_types) if parent_index.respond_to?(:field_types)
26
- @via_relationships.reverse_merge!(parent_index.via_relationships) if parent_index.respond_to?(:via_relationships)
27
- @parent_indexers << parent_index
28
- end
29
-
30
- def to_s
31
- "Indexer @#{object_id} [index_for:#{@indexer_for}, field_types=#{@field_types.keys.join(', ')}, via=#{@via_relationships.inspect}]"
32
- end
33
-
34
- # Add an index on a field so that it will be automatically updated by neo4j transactional events.
35
- #
36
- # The index method takes an optional configuration hash which allows you to:
37
- #
38
- # === Add an index on an a property
39
- #
40
- # Example:
41
- # class Person
42
- # include Neo4j::NodeMixin
43
- # index :name
44
- # end
45
- #
46
- # When the property name is changed/deleted or the node created it will keep the lucene index in sync.
47
- # You can then perform a lucene query like this: Person.find('name: andreas')
48
- #'
49
- # === Add index on other nodes.
50
- #
51
- # Example:
52
- #
53
- # class Person
54
- # include Neo4j::NodeMixin
55
- # has_n(:friends).to(Contact)
56
- # has_n(:known_by).from(:friends)
57
- # index :user_id, :via => :known_by
58
- # end
59
- #
60
- # Notice that you *must* specify an incoming relationship with the via key, as shown above.
61
- # In the example above an index <tt>user_id</tt> will be added to all Person nodes which has a <tt>friends</tt> relationship
62
- # that person with that user_id. This allows you to do lucene queries on your friends properties.
63
- #
64
- # === Set the type value to index
65
- # By default all values will be indexed as Strings.
66
- # If you want for example to do a numerical range query you must tell Neo4j.rb to index it as a numeric value.
67
- # You do that with the key <tt>type</tt> on the property.
68
- #
69
- # Example:
70
- # class Person
71
- # include Neo4j::NodeMixin
72
- # property :height, :weight, :type => Float
73
- # index :height, :weight
74
- # end
75
- #
76
- # Supported values for <tt>:type</tt> is <tt>String</tt>, <tt>Float</tt>, <tt>Date</tt>, <tt>DateTime</tt> and <tt>Fixnum</tt>
77
- #
78
- # === For more information
79
- # * See Neo4j::Index::LuceneQuery
80
- # * See #find
81
- #
82
- def index(*args)
83
- conf = args.last.kind_of?(Hash) ? args.pop : {}
84
- conf_no_via = conf.reject { |k,v| k == :via } # avoid endless recursion
85
-
86
- args.uniq.each do | field |
87
- if conf[:via]
88
- rel_dsl = @indexer_for._decl_rels[conf[:via]]
89
- raise "No relationship defined for '#{conf[:via]}'. Check class '#{@indexer_for}': index :#{field}, via=>:#{conf[:via]} <-- error. Define it with a has_one or has_n" unless rel_dsl
90
- raise "Only incoming relationship are possible to define index on. Check class '#{@indexer_for}': index :#{field}, via=>:#{conf[:via]}" unless rel_dsl.incoming?
91
- via_indexer = rel_dsl.target_class._indexer
92
-
93
- field = field.to_s
94
- @via_relationships[field] = rel_dsl
95
- via_indexer.index(field, conf_no_via)
96
- else
97
- @field_types[field.to_s] = conf[:type] || :exact
98
- end
99
- end
100
- end
101
-
102
- def remove_index_on_fields(node, props, deleted_relationship_set) #:nodoc:
103
- @field_types.keys.each { |field| rm_index(node, field, props[field]) if props[field] }
104
- # remove all via indexed fields
105
- @via_relationships.each_value do |dsl|
106
- indexer = dsl.target_class._indexer
107
- deleted_relationship_set.relationships(node.getId).each do |rel|
108
- indexer.remove_index_on_fields(rel._start_node, props, deleted_relationship_set)
109
- end
110
- end
111
- end
112
-
113
- def update_on_deleted_relationship(relationship) #:nodoc:
114
- update_on_relationship(relationship, false)
115
- end
116
-
117
- def update_on_new_relationship(relationship) #:nodoc:
118
- update_on_relationship(relationship, true)
119
- end
120
-
121
- def update_on_relationship(relationship, is_created) #:nodoc:
122
- rel_type = relationship.rel_type
123
- end_node = relationship._end_node
124
- # find which via relationship match rel_type
125
- @via_relationships.each_pair do |field, dsl|
126
- # have we declared an index on this changed relationship ?
127
- next unless dsl.rel_type == rel_type
128
-
129
- # yes, so find the node and value we should update the index on
130
- val = end_node[field]
131
- start_node = relationship._start_node
132
-
133
- # find the indexer to use
134
- indexer = dsl.target_class._indexer
135
-
136
- # is the relationship created or deleted ?
137
- if is_created
138
- indexer.update_index_on(start_node, field, nil, val)
139
- else
140
- indexer.update_index_on(start_node, field, val, nil)
141
- end
142
- end
143
- end
144
-
145
- def update_index_on(node, field, old_val, new_val) #:nodoc:
146
- if @via_relationships.include?(field)
147
- dsl = @via_relationships[field]
148
- target_class = dsl.target_class
149
-
150
- dsl._all_relationships(node).each do |rel|
151
- other = rel._start_node
152
- target_class._indexer.update_single_index_on(other, field, old_val, new_val)
153
- end
154
- end
155
- update_single_index_on(node, field, old_val, new_val)
156
- end
157
-
158
- def update_single_index_on(node, field, old_val, new_val) #:nodoc:
159
- if @field_types.has_key?(field)
160
- rm_index(node, field, old_val) if old_val
161
- add_index(node, field, new_val) if new_val
162
- end
163
- end
164
-
165
- # Returns true if there is an index on the given field.
166
- #
167
- def index?(field)
168
- @field_types.include?(field.to_s)
169
- end
170
-
171
- # Returns the type of index for the given field (e.g. :exact or :fulltext)
172
- #
173
- def index_type_for(field) #:nodoc:
174
- return nil unless index?(field)
175
- @field_types[field.to_s]
176
- end
177
-
178
- # Returns true if there is an index of the given type defined.
179
- def index_type?(type)
180
- @field_types.values.include?(type)
181
- end
182
-
183
- # Adds an index on the given entity
184
- # This is normally not needed since you can instead declare an index which will automatically keep
185
- # the lucene index in sync. See #index
186
- #
187
- def add_index(entity, field, value)
188
- return false unless @field_types.has_key?(field)
189
- conv_value = indexed_value_for(field, value)
190
- index = index_for_field(field.to_s)
191
- index.add(entity, field, conv_value)
192
- @parent_indexers.each { |i| i.add_index(entity, field, value) }
193
- end
194
-
195
- def indexed_value_for(field, value)
196
- # we might need to know what type the properties are when indexing and querying
197
- @decl_props ||= @indexer_for.respond_to?(:_decl_props) && @indexer_for._decl_props
198
-
199
- type = @decl_props && @decl_props[field.to_sym] && @decl_props[field.to_sym][:type]
200
- return value unless type
201
-
202
- if String != type
203
- org.neo4j.index.lucene.ValueContext.new(value).indexNumeric
204
- else
205
- org.neo4j.index.lucene.ValueContext.new(value)
206
- end
207
- end
208
-
209
- # Removes an index on the given entity
210
- # This is normally not needed since you can instead declare an index which will automatically keep
211
- # the lucene index in sync. See #index
212
- #
213
- def rm_index(entity, field, value)
214
- return false unless @field_types.has_key?(field)
215
- index_for_field(field).remove(entity, field, value)
216
- @parent_indexers.each { |i| i.rm_index(entity, field, value) }
217
- end
218
-
219
- # Performs a Lucene Query.
220
- #
221
- # In order to use this you have to declare an index on the fields first, see #index.
222
- # Notice that you should close the lucene query after the query has been executed.
223
- # You can do that either by provide an block or calling the Neo4j::Index::LuceneQuery#close
224
- # method. When performing queries from Ruby on Rails you do not need this since it will be automatically closed
225
- # (by Rack).
226
- #
227
- # === Example, with a block
228
- #
229
- # Person.find('name: kalle') {|query| puts "#{[*query].join(', )"}
230
- #
231
- # ==== Example
232
- #
233
- # query = Person.find('name: kalle')
234
- # puts "First item #{query.first}"
235
- # query.close
236
- #
237
- # === Return Value
238
- # It will return a Neo4j::Index::LuceneQuery object
239
- #
240
- #
241
- def find(query, params = {})
242
- # we might need to know what type the properties are when indexing and querying
243
- @decl_props ||= @indexer_for.respond_to?(:_decl_props) && @indexer_for._decl_props
244
-
245
- index = index_for_type(params[:type] || :exact)
246
- if query.is_a?(Hash) && (query.include?(:conditions) || query.include?(:sort))
247
- params.merge! query.except(:conditions)
248
- query.delete(:sort)
249
- query = query.delete(:conditions) if query.include?(:conditions)
250
- end
251
- query = (params[:wrapped].nil? || params[:wrapped]) ? LuceneQuery.new(index, @decl_props, query, params) : index.query(query)
252
-
253
- if block_given?
254
- begin
255
- ret = yield query
256
- ensure
257
- query.close
258
- end
259
- ret
260
- else
261
- query
262
- end
263
- end
264
-
265
- # delete the index, if no type is provided clear all types of indexes
266
- def delete_index_type(type=nil)
267
- if type
268
- #raise "can't clear index of type '#{type}' since it does not exist ([#{@field_types.values.join(',')}] exists)" unless index_type?(type)
269
- key = index_key(type)
270
- @indexes[key] && @indexes[key].delete
271
- @indexes[key] = nil
272
- else
273
- @indexes.each_value { |index| index.delete }
274
- @indexes.clear
275
- end
276
- end
277
-
278
- def on_neo4j_shutdown #:nodoc:
279
- # Since we might start the database again we must make sure that we don't keep any references to
280
- # an old lucene index in memory.
281
- @indexes.clear
282
- end
283
-
284
- # Removes the cached lucene index, can be useful for some RSpecs which needs to restart the Neo4j.
285
- #
286
- def rm_field_type(type=nil)
287
- if type
288
- @field_types.delete_if { |k, v| v == type }
289
- else
290
- @field_types.clear
291
- end
292
- end
293
-
294
- def index_for_field(field) #:nodoc:
295
- type = @field_types[field]
296
- @indexes[index_key(type)] ||= create_index_with(type)
297
- end
298
-
299
- def index_for_type(type) #:nodoc:
300
- @indexes[index_key(type)] ||= create_index_with(type)
301
- end
302
-
303
- def index_key(type)
304
- index_names[type] + type.to_s
305
- end
306
-
307
- def lucene_config(type) #:nodoc:
308
- conf = Neo4j::Config[:lucene][type.to_sym]
309
- raise "unknown lucene type #{type}" unless conf
310
- conf
311
- end
312
-
313
- def create_index_with(type) #:nodoc:
314
- db = Neo4j.started_db
315
- index_config = lucene_config(type)
316
- if @entity_type == :node
317
- db.lucene.for_nodes(index_names[type], index_config)
318
- else
319
- db.lucene.for_relationships(index_names[type], index_config)
320
- end
321
- end
322
-
323
- def index_names
324
- @index_names ||= Hash.new do |hash, index_type|
325
- default_filename = index_prefix + @indexer_for.to_s.gsub('::', '_')
326
- hash.fetch(index_type) {"#{default_filename}_#{index_type}"}
327
- end
328
- end
329
-
330
- protected
331
- def index_prefix
332
- return "" unless Neo4j.running?
333
- return "" unless @indexer_for.respond_to?(:ref_node_for_class)
334
- ref_node = @indexer_for.ref_node_for_class.wrapper
335
- prefix = ref_node.send(:_index_prefix) if ref_node.respond_to?(:_index_prefix)
336
- prefix ||= ref_node[:name] # To maintain backward compatiblity
337
- prefix.blank? ? "" : prefix + "_"
338
- end
339
- end
340
- end
341
- end