neo4j 1.0.0.beta.17 → 1.0.0.beta.18
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 +2 -2
- data/README.rdoc +2 -2
- data/lib/generators/neo4j.rb +65 -0
- data/lib/generators/neo4j/model/model_generator.rb +39 -0
- data/lib/generators/neo4j/model/templates/model.rb +7 -0
- data/lib/neo4j.rb +2 -2
- data/lib/neo4j/config.rb +14 -12
- data/lib/neo4j/database.rb +1 -1
- data/lib/neo4j/equal.rb +3 -0
- data/lib/neo4j/event_handler.rb +25 -14
- data/lib/neo4j/index/class_methods.rb +3 -2
- data/lib/neo4j/index/indexer.rb +121 -21
- data/lib/neo4j/index/lucene_query.rb +156 -0
- data/lib/neo4j/load.rb +3 -2
- data/lib/neo4j/mapping/class_methods/property.rb +16 -0
- data/lib/neo4j/mapping/class_methods/relationship.rb +3 -1
- data/lib/neo4j/mapping/class_methods/root.rb +3 -0
- data/lib/neo4j/mapping/class_methods/rule.rb +141 -66
- data/lib/neo4j/mapping/decl_relationship_dsl.rb +8 -8
- data/lib/neo4j/mapping/has_n.rb +11 -1
- data/lib/neo4j/mapping/node_mixin.rb +20 -0
- data/lib/neo4j/neo4j.rb +24 -5
- data/lib/neo4j/node.rb +1 -1
- data/lib/neo4j/property.rb +1 -1
- data/lib/neo4j/rails/model.rb +40 -36
- data/lib/neo4j/rails/properties.rb +29 -0
- data/lib/neo4j/rails/value.rb +8 -29
- data/lib/neo4j/transaction.rb +0 -1
- data/lib/neo4j/version.rb +1 -1
- metadata +8 -5
- data/lib/neo4j/index/wrapped_query.rb +0 -59
- data/lib/neo4j/mapping/class_methods/index.rb +0 -17
data/Gemfile
CHANGED
@@ -6,11 +6,11 @@ group 'test' do
|
|
6
6
|
gem "rake", ">= 0.8.7"
|
7
7
|
gem "rdoc", ">= 2.5.10"
|
8
8
|
gem "horo", ">= 1.0.2"
|
9
|
-
gem "rspec-apigen", ">= 0.0.4"
|
10
9
|
gem "rspec", ">= 2.0.0"
|
11
10
|
gem "rspec-rails-matchers", ">= 0.2.1"
|
11
|
+
gem "test-unit"
|
12
12
|
end
|
13
13
|
|
14
14
|
gem 'ruby-debug-base19' if RUBY_VERSION.include? "1.9"
|
15
15
|
gem 'ruby-debug-base' if RUBY_VERSION.include? "1.8"
|
16
|
-
gem "ruby-debug-ide"
|
16
|
+
gem "ruby-debug-ide"
|
data/README.rdoc
CHANGED
@@ -15,13 +15,13 @@ Here are some of the major benefits of Neo4j.rb
|
|
15
15
|
|
16
16
|
* Domain Modeling - use the language of a graph (nodes/relationship/properties) to express your domain !
|
17
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.
|
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
19
|
* {Performance}[http://www.oscon.com/oscon2009/public/schedule/detail/8364]
|
20
20
|
* Embedded Database - no database tier, easier to install, test, deploy and configure. It is run in the same process as your application.
|
21
21
|
* Express Queries as Traversals
|
22
22
|
* Fast deep traversal instead of slow SQL queries that span many table joins.
|
23
23
|
* Very natural to express graph related problem with traversals (recommendation engine, find shortest parth etc..)
|
24
|
-
* Seamless integration with Ruby on Rails.
|
24
|
+
* Seamless integration with Ruby on \Rails.
|
25
25
|
* ACID Transaction with rollbacks support.
|
26
26
|
|
27
27
|
=== Documentation
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'rails/generators/named_base'
|
2
|
+
require 'rails/generators/active_model'
|
3
|
+
|
4
|
+
module Neo4j
|
5
|
+
module Generators
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Neo4j::Generators::Base < Rails::Generators::NamedBase #:nodoc:
|
10
|
+
def self.source_root
|
11
|
+
@_neo4j_source_root ||= File.expand_path(File.join(File.dirname(__FILE__),
|
12
|
+
'neo4j', generator_name, 'templates'))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Neo4j::Generators::ActiveModel < Rails::Generators::ActiveModel #:nodoc:
|
17
|
+
def self.all(klass)
|
18
|
+
"#{klass}.all"
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.find(klass, params=nil)
|
22
|
+
"#{klass}.find(#{params})"
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.build(klass, params=nil)
|
26
|
+
if params
|
27
|
+
"#{klass}.new(#{params})"
|
28
|
+
else
|
29
|
+
"#{klass}.new"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def save
|
34
|
+
"#{name}.save"
|
35
|
+
end
|
36
|
+
|
37
|
+
def update_attributes(params=nil)
|
38
|
+
"#{name}.update_attributes(#{params})"
|
39
|
+
end
|
40
|
+
|
41
|
+
def errors
|
42
|
+
"#{name}.errors"
|
43
|
+
end
|
44
|
+
|
45
|
+
def destroy
|
46
|
+
"#{name}.destroy"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
module Rails
|
51
|
+
module Generators
|
52
|
+
class GeneratedAttribute #:nodoc:
|
53
|
+
def type_class
|
54
|
+
case type.to_s.downcase
|
55
|
+
when 'datetime' then 'DateTime'
|
56
|
+
when 'date' then 'Date'
|
57
|
+
when 'text' then 'String'
|
58
|
+
when 'integer', 'number', 'fixnum' then 'Fixnum'
|
59
|
+
when 'float' then 'Float'
|
60
|
+
else 'String'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'neo4j.rb')
|
2
|
+
|
3
|
+
class Neo4j::Generators::ModelGenerator < Neo4j::Generators::Base
|
4
|
+
argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
|
5
|
+
|
6
|
+
check_class_collision
|
7
|
+
|
8
|
+
class_option :timestamps, :type => :boolean
|
9
|
+
class_option :parent, :type => :string, :desc => "The parent class for the generated model"
|
10
|
+
|
11
|
+
def create_model_file
|
12
|
+
template "model.rb", File.join('app/models', "#{singular_name}.rb")
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
def migration?
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
def timestamps?
|
21
|
+
options[:timestamps]
|
22
|
+
end
|
23
|
+
|
24
|
+
def parent?
|
25
|
+
options[:parent]
|
26
|
+
end
|
27
|
+
|
28
|
+
def timestamp_statements
|
29
|
+
%q{
|
30
|
+
property :created_at, DateTime
|
31
|
+
# property :created_on, Date
|
32
|
+
|
33
|
+
property :updated_at, DateTime
|
34
|
+
# property :updated_on, Date
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
hook_for :test_framework
|
39
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
class <%= class_name %> < <%= parent? ? options[:parent].classify : "Neo4j::Rails::Model" %>
|
2
|
+
<% attributes.each do |attribute| -%>
|
3
|
+
property :<%= attribute.name %><%= ", :type => #{attribute.type_class}" unless attribute.type_class == "String" %>
|
4
|
+
<% end -%>
|
5
|
+
|
6
|
+
<%= timestamp_statements if timestamps? -%>
|
7
|
+
end
|
data/lib/neo4j.rb
CHANGED
@@ -22,7 +22,7 @@ require 'neo4j/index/index'
|
|
22
22
|
require 'neo4j/index/class_methods'
|
23
23
|
require 'neo4j/index/index_registry'
|
24
24
|
require 'neo4j/index/indexer'
|
25
|
-
require 'neo4j/index/
|
25
|
+
require 'neo4j/index/lucene_query'
|
26
26
|
require 'neo4j/relationship_traverser'
|
27
27
|
require 'neo4j/node_traverser'
|
28
28
|
require 'neo4j/property'
|
@@ -36,7 +36,6 @@ require 'neo4j/mapping/class_methods/init_node'
|
|
36
36
|
require 'neo4j/mapping/class_methods/init_rel'
|
37
37
|
require 'neo4j/mapping/class_methods/root'
|
38
38
|
require 'neo4j/mapping/class_methods/property'
|
39
|
-
require 'neo4j/mapping/class_methods/index'
|
40
39
|
require 'neo4j/mapping/class_methods/relationship'
|
41
40
|
require 'neo4j/mapping/decl_relationship_dsl'
|
42
41
|
require 'neo4j/mapping/has_n'
|
@@ -54,6 +53,7 @@ require 'neo4j/rails/transaction'
|
|
54
53
|
require 'neo4j/rails/railtie'
|
55
54
|
require 'neo4j/rails/validations/uniqueness'
|
56
55
|
require 'neo4j/rails/model'
|
56
|
+
require 'neo4j/rails/properties'
|
57
57
|
require 'neo4j/rails/value'
|
58
58
|
require 'neo4j/rails/lucene_connection_closer'
|
59
59
|
|
data/lib/neo4j/config.rb
CHANGED
@@ -2,9 +2,12 @@
|
|
2
2
|
module Neo4j
|
3
3
|
|
4
4
|
|
5
|
-
# Keeps configuration for neo4j.
|
5
|
+
# == Keeps configuration for neo4j.
|
6
6
|
#
|
7
|
-
# Neo4j::Config[:storage_path]
|
7
|
+
# The most important configuration is <tt>Neo4j::Config[:storage_path]</tt> which is used to
|
8
|
+
# locate where the neo4j database is stored on the filesystem.
|
9
|
+
# If this directory is empty then a new database will be created, otherwise it will use the
|
10
|
+
# database from that directory.
|
8
11
|
#
|
9
12
|
class Config
|
10
13
|
# This code is copied from merb-core/config.rb.
|
@@ -45,8 +48,8 @@ module Neo4j
|
|
45
48
|
# Set the value of a config entry.
|
46
49
|
#
|
47
50
|
# ==== Parameters
|
48
|
-
# key
|
49
|
-
# val
|
51
|
+
# key:: The key to set the parameter for.
|
52
|
+
# val:: The value of the parameter.
|
50
53
|
#
|
51
54
|
def []=(key, val)
|
52
55
|
(@configuration ||= setup)[key] = val
|
@@ -56,7 +59,7 @@ module Neo4j
|
|
56
59
|
# Gets the the value of a config entry
|
57
60
|
#
|
58
61
|
# ==== Parameters
|
59
|
-
# key
|
62
|
+
# key:: The key of the config entry value we want
|
60
63
|
#
|
61
64
|
def [](key)
|
62
65
|
(@configuration ||= setup)[key]
|
@@ -69,7 +72,7 @@ module Neo4j
|
|
69
72
|
# key<Object>:: The key of the parameter to delete.
|
70
73
|
#
|
71
74
|
# ==== Returns
|
72
|
-
#
|
75
|
+
# The value of the removed entry.
|
73
76
|
#
|
74
77
|
def delete(key)
|
75
78
|
@configuration.delete(key)
|
@@ -90,12 +93,11 @@ module Neo4j
|
|
90
93
|
# Retrieve the value of a config entry, returning the provided default if the key is not present
|
91
94
|
#
|
92
95
|
# ==== Parameters
|
93
|
-
# key
|
94
|
-
# default
|
95
|
-
# The default value to return if the parameter is not set.
|
96
|
+
# key:: The key to retrieve the parameter for.
|
97
|
+
# default::The default value to return if the parameter is not set.
|
96
98
|
#
|
97
99
|
# ==== Returns
|
98
|
-
#
|
100
|
+
# The value of the configuration parameter or the default.
|
99
101
|
#
|
100
102
|
def fetch(key, default)
|
101
103
|
@configuration.fetch(key, default)
|
@@ -116,7 +118,7 @@ module Neo4j
|
|
116
118
|
# Returns the configuration as a hash.
|
117
119
|
#
|
118
120
|
# ==== Returns
|
119
|
-
#
|
121
|
+
# The config as a hash.
|
120
122
|
#
|
121
123
|
def to_hash
|
122
124
|
@configuration
|
@@ -125,7 +127,7 @@ module Neo4j
|
|
125
127
|
# Returns the config as YAML.
|
126
128
|
#
|
127
129
|
# ==== Returns
|
128
|
-
#
|
130
|
+
# The config as YAML.
|
129
131
|
#
|
130
132
|
def to_yaml
|
131
133
|
require "yaml"
|
data/lib/neo4j/database.rb
CHANGED
data/lib/neo4j/equal.rb
CHANGED
data/lib/neo4j/event_handler.rb
CHANGED
@@ -1,6 +1,30 @@
|
|
1
1
|
module Neo4j
|
2
2
|
|
3
|
-
# Handles
|
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
|
+
#
|
4
28
|
class EventHandler
|
5
29
|
include org.neo4j.graphdb.event.TransactionEventHandler
|
6
30
|
|
@@ -88,18 +112,5 @@ module Neo4j
|
|
88
112
|
def rel_property_changed(rel, key, old_value, new_value)
|
89
113
|
@listeners.each {|li| li.on_rel_property_changed(rel, key, old_value, new_value) if li.respond_to?(:on_rel_property_changed)}
|
90
114
|
end
|
91
|
-
|
92
|
-
# TODO ?
|
93
|
-
def tx_finished(tx)
|
94
|
-
@listeners.each {|li| li.on_tx_finished(tx) if li.respond_to?(:on_tx_finished)}
|
95
|
-
end
|
96
|
-
|
97
|
-
def neo_started(neo_instance)
|
98
|
-
@listeners.each {|li| li.on_neo_started(neo_instance) if li.respond_to?(:on_neo_started)}
|
99
|
-
end
|
100
|
-
|
101
|
-
def neo_stopped(neo_instance)
|
102
|
-
@listeners.each {|li| li.on_neo_stopped(neo_instance) if li.respond_to?(:on_neo_stopped)}
|
103
|
-
end
|
104
115
|
end
|
105
116
|
end
|
@@ -34,11 +34,12 @@ module Neo4j
|
|
34
34
|
# class Phone
|
35
35
|
# include Neo4j::NodeMixin
|
36
36
|
# property :phone
|
37
|
-
#
|
37
|
+
# node_indexer Contact # put index on the Contact class instead
|
38
|
+
# index :phone
|
38
39
|
# end
|
39
40
|
#
|
40
41
|
# # Find an contact with a phone number, this works since they share the same index
|
41
|
-
# Contact.find('phone: 12345
|
42
|
+
# Contact.find('phone: 12345').first #=> a phone object !
|
42
43
|
#
|
43
44
|
# ==== Returns
|
44
45
|
# The indexer that should be used to index the given class
|
data/lib/neo4j/index/indexer.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
module Neo4j
|
2
2
|
module Index
|
3
|
-
class Indexer
|
3
|
+
class Indexer
|
4
4
|
attr_reader :indexer_for, :field_types, :via_relationships
|
5
5
|
|
6
|
-
def initialize(clazz, type)
|
6
|
+
def initialize(clazz, type) #:nodoc:
|
7
7
|
# part of the unique name of the index
|
8
8
|
@indexer_for = clazz
|
9
9
|
|
@@ -19,7 +19,7 @@ module Neo4j
|
|
19
19
|
@parent_indexers = []
|
20
20
|
end
|
21
21
|
|
22
|
-
def inherit_fields_from(parent_index)
|
22
|
+
def inherit_fields_from(parent_index) #:nodoc:
|
23
23
|
return unless parent_index
|
24
24
|
@field_types.reverse_merge!(parent_index.field_types) if parent_index.respond_to?(:field_types)
|
25
25
|
@via_relationships.reverse_merge!(parent_index.via_relationships) if parent_index.respond_to?(:via_relationships)
|
@@ -30,7 +30,53 @@ module Neo4j
|
|
30
30
|
"Indexer @#{object_id} [index_for:#{@indexer_for}, field_types=#{@field_types.keys.join(', ')}, via=#{@via_relationships.inspect}]"
|
31
31
|
end
|
32
32
|
|
33
|
-
#
|
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>
|
67
|
+
#
|
68
|
+
# Example:
|
69
|
+
# class Person
|
70
|
+
# include Neo4j::NodeMixin
|
71
|
+
# index :weight, :type => Float
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# Supported values for <tt>:type</tt> is <tt>String</tt>, <tt>Float</tt> and <tt>Fixnum</tt>
|
75
|
+
#
|
76
|
+
# === For more information
|
77
|
+
# * See Neo4j::Index::LuceneQuery
|
78
|
+
# * See #find
|
79
|
+
#
|
34
80
|
def index(field, conf = {})
|
35
81
|
if conf[:via]
|
36
82
|
rel_dsl = @indexer_for._decl_rels[conf[:via]]
|
@@ -48,7 +94,7 @@ module Neo4j
|
|
48
94
|
end
|
49
95
|
end
|
50
96
|
|
51
|
-
def remove_index_on_fields(node, props, tx_data)
|
97
|
+
def remove_index_on_fields(node, props, tx_data) #:nodoc:
|
52
98
|
@field_types.keys.each { |field| rm_index(node, field, props[field]) if props[field] }
|
53
99
|
# remove all via indexed fields
|
54
100
|
@via_relationships.each_value do |dsl|
|
@@ -61,15 +107,15 @@ module Neo4j
|
|
61
107
|
end
|
62
108
|
end
|
63
109
|
|
64
|
-
def update_on_deleted_relationship(relationship)
|
110
|
+
def update_on_deleted_relationship(relationship) #:nodoc:
|
65
111
|
update_on_relationship(relationship, false)
|
66
112
|
end
|
67
113
|
|
68
|
-
def update_on_new_relationship(relationship)
|
114
|
+
def update_on_new_relationship(relationship) #:nodoc:
|
69
115
|
update_on_relationship(relationship, true)
|
70
116
|
end
|
71
117
|
|
72
|
-
def update_on_relationship(relationship, is_created)
|
118
|
+
def update_on_relationship(relationship, is_created) #:nodoc:
|
73
119
|
rel_type = relationship.rel_type
|
74
120
|
end_node = relationship._end_node
|
75
121
|
# find which via relationship match rel_type
|
@@ -93,7 +139,7 @@ module Neo4j
|
|
93
139
|
end
|
94
140
|
end
|
95
141
|
|
96
|
-
def update_index_on(node, field, old_val, new_val)
|
142
|
+
def update_index_on(node, field, old_val, new_val) #:nodoc:
|
97
143
|
if @via_relationships.include?(field)
|
98
144
|
dsl = @via_relationships[field]
|
99
145
|
to_class = dsl.to_class
|
@@ -106,42 +152,94 @@ module Neo4j
|
|
106
152
|
update_single_index_on(node, field, old_val, new_val)
|
107
153
|
end
|
108
154
|
|
109
|
-
def update_single_index_on(node, field, old_val, new_val)
|
155
|
+
def update_single_index_on(node, field, old_val, new_val) #:nodoc:
|
110
156
|
if @field_types.include?(field)
|
111
157
|
rm_index(node, field, old_val) if old_val
|
112
158
|
add_index(node, field, new_val) if new_val
|
113
159
|
end
|
114
160
|
end
|
115
161
|
|
162
|
+
# Returns true if there is an index on the given field.
|
163
|
+
#
|
116
164
|
def index?(field)
|
117
165
|
@field_types.include?(field.to_s)
|
118
166
|
end
|
119
167
|
|
120
|
-
|
168
|
+
# Returns the type of index for the given field (e.g. :exact or :fulltext)
|
169
|
+
#
|
170
|
+
def index_type_for(field) #:nodoc:
|
121
171
|
return nil unless index?(field)
|
122
172
|
@field_types[field.to_s]
|
123
173
|
end
|
124
174
|
|
175
|
+
# Returns true if there is an index of the given type defined.
|
125
176
|
def index_type?(type)
|
126
177
|
@field_types.values.include?(type)
|
127
178
|
end
|
128
179
|
|
180
|
+
# Adds an index on the given entity
|
181
|
+
# This is normally not needed since you can instead declare an index which will automatically keep
|
182
|
+
# the lucene index in sync. See #index
|
183
|
+
#
|
129
184
|
def add_index(entity, field, value)
|
130
185
|
return false unless @field_types.has_key?(field)
|
186
|
+
|
187
|
+
# we might need to know what type the properties are when indexing and querying
|
188
|
+
@decl_props ||= @indexer_for.respond_to?(:_decl_props) && @indexer_for._decl_props
|
189
|
+
|
190
|
+
type = @decl_props && @decl_props[field.to_sym] && @decl_props[field.to_sym][:type]
|
191
|
+
if type
|
192
|
+
raise "Can't index #{type} with value #{value} since it is not a #{type}" unless type === value
|
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
|
+
|
199
|
+
end
|
200
|
+
|
131
201
|
index_for_field(field.to_s).add(entity, field, value)
|
132
202
|
@parent_indexers.each { |i| i.add_index(entity, field, value) }
|
133
203
|
end
|
134
204
|
|
205
|
+
# Removes an index on the given entity
|
206
|
+
# This is normally not needed since you can instead declare an index which will automatically keep
|
207
|
+
# the lucene index in sync. See #index
|
208
|
+
#
|
135
209
|
def rm_index(entity, field, value)
|
136
210
|
return false unless @field_types.has_key?(field)
|
137
211
|
index_for_field(field).remove(entity, field, value)
|
138
212
|
@parent_indexers.each { |i| i.rm_index(entity, field, value) }
|
139
213
|
end
|
140
214
|
|
215
|
+
# Performs a Lucene Query.
|
216
|
+
#
|
217
|
+
# In order to use this you have to declare an index on the fields first, see #index.
|
218
|
+
# Notice that you should close the lucene query after the query has been executed.
|
219
|
+
# You can do that either by provide an block or calling the Neo4j::Index::LuceneQuery#close
|
220
|
+
# method. When performing queries from Ruby on Rails you do not need this since it will be automatically closed
|
221
|
+
# (by Rack).
|
222
|
+
#
|
223
|
+
# === Example, with a block
|
224
|
+
#
|
225
|
+
# Person.find('name: kalle') {|query| puts "#{[*query].join(', )"}
|
226
|
+
#
|
227
|
+
# ==== Example
|
228
|
+
#
|
229
|
+
# query = Person.find('name: kalle')
|
230
|
+
# puts "First item #{query.first}"
|
231
|
+
# query.close
|
232
|
+
#
|
233
|
+
# === Return Value
|
234
|
+
# It will return a Neo4j::Index::LuceneQuery object
|
235
|
+
#
|
236
|
+
#
|
141
237
|
def find(query, params = {})
|
142
|
-
|
143
|
-
|
144
|
-
|
238
|
+
# we might need to know what type the properties are when indexing and querying
|
239
|
+
@decl_props ||= @indexer_for.respond_to?(:_decl_props) && @indexer_for._decl_props
|
240
|
+
|
241
|
+
index = index_for_type(params[:type] || :exact)
|
242
|
+
query = (params[:wrapped].nil? || params[:wrapped]) ? LuceneQuery.new(index, @decl_props, query) : index.query(query)
|
145
243
|
|
146
244
|
if block_given?
|
147
245
|
begin
|
@@ -155,7 +253,7 @@ module Neo4j
|
|
155
253
|
end
|
156
254
|
end
|
157
255
|
|
158
|
-
#
|
256
|
+
# delete the index, if no type is provided clear all types of indexes
|
159
257
|
def delete_index_type(type=nil)
|
160
258
|
if type
|
161
259
|
#raise "can't clear index of type '#{type}' since it does not exist ([#{@field_types.values.join(',')}] exists)" unless index_type?(type)
|
@@ -167,12 +265,14 @@ module Neo4j
|
|
167
265
|
end
|
168
266
|
end
|
169
267
|
|
170
|
-
def on_neo4j_shutdown
|
268
|
+
def on_neo4j_shutdown #:nodoc:
|
171
269
|
# Since we might start the database again we must make sure that we don't keep any references to
|
172
|
-
# an old lucene index
|
270
|
+
# an old lucene index in memory.
|
173
271
|
@indexes.clear
|
174
272
|
end
|
175
273
|
|
274
|
+
# Removes the cached lucene index, can be useful for some RSpecs which needs to restart the Neo4j.
|
275
|
+
#
|
176
276
|
def rm_field_type(type=nil)
|
177
277
|
if type
|
178
278
|
@field_types.delete_if { |k, v| v == type }
|
@@ -181,22 +281,22 @@ module Neo4j
|
|
181
281
|
end
|
182
282
|
end
|
183
283
|
|
184
|
-
def index_for_field(field)
|
284
|
+
def index_for_field(field) #:nodoc:
|
185
285
|
type = @field_types[field]
|
186
286
|
@indexes[type] ||= create_index_with(type)
|
187
287
|
end
|
188
288
|
|
189
|
-
def index_for_type(type)
|
289
|
+
def index_for_type(type) #:nodoc:
|
190
290
|
@indexes[type] ||= create_index_with(type)
|
191
291
|
end
|
192
292
|
|
193
|
-
def lucene_config(type)
|
293
|
+
def lucene_config(type) #:nodoc:
|
194
294
|
conf = Neo4j::Config[:lucene][type.to_sym]
|
195
295
|
raise "unknown lucene type #{type}" unless conf
|
196
296
|
conf
|
197
297
|
end
|
198
298
|
|
199
|
-
def create_index_with(type)
|
299
|
+
def create_index_with(type) #:nodoc:
|
200
300
|
db=Neo4j.started_db
|
201
301
|
index_config = lucene_config(type)
|
202
302
|
if @type == :node
|