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

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.
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