neo4j 1.0.0.beta.13 → 1.0.0.beta.14

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,3 +1,12 @@
1
1
  source :gemcutter
2
2
 
3
3
  gemspec
4
+
5
+ group 'test' do
6
+ gem "rake", ">= 0.8.7"
7
+ gem "rdoc", ">= 2.5.10"
8
+ gem "horo", ">= 1.0.2"
9
+ gem "rspec-apigen", ">= 0.0.4"
10
+ gem "rspec", ">= 2.0.0"
11
+ gem "rspec-rails-matchers", ">= 0.2.1"
12
+ end
data/README.rdoc CHANGED
@@ -1,40 +1,104 @@
1
- = Neo4j.rb
1
+ == Welcome to Neo4j.rb
2
2
 
3
3
  Neo4j.rb is a graph database for JRuby.
4
4
 
5
-
6
-
7
- It provides:
8
- * Mapping of ruby objects to nodes in networks rather than in tables.
9
- * Dynamic, and schema-free - no need to declare nodes/properties/relationships in advance.
10
- * Storage of ruby object to a file system.
11
- * Fast traversal of relationships between nodes in a huge node space.
12
- * Transaction with rollbacks support.
13
- * Indexing and querying of ruby objects.
14
- * Migration and BatchInserter support
15
- * Can be used instead of ActiveRecord in Ruby on Rails or Merb
16
- * Can be accessible as REST resources.
5
+ You can think of \Neo4j as a high-performance graph engine with all the features of a mature and robust database.
6
+ The programmer works with an object-oriented, flexible network structure rather than with strict and static tables — yet enjoys all the benefits of a fully transactional, enterprise-strength database.
17
7
 
18
8
  It uses two powerful and mature Java libraries:
19
- * Neo4J (http://www.neo4j.org/) - for persistence and traversal of the graph
20
- * Lucene (http://lucene.apache.org/java/docs/index.html) for querying and indexing.
9
+ * {Neo4J}[http://www.neo4j.org] - for persistence and traversal of the graph
10
+ * {Lucene}[http://lucene.apache.org/java/docs/index.html] for querying and indexing.
11
+
12
+ === Why Neo4j.rb or a Graph Database ?
13
+
14
+ Here are some of the major benefits of Neo4j.rb
15
+
16
+ * Domain Modeling - use the language of a graph (nodes/relationship/properties) to express your domain !
17
+ * Schema Less and Efficient storage of Semi Structured Information
18
+ * No {O/R mismatch}[http://en.wikipedia.org/wiki/Object-relational_impedance_mismatch] - very natural to map a graph to an Object Oriented language like Ruby.
19
+ * {Performance}[http://www.oscon.com/oscon2009/public/schedule/detail/8364]
20
+ * Embedded Database - no database tier, easier to install, test, deploy and configure. It is run in the same process as your application.
21
+ * Express Queries as Traversals
22
+ * Fast deep traversal instead of slow SQL queries that span many table joins.
23
+ * Very natural to express graph related problem with traversals (recommendation engine, find shortest parth etc..)
24
+ * Seamless integration with Ruby on Rails.
25
+ * ACID Transaction with rollbacks support.
21
26
 
22
27
  === Documentation
23
- * Wiki: http://github.com/andreasronge/neo4j/wiki
24
- * API Documentation - http://neo4j.rubyforge.org/ (of the released version)
25
28
 
26
- === Project information
27
- * GitHub - http://github.com/andreasronge/neo4j/tree/master
28
- * Issue Tracking - http://neo4j.lighthouseapp.com
29
- * Twitter - http://twitter.com/ronge
30
- * IRC - #neo4j @ irc.freenode.net
31
- * Source repo - git://github.com/andreasronge/neo4j.git
32
- * Mailing list - http://groups.google.com/group/neo4jrb (neo4jrb@googlegroups.com)
29
+ * {Documentation and Getting Started with Neo4j}[http://github.com/andreasronge/neo4j/wiki]
30
+ * {API Documentation (released version)}[http://neo4j.rubyforge.org]
31
+
32
+ === Some Examples
33
+
34
+ ==== Neo4j::Node
35
+
36
+ Example of creating a Neo4j::Node
37
+
38
+ require "rubygems"
39
+ require 'neo4j'
40
+
41
+ Neo4j::Transaction.run do
42
+ node = Neo4j::Node.new :name => 'andreas'
43
+ node.outgoing(:friends) << Neo4j::Node.new :name => 'peter'
44
+ node.outgoing(:friends).each {|node| puts "name #{node[:name]}"}
45
+ end
46
+
47
+ ==== Neo4j::Mapping::NodeMixin
48
+
49
+ Example of mapping a ruby class to a node and delaring properties and relationships and lucene index.
50
+
51
+ class Person
52
+ include Neo4j::NodeMixin
53
+ property :name
54
+ property :city
55
+
56
+ has_n :friends
57
+ has_one :address
58
+ index :name
59
+ end
60
+
61
+ # assume we have an transaction already running
62
+ andreas = Person.new :name => 'andreas'
63
+ andreas.friends << Person.new :name => 'peter'
64
+ andreas.friends.each {|person| puts "name #{person.name}" }
65
+ Person.find("name: andreas").first.name # => 'andreas'
66
+
67
+ ==== Neo4j::Rails::Model
68
+
69
+ Example of using Neo4j with Rails 3 (ActiveModel)
70
+
71
+ class User < Neo4j::Model
72
+ attr_accessor :password
73
+ attr_accessible :email, :password, :password_confirmation, :pending_account
74
+
75
+ after_save :encrypt_password
76
+
77
+ email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
78
+
79
+ validates :email, :presence => true,:format => { :with => email_regex }
80
+ validates :email, :uniqueness => true, :unless => :pending_account?
81
+ accepts_nested_attributes_for :avatar, :allow_destroy => true
82
+
83
+ property :email
84
+ index :email
85
+
86
+ has_one(:avatar).to(Avator)
87
+
88
+ ...
89
+ end
33
90
 
34
91
  === Presentation Materials and other URLs
35
- * Ruby Manor 2008 - Jonathan Conway: http://jaikoo.com/assets/presentations/neo4j.pdf
36
- * Nordic Ruby 2010 (upcoming May 21-23) http://nordicruby.org/speakers#user_29
37
- * Neo4j wiki - http://wiki.neo4j.org/content/Main_Page (check the guidelines and domain modeling gallery pages)
92
+ * {Intoduction to Neo4j.rb}[http://www.slideshare.net/andreasronge/neo4jrb]
93
+ * {Nordic Ruby 2010 May 21-23}[http://nordicruby.org/speakers#user_29]
94
+ * {Neo4j wiki, check the guidelines and domain modeling gallery pages}[http://wiki.neo4j.org/content/Main_Page]
95
+
96
+ === Project information
97
+ * {GitHub}[http://github.com/andreasronge/neo4j/tree/master]
98
+ * {Lighthouse Issue Tracking}[http://neo4j.lighthouseapp.com]
99
+ * {Twitter}[http://twitter.com/ronge]
100
+ * IRC - #neo4j @ irc.freenode.net
101
+ * {Mailing list, neo4jrb@googlegroups.com}[http://groups.google.com/group/neo4jrb]
38
102
 
39
103
  === Contributing
40
104
 
@@ -46,4 +110,4 @@ Please also check/add issues at lighthouse, http://neo4j.lighthouseapp.com
46
110
  === License
47
111
  * Neo4j.rb - MIT, see the LICENSE file http://github.com/andreasronge/neo4j/tree/master/LICENSE.
48
112
  * Lucene - Apache, see http://lucene.apache.org/java/docs/features.html
49
- * Neo4j - Dual free software/commercial license, see http://neo4j.org/
113
+ * \Neo4j - Dual free software/commercial license, see http://neo4j.org/
data/lib/neo4j.rb CHANGED
@@ -12,10 +12,17 @@ require 'neo4j/jars/neo4j-lucene-index-0.1-20101002.153213-102.jar'
12
12
  require 'neo4j/to_java'
13
13
  require 'neo4j/version'
14
14
  require 'neo4j/equal'
15
- require 'neo4j/index'
16
- require 'neo4j/relationship_traverser'
15
+
17
16
  require 'neo4j/event_handler'
18
17
  require 'neo4j/database'
18
+ require 'neo4j/neo4j'
19
+
20
+ require 'neo4j/index/index'
21
+ require 'neo4j/index/class_methods'
22
+ require 'neo4j/index/index_registry'
23
+ require 'neo4j/index/indexer'
24
+ require 'neo4j/index/wrapped_query'
25
+ require 'neo4j/relationship_traverser'
19
26
  require 'neo4j/node_traverser'
20
27
  require 'neo4j/property'
21
28
  require 'neo4j/transaction'
@@ -24,7 +31,6 @@ require 'neo4j/load'
24
31
  require 'neo4j/relationship'
25
32
  require 'neo4j/node'
26
33
  require 'neo4j/config'
27
- require 'neo4j/neo4j'
28
34
  require 'neo4j/mapping/class_methods/init_node'
29
35
  require 'neo4j/mapping/class_methods/init_rel'
30
36
  require 'neo4j/mapping/class_methods/root'
@@ -20,8 +20,11 @@ module Neo4j
20
20
  if @running
21
21
  @graph.unregister_transaction_event_handler(@event_handler)
22
22
  @event_handler.neo4j_shutdown(self)
23
+ @graph.shutdown
24
+ @graph = nil
25
+ @lucene = nil
23
26
  end
24
- @graph.shutdown
27
+
25
28
  @running = false
26
29
  end
27
30
 
@@ -37,7 +40,14 @@ module Neo4j
37
40
  def each_node
38
41
  iter = @graph.all_nodes.iterator
39
42
  while (iter.hasNext)
40
- yield Node.wrapper(iter.next)
43
+ yield iter.next.wrapper
44
+ end
45
+ end
46
+
47
+ def _each_node
48
+ iter = @graph.all_nodes.iterator
49
+ while (iter.hasNext)
50
+ yield iter.next
41
51
  end
42
52
  end
43
53
 
data/lib/neo4j/equal.rb CHANGED
@@ -1,9 +1,5 @@
1
1
  module Neo4j
2
2
  module Equal
3
- def neo_id
4
- getId
5
- end
6
-
7
3
  def equal?(o)
8
4
  eql?(o)
9
5
  end
@@ -19,9 +19,9 @@ module Neo4j
19
19
  data.created_nodes.each{|node| node_created(node)}
20
20
  data.assigned_node_properties.each { |tx_data| property_changed(tx_data.entity, tx_data.key, tx_data.previously_commited_value, tx_data.value) }
21
21
  data.removed_node_properties.each { |tx_data| property_changed(tx_data.entity, tx_data.key, tx_data.previously_commited_value, nil) unless data.deleted_nodes.include?(tx_data.entity) }
22
- data.deleted_nodes.each { |node| node_deleted(node, deleted_properties_for(node,data))}
23
- data.created_relationships.each {|rel| relationship_created(rel)}
24
- data.deleted_relationships.each {|rel| relationship_deleted(rel, deleted_rel_properties_for(rel, data))}
22
+ data.deleted_nodes.each { |node| node_deleted(node, deleted_properties_for(node,data), data)}
23
+ data.created_relationships.each {|rel| relationship_created(rel, data)}
24
+ data.deleted_relationships.each {|rel| relationship_deleted(rel, deleted_rel_properties_for(rel, data), data)}
25
25
  data.assigned_relationship_properties.each { |tx_data| rel_property_changed(tx_data.entity, tx_data.key, tx_data.previously_commited_value, tx_data.value) }
26
26
  data.removed_relationship_properties.each {|tx_data| rel_property_changed(tx_data.entity, tx_data.key, tx_data.previously_commited_value, nil) unless data.deleted_relationships.include?(tx_data.entity) }
27
27
  end
@@ -69,16 +69,16 @@ module Neo4j
69
69
  @listeners.each {|li| li.on_node_created(node) if li.respond_to?(:on_node_created)}
70
70
  end
71
71
 
72
- def node_deleted(node,old_properties)
73
- @listeners.each {|li| li.on_node_deleted(node,old_properties) if li.respond_to?(:on_node_deleted)}
72
+ def node_deleted(node,old_properties, data)
73
+ @listeners.each {|li| li.on_node_deleted(node,old_properties, data) if li.respond_to?(:on_node_deleted)}
74
74
  end
75
75
 
76
- def relationship_created(relationship)
77
- @listeners.each {|li| li.on_relationship_created(relationship) if li.respond_to?(:on_relationship_created)}
76
+ def relationship_created(relationship, tx_data)
77
+ @listeners.each {|li| li.on_relationship_created(relationship, tx_data) if li.respond_to?(:on_relationship_created)}
78
78
  end
79
79
 
80
- def relationship_deleted(relationship, old_props)
81
- @listeners.each {|li| li.on_relationship_deleted(relationship, old_props) if li.respond_to?(:on_relationship_deleted)}
80
+ def relationship_deleted(relationship, old_props, data)
81
+ @listeners.each {|li| li.on_relationship_deleted(relationship, old_props, data) if li.respond_to?(:on_relationship_deleted)}
82
82
  end
83
83
 
84
84
  def property_changed(node, key, old_value, new_value)
@@ -0,0 +1,61 @@
1
+ module Neo4j
2
+ module Index
3
+ module ClassMethods
4
+ attr_reader :_indexer
5
+
6
+ extend Forwardable
7
+
8
+ ##
9
+ # See Neo4j::Index::Indexer#index
10
+ # Forwards to the indexer that should be used.
11
+ # It is possible to share the same index for several different classes, see #node_indexer.
12
+ # :singleton-method: index
13
+
14
+ ##
15
+ # See Neo4j::Index::Indexer#find
16
+ # Forwards to the indexer that should be used.
17
+ # It is possible to share the same index for several different classes, see #node_indexer.
18
+ # :singleton-method: find
19
+
20
+
21
+ def_delegators :@_indexer, :index, :find, :index?, :index_type?, :clear_index_type, :rm_index_type, :add_index, :rm_index, :index_type_for, :index_name
22
+
23
+
24
+ # Sets which indexer should be used for the given node class.
25
+ # You can share an indexer between several different classes.
26
+ #
27
+ # ==== Example
28
+ # class Contact
29
+ # include Neo4j::NodeMixin
30
+ # index :name
31
+ # has_one :phone
32
+ # end
33
+ #
34
+ # class Phone
35
+ # include Neo4j::NodeMixin
36
+ # property :phone
37
+ # index :phone, :indexer => Person, :via => proc{|node| node.incoming(:phone).first}
38
+ # end
39
+ #
40
+ # # Find an contact with a phone number, this works since they share the same index
41
+ # Contact.find('phone: 12345 AND name: 'pelle'')
42
+ #
43
+ # ==== Returns
44
+ # The indexer that should be used to index the given class
45
+ def node_indexer(clazz)
46
+ indexer(clazz, :node)
47
+ end
48
+
49
+ # Sets which indexer should be used for the given relationship class
50
+ # Same as #node_indexer except that it indexes relationships instead of nodes.
51
+ #
52
+ def rel_indexer(clazz)
53
+ indexer(clazz, :rel)
54
+ end
55
+
56
+ def indexer(clazz, type) #:nodoc:
57
+ @_indexer = IndexerRegistry.create_for(self, clazz, type)
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,33 @@
1
+ module Neo4j
2
+
3
+ module Index
4
+
5
+ # Adds an index on the given property
6
+ # Notice that you normally don't have to do that since you simply can declare
7
+ # that the property and index should be updated automatically by using the class method #index.
8
+ #
9
+ # The index operation will take place immediately unlike when using the Neo4j::Index::ClassMethods::index
10
+ # method which instead will guarantee that the neo4j database and the lucene database will be consistent.
11
+ # It uses a two phase commit when the transaction is about to be committed.
12
+ #
13
+ # ==== See also
14
+ # Neo4j::Index::ClassMethods::index
15
+ #
16
+ def add_index(field, value=self[field])
17
+ self.class.add_index(wrapped_entity, field.to_s, value)
18
+ end
19
+
20
+ # Removes an index on the given property.
21
+ # Just like #add_index this is normally not needed since you instead can declare it with the
22
+ # #index class method instead.
23
+ #
24
+ # ==== See also
25
+ # Neo4j::Index::ClassMethods::index
26
+ # Neo4j::Index#add_index
27
+ #
28
+ def rm_index(field, value=self[field])
29
+ self.class.rm_index(wrapped_entity, field.to_s, value)
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,67 @@
1
+ module Neo4j
2
+ module Index
3
+ class IndexerRegistry #:nodoc:
4
+ class << self
5
+
6
+ def clear_all_indexes
7
+ @@indexers.values.each {|i| i.clear_index_type}
8
+ end
9
+
10
+ def create_for(this_clazz, using_other_clazz, type)
11
+ @@indexers ||= {}
12
+ @@indexers[this_clazz.to_s] = @@indexers[using_other_clazz.to_s] || Indexer.new(this_clazz, type)
13
+ @@indexers[this_clazz.to_s]
14
+ end
15
+
16
+ def find_by_class(classname)
17
+ @@indexers[classname]
18
+ end
19
+
20
+ def on_node_deleted(node, old_props, tx_data)
21
+ indexer = find_by_class(old_props['_classname'] || node.class.to_s)
22
+ indexer && indexer.remove_index_on_fields(node, old_props, tx_data)
23
+ end
24
+
25
+ def on_property_changed(node, field, old_val, new_val)
26
+ classname = node['_classname'] || node.class.to_s
27
+ indexer = find_by_class(classname)
28
+ indexer && indexer.update_index_on(node, field, old_val, new_val)
29
+ end
30
+
31
+ def on_rel_property_changed(rel, field, old_val, new_val)
32
+ # works exactly like for nodes
33
+ on_property_changed(rel, field, old_val, new_val)
34
+ end
35
+
36
+ def on_relationship_created(rel, tx_data)
37
+ end_node = rel._end_node
38
+ # if end_node was created in this transaction then it will be handled in on_property_changed
39
+ created = tx_data.created_nodes.find{|n| n.neo_id == end_node.neo_id}
40
+ unless created
41
+ indexer = find_by_class(end_node['_classname'])
42
+ indexer && indexer.update_on_new_relationship(rel)
43
+ end
44
+ end
45
+
46
+ def on_relationship_deleted(rel, old_props, tx_data)
47
+ on_node_deleted(rel, old_props, tx_data)
48
+ # if only the relationship has been deleted then we have to remove the index
49
+ # if both the relationship and the node has been deleted then the index will be removed in the
50
+ # on_node_deleted callback
51
+ end_node = rel._end_node
52
+ deleted = tx_data.deleted_nodes.find{|n| n.neo_id == end_node.neo_id}
53
+ unless deleted
54
+ indexer = find_by_class(end_node['_classname'])
55
+ indexer && indexer.update_on_deleted_relationship(rel)
56
+ end
57
+ end
58
+
59
+ def on_neo4j_shutdown(*)
60
+ @@indexers.each_value {|indexer| indexer.on_neo4j_shutdown}
61
+ end
62
+ end
63
+ end
64
+ Neo4j.unstarted_db.event_handler.add(IndexerRegistry)
65
+
66
+ end
67
+ end
@@ -0,0 +1,193 @@
1
+ module Neo4j
2
+ module Index
3
+ class Indexer #:nodoc:
4
+ attr_reader :indexer_for
5
+
6
+ def initialize(clazz, type)
7
+ # part of the unique name of the index
8
+ @indexer_for = clazz
9
+
10
+ # do we want to index nodes or relationships ?
11
+ @type = type
12
+
13
+ @indexes = {} # key = type, value = java neo4j index
14
+ @field_types = {} # key = field, value = type (e.g. :exact or :fulltext)
15
+ @via_relationships = {} # key = field, value = relationship
16
+ end
17
+
18
+ def to_s
19
+ "Indexer @#{object_id} [index_for:#{@indexer_for}, field_types=#{@field_types.keys.join(', ')}, via=#{@via_relationships.inspect}]"
20
+ end
21
+
22
+ # add an index on a field so that it will be automatically updated by neo4j events.
23
+ def index(field, conf = {})
24
+ if conf[:via]
25
+ rel_dsl = @indexer_for._decl_rels[conf[:via]]
26
+ 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
27
+ raise "Only incoming relationship are possible to define index on. Check class '#{@indexer_for}': index :#{field}, via=>:#{conf[:via]}" unless rel_dsl.incoming?
28
+ via_indexer = rel_dsl.to_class._indexer
29
+
30
+ field = field.to_s
31
+ @via_relationships[field] = rel_dsl
32
+ conf.delete :via # avoid endless recursion
33
+ via_indexer.index(field, conf)
34
+ else
35
+ raise "Already defined an (via?) index on #{field}, Using the same index for from two classes ? Check index :#{field}, :via => :#{@indexer_for}" if @field_types[field.to_s]
36
+ @field_types[field.to_s] = conf[:type] || :exact
37
+ end
38
+ end
39
+
40
+ def remove_index_on_fields(node, props, tx_data)
41
+ @field_types.keys.each { |field| rm_index(node, field, props[field]) if props[field] }
42
+ # remove all via indexed fields
43
+ @via_relationships.each_value do |dsl|
44
+ indexer = dsl.to_class._indexer
45
+ tx_data.deleted_relationships.each do |rel|
46
+ start_node = rel._start_node
47
+ next if node != rel._end_node
48
+ indexer.remove_index_on_fields(start_node, props, tx_data)
49
+ end
50
+ end
51
+ end
52
+
53
+ def update_on_deleted_relationship(relationship)
54
+ update_on_relationship(relationship, false)
55
+ end
56
+
57
+ def update_on_new_relationship(relationship)
58
+ update_on_relationship(relationship, true)
59
+ end
60
+
61
+ def update_on_relationship(relationship, is_created)
62
+ rel_type = relationship.rel_type
63
+ end_node = relationship._end_node
64
+ # find which via relationship match rel_type
65
+ @via_relationships.each_pair do |field, dsl|
66
+ # have we declared an index on this changed relationship ?
67
+ next unless dsl.incoming_dsl.namespace_type == rel_type
68
+
69
+ # yes, so find the node and value we should update the index on
70
+ val = end_node[field]
71
+ start_node = relationship._start_node
72
+
73
+ # find the indexer to use
74
+ indexer = dsl.to_class._indexer
75
+
76
+ # is the relationship created or deleted ?
77
+ if is_created
78
+ indexer.update_index_on(start_node, field, nil, val)
79
+ else
80
+ indexer.update_index_on(start_node, field, val, nil)
81
+ end
82
+ end
83
+ end
84
+
85
+ def update_index_on(node, field, old_val, new_val)
86
+ if @via_relationships.include?(field)
87
+ dsl = @via_relationships[field]
88
+ to_class = dsl.to_class
89
+
90
+ dsl.all_relationships(node).each do |rel|
91
+ other = rel._start_node
92
+ to_class._indexer.update_index_on(other, field, old_val, new_val)
93
+ end
94
+ end
95
+
96
+ if @field_types.include?(field)
97
+ rm_index(node, field, old_val) if old_val
98
+ add_index(node, field, new_val) if new_val
99
+ end
100
+ end
101
+
102
+ def index?(field)
103
+ @field_types.include?(field.to_s)
104
+ end
105
+
106
+ def index_type_for(field)
107
+ return nil unless index?(field)
108
+ @field_types[field.to_s]
109
+ end
110
+
111
+ def index_type?(type)
112
+ @field_types.values.include?(type)
113
+ end
114
+
115
+ def add_index(entity, field, value)
116
+ index_for_field(field.to_s).add(entity, field, value)
117
+ end
118
+
119
+ def rm_index(entity, field, value)
120
+ index_for_field(field).remove(entity, field, value)
121
+ end
122
+
123
+ def find(query, params = {})
124
+ type = params[:type] || :exact
125
+ index = index_for_type(type)
126
+ query = (params[:wrapped].nil? || params[:wrapped]) ? WrappedQuery.new(index, query) : index.query(query)
127
+
128
+ if block_given?
129
+ begin
130
+ ret = yield query
131
+ ensure
132
+ query.close
133
+ end
134
+ ret
135
+ else
136
+ query
137
+ end
138
+ end
139
+
140
+ # clears the index, if no type is provided clear all types of indexes
141
+ def clear_index_type(type=nil)
142
+ if type
143
+ #raise "can't clear index of type '#{type}' since it does not exist ([#{@field_types.values.join(',')}] exists)" unless index_type?(type)
144
+ @indexes[type] && @indexes[type].clear
145
+ else
146
+ @indexes.each_value { |index| index.clear }
147
+ end
148
+ end
149
+
150
+ def on_neo4j_shutdown
151
+ # Since we might start the database again we must make sure that we don't keep any references to
152
+ # an old lucene index service.
153
+ @indexes.clear
154
+ end
155
+
156
+ def rm_index_type(type=nil)
157
+ if type
158
+ @field_types.delete_if { |k, v| v == type }
159
+ else
160
+ @field_types.clear
161
+ end
162
+ end
163
+
164
+ def index_for_field(field)
165
+ type = @field_types[field]
166
+ @indexes[type] ||= create_index_with(type)
167
+ end
168
+
169
+ def index_for_type(type)
170
+ @indexes[type] ||= create_index_with(type)
171
+ end
172
+
173
+ def lucene_config(type)
174
+ conf = Neo4j::Config[:lucene][type.to_sym]
175
+ raise "unknown lucene type #{type}" unless conf
176
+ conf
177
+ end
178
+
179
+ def create_index_with(type)
180
+ db=Neo4j.started_db
181
+ index_config = lucene_config(type)
182
+ if @type == :node
183
+ db.lucene.node_index("#{@indexer_for}-#{type}", index_config)
184
+ else
185
+ db.lucene.relationship_index("#{@indexer_for}-#{type}", index_config)
186
+ end
187
+ end
188
+
189
+ end
190
+
191
+ end
192
+
193
+ end