neo4j 1.0.0.beta.20 → 3.0.0.alpha.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG +243 -0
- data/CONTRIBUTORS +12 -0
- data/Gemfile +10 -11
- data/README.md +23 -0
- data/bin/neo4j-jars +33 -0
- data/config/locales/en.yml +5 -0
- data/config/neo4j/config.yml +98 -0
- data/lib/neo4j.rb +28 -68
- data/lib/neo4j/active_node.rb +60 -0
- data/lib/neo4j/active_node/callbacks.rb +41 -0
- data/lib/neo4j/active_node/has_n.rb +138 -0
- data/lib/neo4j/active_node/has_n/decl_rel.rb +236 -0
- data/lib/neo4j/active_node/has_n/nodes.rb +82 -0
- data/lib/neo4j/active_node/identity.rb +28 -0
- data/lib/neo4j/active_node/initialize.rb +24 -0
- data/lib/neo4j/active_node/labels.rb +142 -0
- data/lib/neo4j/active_node/persistence.rb +193 -0
- data/lib/neo4j/active_node/property.rb +41 -0
- data/lib/neo4j/active_node/rels.rb +11 -0
- data/lib/neo4j/active_node/validations.rb +51 -0
- data/lib/neo4j/railtie.rb +40 -0
- data/lib/neo4j/version.rb +1 -1
- data/lib/neo4j/wrapper.rb +25 -0
- data/neo4j.gemspec +25 -15
- metadata +136 -149
- data/README.rdoc +0 -135
- data/lib/generators/neo4j.rb +0 -65
- data/lib/generators/neo4j/model/model_generator.rb +0 -39
- data/lib/generators/neo4j/model/templates/model.erb +0 -7
- data/lib/neo4j/config.rb +0 -153
- data/lib/neo4j/database.rb +0 -56
- data/lib/neo4j/equal.rb +0 -21
- data/lib/neo4j/event_handler.rb +0 -116
- data/lib/neo4j/index/class_methods.rb +0 -62
- data/lib/neo4j/index/index.rb +0 -33
- data/lib/neo4j/index/indexer.rb +0 -312
- data/lib/neo4j/index/indexer_registry.rb +0 -68
- data/lib/neo4j/index/lucene_query.rb +0 -191
- data/lib/neo4j/jars/geronimo-jta_1.1_spec-1.1.1.jar +0 -0
- data/lib/neo4j/jars/lucene-core-3.0.2.jar +0 -0
- data/lib/neo4j/jars/neo4j-index-1.2-1.2.M03.jar +0 -0
- data/lib/neo4j/jars/neo4j-kernel-1.2-1.2.M03.jar +0 -0
- data/lib/neo4j/jars/neo4j-lucene-index-0.2-1.2.M03.jar +0 -0
- data/lib/neo4j/load.rb +0 -21
- data/lib/neo4j/mapping/class_methods/init_node.rb +0 -50
- data/lib/neo4j/mapping/class_methods/init_rel.rb +0 -35
- data/lib/neo4j/mapping/class_methods/property.rb +0 -80
- data/lib/neo4j/mapping/class_methods/relationship.rb +0 -90
- data/lib/neo4j/mapping/class_methods/root.rb +0 -31
- data/lib/neo4j/mapping/class_methods/rule.rb +0 -295
- data/lib/neo4j/mapping/decl_relationship_dsl.rb +0 -214
- data/lib/neo4j/mapping/has_n.rb +0 -83
- data/lib/neo4j/mapping/node_mixin.rb +0 -97
- data/lib/neo4j/mapping/relationship_mixin.rb +0 -117
- data/lib/neo4j/model.rb +0 -4
- data/lib/neo4j/neo4j.rb +0 -95
- data/lib/neo4j/node.rb +0 -131
- data/lib/neo4j/node_mixin.rb +0 -4
- data/lib/neo4j/node_relationship.rb +0 -149
- data/lib/neo4j/node_traverser.rb +0 -157
- data/lib/neo4j/property.rb +0 -111
- data/lib/neo4j/rails/finders.rb +0 -121
- data/lib/neo4j/rails/lucene_connection_closer.rb +0 -19
- data/lib/neo4j/rails/mapping/property.rb +0 -35
- data/lib/neo4j/rails/model.rb +0 -324
- data/lib/neo4j/rails/railtie.rb +0 -16
- data/lib/neo4j/rails/transaction.rb +0 -67
- data/lib/neo4j/rails/tx_methods.rb +0 -15
- data/lib/neo4j/rails/validations/non_nil.rb +0 -11
- data/lib/neo4j/rails/validations/uniqueness.rb +0 -31
- data/lib/neo4j/rails/value.rb +0 -124
- data/lib/neo4j/rails/value_properties.rb +0 -29
- data/lib/neo4j/relationship.rb +0 -169
- data/lib/neo4j/relationship_mixin.rb +0 -4
- data/lib/neo4j/relationship_traverser.rb +0 -92
- data/lib/neo4j/to_java.rb +0 -31
- data/lib/neo4j/transaction.rb +0 -68
- data/lib/neo4j/type_converters.rb +0 -98
data/lib/neo4j/equal.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
module Neo4j
|
2
|
-
|
3
|
-
# == This mixin is used for both nodes and relationships to decide if two entities are equal or not.
|
4
|
-
#
|
5
|
-
module Equal
|
6
|
-
def equal?(o)
|
7
|
-
eql?(o)
|
8
|
-
end
|
9
|
-
|
10
|
-
def eql?(o)
|
11
|
-
return false unless o.respond_to?(:getId)
|
12
|
-
o.getId == getId
|
13
|
-
end
|
14
|
-
|
15
|
-
def ==(o)
|
16
|
-
eql?(o)
|
17
|
-
end
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
data/lib/neo4j/event_handler.rb
DELETED
@@ -1,116 +0,0 @@
|
|
1
|
-
module Neo4j
|
2
|
-
|
3
|
-
# == Handles Transactional Events
|
4
|
-
#
|
5
|
-
# You can use this to receive event before the transaction commits.
|
6
|
-
# The following events are supported:
|
7
|
-
# * <tt>on_neo4j_started</tt>
|
8
|
-
# * <tt>on_neo4j_shutdown</tt>
|
9
|
-
# * <tt>on_node_created</tt>
|
10
|
-
# * <tt>on_node_deleted</tt>
|
11
|
-
# * <tt>on_relationship_created</tt>
|
12
|
-
# * <tt>on_relationship_deleted</tt>
|
13
|
-
# * <tt>on_property_changed</tt>
|
14
|
-
# * <tt>on_rel_property_changed</tt>
|
15
|
-
#
|
16
|
-
# === Usage
|
17
|
-
#
|
18
|
-
# class MyListener
|
19
|
-
# def on_node_deleted(node, old_props, tx_data)
|
20
|
-
# end
|
21
|
-
# end
|
22
|
-
#
|
23
|
-
# # to add an listener without starting neo4j:
|
24
|
-
# Neo4j.unstarted_db.event_handler.add(MyListener.new)
|
25
|
-
#
|
26
|
-
# You only need to implement the methods that you need.
|
27
|
-
#
|
28
|
-
class EventHandler
|
29
|
-
include org.neo4j.graphdb.event.TransactionEventHandler
|
30
|
-
|
31
|
-
def initialize
|
32
|
-
@listeners = []
|
33
|
-
end
|
34
|
-
|
35
|
-
|
36
|
-
def after_commit(data, state)
|
37
|
-
end
|
38
|
-
|
39
|
-
def after_rollback(data, state)
|
40
|
-
end
|
41
|
-
|
42
|
-
def before_commit(data)
|
43
|
-
data.created_nodes.each{|node| node_created(node)}
|
44
|
-
data.assigned_node_properties.each { |tx_data| property_changed(tx_data.entity, tx_data.key, tx_data.previously_commited_value, tx_data.value) }
|
45
|
-
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) }
|
46
|
-
data.deleted_nodes.each { |node| node_deleted(node, deleted_properties_for(node,data), data)}
|
47
|
-
data.created_relationships.each {|rel| relationship_created(rel, data)}
|
48
|
-
data.deleted_relationships.each {|rel| relationship_deleted(rel, deleted_rel_properties_for(rel, data), data)}
|
49
|
-
data.assigned_relationship_properties.each { |tx_data| rel_property_changed(tx_data.entity, tx_data.key, tx_data.previously_commited_value, tx_data.value) }
|
50
|
-
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) }
|
51
|
-
end
|
52
|
-
|
53
|
-
def deleted_properties_for(node, data)
|
54
|
-
data.removed_node_properties.find_all{|tx_data| tx_data.entity == node}.inject({}) do |memo, tx_data|
|
55
|
-
memo[tx_data.key] = tx_data.previously_commited_value
|
56
|
-
memo
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def deleted_rel_properties_for(rel, data)
|
61
|
-
data.removed_relationship_properties.find_all{|tx_data| tx_data.entity == rel}.inject({}) do |memo, tx_data|
|
62
|
-
memo[tx_data.key] = tx_data.previously_commited_value
|
63
|
-
memo
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def add(listener)
|
68
|
-
@listeners << listener unless @listeners.include?(listener)
|
69
|
-
end
|
70
|
-
|
71
|
-
def remove(listener)
|
72
|
-
@listeners.delete(listener)
|
73
|
-
end
|
74
|
-
|
75
|
-
def remove_all
|
76
|
-
@listeners = []
|
77
|
-
end
|
78
|
-
|
79
|
-
def print
|
80
|
-
puts "Listeners #{@listeners.size}"
|
81
|
-
@listeners.each {|li| puts " Listener '#{li}'"}
|
82
|
-
end
|
83
|
-
|
84
|
-
def neo4j_started(db)
|
85
|
-
@listeners.each { |li| li.on_neo4j_started(db) if li.respond_to?(:on_neo4j_started) }
|
86
|
-
end
|
87
|
-
|
88
|
-
def neo4j_shutdown(db)
|
89
|
-
@listeners.each { |li| li.on_neo4j_shutdown(db) if li.respond_to?(:on_neo4j_shutdown) }
|
90
|
-
end
|
91
|
-
|
92
|
-
def node_created(node)
|
93
|
-
@listeners.each {|li| li.on_node_created(node) if li.respond_to?(:on_node_created)}
|
94
|
-
end
|
95
|
-
|
96
|
-
def node_deleted(node,old_properties, data)
|
97
|
-
@listeners.each {|li| li.on_node_deleted(node,old_properties, data) if li.respond_to?(:on_node_deleted)}
|
98
|
-
end
|
99
|
-
|
100
|
-
def relationship_created(relationship, tx_data)
|
101
|
-
@listeners.each {|li| li.on_relationship_created(relationship, tx_data) if li.respond_to?(:on_relationship_created)}
|
102
|
-
end
|
103
|
-
|
104
|
-
def relationship_deleted(relationship, old_props, data)
|
105
|
-
@listeners.each {|li| li.on_relationship_deleted(relationship, old_props, data) if li.respond_to?(:on_relationship_deleted)}
|
106
|
-
end
|
107
|
-
|
108
|
-
def property_changed(node, key, old_value, new_value)
|
109
|
-
@listeners.each {|li| li.on_property_changed(node, key, old_value, new_value) if li.respond_to?(:on_property_changed)}
|
110
|
-
end
|
111
|
-
|
112
|
-
def rel_property_changed(rel, key, old_value, new_value)
|
113
|
-
@listeners.each {|li| li.on_rel_property_changed(rel, key, old_value, new_value) if li.respond_to?(:on_rel_property_changed)}
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
@@ -1,62 +0,0 @@
|
|
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?, :delete_index_type, :rm_field_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
|
-
# node_indexer Contact # put index on the Contact class instead
|
38
|
-
# index :phone
|
39
|
-
# end
|
40
|
-
#
|
41
|
-
# # Find an contact with a phone number, this works since they share the same index
|
42
|
-
# Contact.find('phone: 12345').first #=> a phone object !
|
43
|
-
#
|
44
|
-
# ==== Returns
|
45
|
-
# The indexer that should be used to index the given class
|
46
|
-
def node_indexer(clazz)
|
47
|
-
indexer(clazz, :node)
|
48
|
-
end
|
49
|
-
|
50
|
-
# Sets which indexer should be used for the given relationship class
|
51
|
-
# Same as #node_indexer except that it indexes relationships instead of nodes.
|
52
|
-
#
|
53
|
-
def rel_indexer(clazz)
|
54
|
-
indexer(clazz, :rel)
|
55
|
-
end
|
56
|
-
|
57
|
-
def indexer(clazz, type) #:nodoc:
|
58
|
-
@_indexer = IndexerRegistry.create_for(self, clazz, type)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
data/lib/neo4j/index/index.rb
DELETED
@@ -1,33 +0,0 @@
|
|
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
|
data/lib/neo4j/index/indexer.rb
DELETED
@@ -1,312 +0,0 @@
|
|
1
|
-
module Neo4j
|
2
|
-
module Index
|
3
|
-
class Indexer
|
4
|
-
attr_reader :indexer_for, :field_types, :via_relationships
|
5
|
-
|
6
|
-
def initialize(clazz, type) #:nodoc:
|
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
|
-
|
17
|
-
# to enable subclass indexing to work properly, store a list of parent indexers and
|
18
|
-
# whenever an operation is performed on this one, perform it on all
|
19
|
-
@parent_indexers = []
|
20
|
-
end
|
21
|
-
|
22
|
-
def inherit_fields_from(parent_index) #:nodoc:
|
23
|
-
return unless parent_index
|
24
|
-
@field_types.reverse_merge!(parent_index.field_types) if parent_index.respond_to?(:field_types)
|
25
|
-
@via_relationships.reverse_merge!(parent_index.via_relationships) if parent_index.respond_to?(:via_relationships)
|
26
|
-
@parent_indexers << parent_index
|
27
|
-
end
|
28
|
-
|
29
|
-
def to_s
|
30
|
-
"Indexer @#{object_id} [index_for:#{@indexer_for}, field_types=#{@field_types.keys.join(', ')}, via=#{@via_relationships.inspect}]"
|
31
|
-
end
|
32
|
-
|
33
|
-
# Add an index on a field so that it will be automatically updated by neo4j transactional events.
|
34
|
-
#
|
35
|
-
# The index method takes an optional configuration hash which allows you to:
|
36
|
-
#
|
37
|
-
# === Add an index on an a property
|
38
|
-
#
|
39
|
-
# Example:
|
40
|
-
# class Person
|
41
|
-
# include Neo4j::NodeMixin
|
42
|
-
# index :name
|
43
|
-
# end
|
44
|
-
#
|
45
|
-
# When the property name is changed/deleted or the node created it will keep the lucene index in sync.
|
46
|
-
# You can then perform a lucene query like this: Person.find('name: andreas')
|
47
|
-
#'
|
48
|
-
# === Add index on other nodes.
|
49
|
-
#
|
50
|
-
# Example:
|
51
|
-
#
|
52
|
-
# class Person
|
53
|
-
# include Neo4j::NodeMixin
|
54
|
-
# has_n(:friends).to(Contact)
|
55
|
-
# has_n(:known_by).from(:friends)
|
56
|
-
# index :user_id, :via => :known_by
|
57
|
-
# end
|
58
|
-
#
|
59
|
-
# Notice that you *must* specify an incoming relationship with the via key, as shown above.
|
60
|
-
# In the example above an index <tt>user_id</tt> will be added to all Person nodes which has a <tt>friends</tt> relationship
|
61
|
-
# that person with that user_id. This allows you to do lucene queries on your friends properties.
|
62
|
-
#
|
63
|
-
# === Set the type value to index
|
64
|
-
# By default all values will be indexed as Strings.
|
65
|
-
# If you want for example to do a numerical range query you must tell Neo4j.rb to index it as a numeric value.
|
66
|
-
# You do that with the key <tt>type</tt> on the property.
|
67
|
-
#
|
68
|
-
# Example:
|
69
|
-
# class Person
|
70
|
-
# include Neo4j::NodeMixin
|
71
|
-
# property :weight, :type => Float
|
72
|
-
# index :weight
|
73
|
-
# end
|
74
|
-
#
|
75
|
-
# Supported values for <tt>:type</tt> is <tt>String</tt>, <tt>Float</tt>, <tt>Date</tt>, <tt>DateTime</tt> and <tt>Fixnum</tt>
|
76
|
-
#
|
77
|
-
# === For more information
|
78
|
-
# * See Neo4j::Index::LuceneQuery
|
79
|
-
# * See #find
|
80
|
-
#
|
81
|
-
def index(field, conf = {})
|
82
|
-
if conf[:via]
|
83
|
-
rel_dsl = @indexer_for._decl_rels[conf[:via]]
|
84
|
-
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
|
85
|
-
raise "Only incoming relationship are possible to define index on. Check class '#{@indexer_for}': index :#{field}, via=>:#{conf[:via]}" unless rel_dsl.incoming?
|
86
|
-
via_indexer = rel_dsl.target_class._indexer
|
87
|
-
|
88
|
-
field = field.to_s
|
89
|
-
@via_relationships[field] = rel_dsl
|
90
|
-
conf.delete :via # avoid endless recursion
|
91
|
-
via_indexer.index(field, conf)
|
92
|
-
else
|
93
|
-
# 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]
|
94
|
-
@field_types[field.to_s] = conf[:type] || :exact
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def remove_index_on_fields(node, props, tx_data) #:nodoc:
|
99
|
-
@field_types.keys.each { |field| rm_index(node, field, props[field]) if props[field] }
|
100
|
-
# remove all via indexed fields
|
101
|
-
@via_relationships.each_value do |dsl|
|
102
|
-
indexer = dsl.target_class._indexer
|
103
|
-
tx_data.deleted_relationships.each do |rel|
|
104
|
-
start_node = rel._start_node
|
105
|
-
next if node != rel._end_node
|
106
|
-
indexer.remove_index_on_fields(start_node, props, tx_data)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
def update_on_deleted_relationship(relationship) #:nodoc:
|
112
|
-
update_on_relationship(relationship, false)
|
113
|
-
end
|
114
|
-
|
115
|
-
def update_on_new_relationship(relationship) #:nodoc:
|
116
|
-
update_on_relationship(relationship, true)
|
117
|
-
end
|
118
|
-
|
119
|
-
def update_on_relationship(relationship, is_created) #:nodoc:
|
120
|
-
rel_type = relationship.rel_type
|
121
|
-
end_node = relationship._end_node
|
122
|
-
# find which via relationship match rel_type
|
123
|
-
@via_relationships.each_pair do |field, dsl|
|
124
|
-
# have we declared an index on this changed relationship ?
|
125
|
-
next unless dsl.rel_type == rel_type
|
126
|
-
|
127
|
-
# yes, so find the node and value we should update the index on
|
128
|
-
val = end_node[field]
|
129
|
-
start_node = relationship._start_node
|
130
|
-
|
131
|
-
# find the indexer to use
|
132
|
-
indexer = dsl.target_class._indexer
|
133
|
-
|
134
|
-
# is the relationship created or deleted ?
|
135
|
-
if is_created
|
136
|
-
indexer.update_index_on(start_node, field, nil, val)
|
137
|
-
else
|
138
|
-
indexer.update_index_on(start_node, field, val, nil)
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
def update_index_on(node, field, old_val, new_val) #:nodoc:
|
144
|
-
if @via_relationships.include?(field)
|
145
|
-
dsl = @via_relationships[field]
|
146
|
-
target_class = dsl.target_class
|
147
|
-
|
148
|
-
dsl._all_relationships(node).each do |rel|
|
149
|
-
other = rel._start_node
|
150
|
-
target_class._indexer.update_single_index_on(other, field, old_val, new_val)
|
151
|
-
end
|
152
|
-
end
|
153
|
-
update_single_index_on(node, field, old_val, new_val)
|
154
|
-
end
|
155
|
-
|
156
|
-
def update_single_index_on(node, field, old_val, new_val) #:nodoc:
|
157
|
-
if @field_types.include?(field)
|
158
|
-
rm_index(node, field, old_val) if old_val
|
159
|
-
add_index(node, field, new_val) if new_val
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
# Returns true if there is an index on the given field.
|
164
|
-
#
|
165
|
-
def index?(field)
|
166
|
-
@field_types.include?(field.to_s)
|
167
|
-
end
|
168
|
-
|
169
|
-
# Returns the type of index for the given field (e.g. :exact or :fulltext)
|
170
|
-
#
|
171
|
-
def index_type_for(field) #:nodoc:
|
172
|
-
return nil unless index?(field)
|
173
|
-
@field_types[field.to_s]
|
174
|
-
end
|
175
|
-
|
176
|
-
# Returns true if there is an index of the given type defined.
|
177
|
-
def index_type?(type)
|
178
|
-
@field_types.values.include?(type)
|
179
|
-
end
|
180
|
-
|
181
|
-
# Adds an index on the given entity
|
182
|
-
# This is normally not needed since you can instead declare an index which will automatically keep
|
183
|
-
# the lucene index in sync. See #index
|
184
|
-
#
|
185
|
-
def add_index(entity, field, value)
|
186
|
-
return false unless @field_types.has_key?(field)
|
187
|
-
|
188
|
-
# we might need to know what type the properties are when indexing and querying
|
189
|
-
@decl_props ||= @indexer_for.respond_to?(:_decl_props) && @indexer_for._decl_props
|
190
|
-
|
191
|
-
type = @decl_props && @decl_props[field.to_sym] && @decl_props[field.to_sym][:type]
|
192
|
-
if type
|
193
|
-
value = if String != type
|
194
|
-
org.neo4j.index.impl.lucene.ValueContext.new(value).indexNumeric
|
195
|
-
else
|
196
|
-
org.neo4j.index.impl.lucene.ValueContext.new(value)
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
index_for_field(field.to_s).add(entity, field, value)
|
201
|
-
@parent_indexers.each { |i| i.add_index(entity, field, value) }
|
202
|
-
end
|
203
|
-
|
204
|
-
# Removes an index on the given entity
|
205
|
-
# This is normally not needed since you can instead declare an index which will automatically keep
|
206
|
-
# the lucene index in sync. See #index
|
207
|
-
#
|
208
|
-
def rm_index(entity, field, value)
|
209
|
-
return false unless @field_types.has_key?(field)
|
210
|
-
index_for_field(field).remove(entity, field, value)
|
211
|
-
@parent_indexers.each { |i| i.rm_index(entity, field, value) }
|
212
|
-
end
|
213
|
-
|
214
|
-
# Performs a Lucene Query.
|
215
|
-
#
|
216
|
-
# In order to use this you have to declare an index on the fields first, see #index.
|
217
|
-
# Notice that you should close the lucene query after the query has been executed.
|
218
|
-
# You can do that either by provide an block or calling the Neo4j::Index::LuceneQuery#close
|
219
|
-
# method. When performing queries from Ruby on Rails you do not need this since it will be automatically closed
|
220
|
-
# (by Rack).
|
221
|
-
#
|
222
|
-
# === Example, with a block
|
223
|
-
#
|
224
|
-
# Person.find('name: kalle') {|query| puts "#{[*query].join(', )"}
|
225
|
-
#
|
226
|
-
# ==== Example
|
227
|
-
#
|
228
|
-
# query = Person.find('name: kalle')
|
229
|
-
# puts "First item #{query.first}"
|
230
|
-
# query.close
|
231
|
-
#
|
232
|
-
# === Return Value
|
233
|
-
# It will return a Neo4j::Index::LuceneQuery object
|
234
|
-
#
|
235
|
-
#
|
236
|
-
def find(query, params = {})
|
237
|
-
# we might need to know what type the properties are when indexing and querying
|
238
|
-
@decl_props ||= @indexer_for.respond_to?(:_decl_props) && @indexer_for._decl_props
|
239
|
-
|
240
|
-
index = index_for_type(params[:type] || :exact)
|
241
|
-
query = (params[:wrapped].nil? || params[:wrapped]) ? LuceneQuery.new(index, @decl_props, query) : index.query(query)
|
242
|
-
|
243
|
-
if block_given?
|
244
|
-
begin
|
245
|
-
ret = yield query
|
246
|
-
ensure
|
247
|
-
query.close
|
248
|
-
end
|
249
|
-
ret
|
250
|
-
else
|
251
|
-
query
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
# delete the index, if no type is provided clear all types of indexes
|
256
|
-
def delete_index_type(type=nil)
|
257
|
-
if type
|
258
|
-
#raise "can't clear index of type '#{type}' since it does not exist ([#{@field_types.values.join(',')}] exists)" unless index_type?(type)
|
259
|
-
@indexes[type] && @indexes[type].delete
|
260
|
-
@indexes[type] = nil
|
261
|
-
else
|
262
|
-
@indexes.each_value { |index| index.delete }
|
263
|
-
@indexes.clear
|
264
|
-
end
|
265
|
-
end
|
266
|
-
|
267
|
-
def on_neo4j_shutdown #:nodoc:
|
268
|
-
# Since we might start the database again we must make sure that we don't keep any references to
|
269
|
-
# an old lucene index in memory.
|
270
|
-
@indexes.clear
|
271
|
-
end
|
272
|
-
|
273
|
-
# Removes the cached lucene index, can be useful for some RSpecs which needs to restart the Neo4j.
|
274
|
-
#
|
275
|
-
def rm_field_type(type=nil)
|
276
|
-
if type
|
277
|
-
@field_types.delete_if { |k, v| v == type }
|
278
|
-
else
|
279
|
-
@field_types.clear
|
280
|
-
end
|
281
|
-
end
|
282
|
-
|
283
|
-
def index_for_field(field) #:nodoc:
|
284
|
-
type = @field_types[field]
|
285
|
-
@indexes[type] ||= create_index_with(type)
|
286
|
-
end
|
287
|
-
|
288
|
-
def index_for_type(type) #:nodoc:
|
289
|
-
@indexes[type] ||= create_index_with(type)
|
290
|
-
end
|
291
|
-
|
292
|
-
def lucene_config(type) #:nodoc:
|
293
|
-
conf = Neo4j::Config[:lucene][type.to_sym]
|
294
|
-
raise "unknown lucene type #{type}" unless conf
|
295
|
-
conf
|
296
|
-
end
|
297
|
-
|
298
|
-
def create_index_with(type) #:nodoc:
|
299
|
-
db=Neo4j.started_db
|
300
|
-
index_config = lucene_config(type)
|
301
|
-
if @type == :node
|
302
|
-
db.lucene.for_nodes("#{@indexer_for}-#{type}", index_config)
|
303
|
-
else
|
304
|
-
db.lucene.for_relationships("#{@indexer_for}-#{type}", index_config)
|
305
|
-
end
|
306
|
-
end
|
307
|
-
|
308
|
-
end
|
309
|
-
|
310
|
-
end
|
311
|
-
|
312
|
-
end
|