neo4j-core 2.0.0.alpha.1-java → 2.0.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +2 -2
- data/README.rdoc +161 -13
- data/config/neo4j/config.yml +1 -1
- data/lib/db/active_tx_log +1 -0
- data/lib/db/index/lucene-store.db +0 -0
- data/lib/db/index/lucene.log.active +0 -0
- data/lib/db/messages.log +2299 -0
- data/lib/db/neostore +0 -0
- data/lib/db/neostore.id +0 -0
- data/lib/db/neostore.nodestore.db +0 -0
- data/lib/db/neostore.nodestore.db.id +0 -0
- data/lib/db/neostore.propertystore.db +0 -0
- data/lib/db/neostore.propertystore.db.arrays +0 -0
- data/lib/db/neostore.propertystore.db.arrays.id +0 -0
- data/lib/db/neostore.propertystore.db.id +0 -0
- data/lib/db/neostore.propertystore.db.index +0 -0
- data/lib/db/neostore.propertystore.db.index.id +0 -0
- data/lib/db/neostore.propertystore.db.index.keys +0 -0
- data/lib/db/neostore.propertystore.db.index.keys.id +0 -0
- data/lib/db/neostore.propertystore.db.strings +0 -0
- data/lib/db/neostore.propertystore.db.strings.id +0 -0
- data/lib/db/neostore.relationshipstore.db +0 -0
- data/lib/db/neostore.relationshipstore.db.id +0 -0
- data/lib/db/neostore.relationshiptypestore.db +0 -0
- data/lib/db/neostore.relationshiptypestore.db.id +0 -0
- data/lib/db/neostore.relationshiptypestore.db.names +0 -0
- data/lib/db/neostore.relationshiptypestore.db.names.id +0 -0
- data/lib/db/nioneo_logical.log.active +0 -0
- data/lib/db/tm_tx_log.1 +0 -0
- data/lib/neo4j-core.rb +20 -3
- data/lib/neo4j-core/cypher/cypher.rb +1033 -0
- data/lib/neo4j-core/cypher/result_wrapper.rb +48 -0
- data/lib/neo4j-core/database.rb +4 -5
- data/lib/neo4j-core/event_handler.rb +1 -1
- data/lib/neo4j-core/hash_with_indifferent_access.rb +165 -0
- data/lib/neo4j-core/index/class_methods.rb +27 -41
- data/lib/neo4j-core/index/index.rb +3 -4
- data/lib/neo4j-core/index/index_config.rb +30 -23
- data/lib/neo4j-core/index/indexer.rb +65 -53
- data/lib/neo4j-core/index/indexer_registry.rb +2 -2
- data/lib/neo4j-core/index/lucene_query.rb +53 -42
- data/lib/neo4j-core/index/unique_factory.rb +54 -0
- data/lib/neo4j-core/node/class_methods.rb +4 -4
- data/lib/neo4j-core/node/node.rb +1 -8
- data/lib/neo4j-core/property/java.rb +59 -0
- data/lib/neo4j-core/property/property.rb +1 -3
- data/lib/neo4j-core/relationship/relationship.rb +8 -10
- data/lib/neo4j-core/rels/rels.rb +9 -4
- data/lib/neo4j-core/rels/traverser.rb +13 -27
- data/lib/neo4j-core/traversal/prune_evaluator.rb +2 -2
- data/lib/neo4j-core/traversal/traverser.rb +122 -27
- data/lib/neo4j-core/version.rb +1 -1
- data/lib/neo4j-core/wrapper/class_methods.rb +22 -0
- data/lib/neo4j-core/wrapper/wrapper.rb +20 -0
- data/lib/neo4j/algo.rb +300 -0
- data/lib/neo4j/config.rb +3 -6
- data/lib/neo4j/cypher.rb +180 -0
- data/lib/neo4j/neo4j.rb +51 -23
- data/lib/neo4j/node.rb +27 -0
- data/lib/neo4j/relationship.rb +25 -0
- data/lib/test.rb~ +27 -0
- data/neo4j-core.gemspec +2 -2
- metadata +44 -11
- data/lib/neo4j-core/type_converters/type_converters.rb +0 -287
- data/lib/neo4j-core/version.rb~ +0 -3
- data/lib/test.rb +0 -27
@@ -17,55 +17,21 @@ module Neo4j
|
|
17
17
|
|
18
18
|
|
19
19
|
def to_s
|
20
|
-
"Indexer @#{object_id} index on: [#{@config.fields.map{|f| @config.numeric?(f)? "#{f} (numeric)" : f}.join(', ')}]"
|
20
|
+
"Indexer @#{object_id} index on: [#{@config.fields.map { |f| @config.numeric?(f) ? "#{f} (numeric)" : f }.join(', ')}]"
|
21
21
|
end
|
22
22
|
|
23
23
|
# Add an index on a field so that it will be automatically updated by neo4j transactional events.
|
24
|
+
# Notice that if you want to numerical range queries then you should specify a field_type of either Fixnum or Float.
|
25
|
+
# The index type will by default be <tt>:exact</tt>.
|
26
|
+
# Index on property arrays are supported.
|
24
27
|
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
# class Person
|
30
|
-
# include Neo4j::NodeMixin
|
31
|
-
# index :name
|
32
|
-
# end
|
33
|
-
#
|
34
|
-
# When the property name is changed/deleted or the node created it will keep the lucene index in sync.
|
35
|
-
# You can then perform a lucene query like this: Person.find('name: andreas')
|
36
|
-
#
|
37
|
-
# @example Add index on other nodes.
|
38
|
-
#
|
39
|
-
# class Person
|
40
|
-
# include Neo4j::NodeMixin
|
41
|
-
# has_n(:friends).to(Contact)
|
42
|
-
# has_n(:known_by).from(:friends)
|
43
|
-
# index :user_id, :via => :known_by
|
44
|
-
# end
|
45
|
-
#
|
46
|
-
# Notice that you *must* specify an incoming relationship with the via key, as shown above.
|
47
|
-
# In the example above an index <tt>user_id</tt> will be added to all Person nodes which has a <tt>friends</tt> relationship
|
48
|
-
# that person with that user_id. This allows you to do lucene queries on your friends properties.
|
49
|
-
#
|
50
|
-
# @example Set the type value to index
|
51
|
-
#
|
52
|
-
# class Person
|
53
|
-
# include Neo4j::NodeMixin
|
54
|
-
# property :height, :weight, :type => Float
|
55
|
-
# index :height, :weight
|
56
|
-
# end
|
57
|
-
#
|
58
|
-
# By default all values will be indexed as Strings.
|
59
|
-
# If you want for example to do a numerical range query you must tell Neo4j.rb to index it as a numeric value.
|
60
|
-
# You do that with the key <tt>type</tt> on the property.
|
61
|
-
#
|
62
|
-
# Supported values for <tt>:type</tt> is <tt>String</tt>, <tt>Float</tt>, <tt>Date</tt>, <tt>DateTime</tt> and <tt>Fixnum</tt>
|
63
|
-
#
|
64
|
-
# === For more information
|
28
|
+
# @example
|
29
|
+
# MyIndex.index(:age, :field_type => Fixnum) # default :exact
|
30
|
+
# MyIndex.index(:wheels, :field_type => Fixnum)
|
31
|
+
# MyIndex.index(:description, :type => :fulltext)
|
65
32
|
#
|
66
33
|
# @see Neo4j::Core::Index::LuceneQuery
|
67
34
|
# @see #find
|
68
|
-
#
|
69
35
|
def index(*args)
|
70
36
|
@config.index(args)
|
71
37
|
end
|
@@ -96,11 +62,18 @@ module Neo4j
|
|
96
62
|
# @see #index
|
97
63
|
def add_index(entity, field, value)
|
98
64
|
return false unless index?(field)
|
99
|
-
|
65
|
+
if (java_array?(value))
|
66
|
+
conv_value = value.map{|x| indexed_value_for(field, x)}.to_java(Java::OrgNeo4jIndexLucene::ValueContext)
|
67
|
+
else
|
68
|
+
conv_value = indexed_value_for(field, value)
|
69
|
+
end
|
100
70
|
index = index_for_field(field.to_s)
|
101
71
|
index.add(entity, field, conv_value)
|
102
72
|
end
|
103
73
|
|
74
|
+
def java_array?(value)
|
75
|
+
value.respond_to?(:java_class) && value.java_class.to_s[0..0] == '['
|
76
|
+
end
|
104
77
|
|
105
78
|
# Removes an index on the given entity
|
106
79
|
# This is normally not needed since you can instead declare an index which will automatically keep
|
@@ -108,6 +81,7 @@ module Neo4j
|
|
108
81
|
# @see #index
|
109
82
|
def rm_index(entity, field, value)
|
110
83
|
return false unless index?(field)
|
84
|
+
#return value.each {|x| rm_index(entity, field, x)} if value.respond_to?(:each)
|
111
85
|
index_for_field(field).remove(entity, field, value)
|
112
86
|
end
|
113
87
|
|
@@ -120,23 +94,44 @@ module Neo4j
|
|
120
94
|
# (by Rack).
|
121
95
|
#
|
122
96
|
# @example with a block
|
97
|
+
# Person.find('name: kalle') {|query| puts "First item #{query.first}"}
|
123
98
|
#
|
124
|
-
#
|
125
|
-
#
|
126
|
-
# @example
|
127
|
-
#
|
99
|
+
# @example using an exact lucene index
|
128
100
|
# query = Person.find('name: kalle')
|
129
101
|
# puts "First item #{query.first}"
|
130
102
|
# query.close
|
131
103
|
#
|
132
|
-
# @
|
104
|
+
# @example using an fulltext lucene index
|
105
|
+
# query = Person.find('name: kalle', :type => :fulltext)
|
106
|
+
# puts "First item #{query.first}"
|
107
|
+
# query.close
|
108
|
+
#
|
109
|
+
# @example Sorting, descending by one property
|
110
|
+
# Person.find({:name => 'kalle'}, :sort => {:name => :desc})
|
111
|
+
#
|
112
|
+
# @example Sorting using the builder pattern
|
113
|
+
# Person.find(:name => 'kalle').asc(:name)
|
114
|
+
#
|
115
|
+
# @example Searching by a set of values, OR search
|
116
|
+
# Person.find(:name => ['kalle', 'sune', 'jimmy'])
|
117
|
+
#
|
118
|
+
# @example Compound queries and Range queries
|
119
|
+
# Person.find('name: pelle').and(:age).between(2, 5)
|
120
|
+
# Person.find(:name => 'kalle', :age => (2..5))
|
121
|
+
# Person.find("name: 'asd'").and(:wheels => 8)
|
122
|
+
#
|
123
|
+
# @example Using the lucene java object
|
124
|
+
# # using the Neo4j query method directly
|
125
|
+
# # see, http://api.neo4j.org/1.6.1/org/neo4j/graphdb/index/ReadableIndex.html#query(java.lang.Object)
|
126
|
+
# MyIndex.find('description: "hej"', :type => :fulltext, :wrapped => false).get_single
|
127
|
+
#
|
128
|
+
# @param [String, Hash] query the lucene query
|
129
|
+
# @param [Hash] params lucene configuration parameters
|
130
|
+
# @return [Neo4j::Core::Index::LuceneQuery] a query object which uses the builder pattern for creating compound and sort queries.
|
131
|
+
# @note You must specify the index type <tt>:fulltext<tt>) if the property is index using that index (default is <tt>:exact</tt>)
|
133
132
|
def find(query, params = {})
|
134
133
|
index = index_for_type(params[:type] || :exact)
|
135
|
-
|
136
|
-
params.merge! query.reject { |k, _| k == :conditions }
|
137
|
-
query.delete(:sort)
|
138
|
-
query = query.delete(:conditions) if query.include?(:conditions)
|
139
|
-
end
|
134
|
+
query.delete(:sort) if query.is_a?(Hash) && query.include?(:sort)
|
140
135
|
query = (params[:wrapped].nil? || params[:wrapped]) ? LuceneQuery.new(index, @config, query, params) : index.query(query)
|
141
136
|
|
142
137
|
if block_given?
|
@@ -151,6 +146,23 @@ module Neo4j
|
|
151
146
|
end
|
152
147
|
end
|
153
148
|
|
149
|
+
# Add the entity to this index for the given key/value pair if this particular key/value pair doesn't already exist.
|
150
|
+
# This ensures that only one entity will be associated with the key/value pair even if multiple transactions are trying to add it at the same time.
|
151
|
+
# One of those transactions will win and add it while the others will block, waiting for the winning transaction to finish.
|
152
|
+
# If the winning transaction was successful these other transactions will return the associated entity instead of adding it.
|
153
|
+
# If it wasn't successful the waiting transactions will begin a new race to add it.
|
154
|
+
#
|
155
|
+
# @param [Neo4j::Node, Neo4j::Relationship] entity the entity (i.e Node or Relationship) to associate the key/value pair with.
|
156
|
+
# @param [String, Symbol] key the key in the key/value pair to associate with the entity.
|
157
|
+
# @param [String, Fixnum, Float] value the value in the key/value pair to associate with the entity.
|
158
|
+
# @param [Symbol] index_type the type of lucene index
|
159
|
+
# @return [nil, Neo4j:Node, Neo4j::Relationship] the previously indexed entity, or nil if no entity was indexed before (and the specified entity was added to the index).
|
160
|
+
# @see Neo4j::Core::Index::UniqueFactory as an alternative which probably simplify creating unique entities
|
161
|
+
def put_if_absent(entity, key, value, index_type = :exact)
|
162
|
+
index = index_for_type(index_type)
|
163
|
+
index.put_if_absent(entity, key.to_s, value)
|
164
|
+
end
|
165
|
+
|
154
166
|
# Delete all index configuration. No more automatic indexing will be performed
|
155
167
|
def rm_index_config
|
156
168
|
@config.rm_index_config
|
@@ -7,7 +7,7 @@ module Neo4j
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def delete_all_indexes
|
10
|
-
@indexers.
|
10
|
+
@indexers.each { |i| i.rm_index_type }
|
11
11
|
end
|
12
12
|
|
13
13
|
def register(indexer)
|
@@ -16,7 +16,7 @@ module Neo4j
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def indexers_for(props)
|
19
|
-
|
19
|
+
Enumerator.new(self, :each_indexer, props)
|
20
20
|
end
|
21
21
|
|
22
22
|
def each_indexer(props)
|
@@ -39,11 +39,7 @@ module Neo4j
|
|
39
39
|
@query = query
|
40
40
|
@index_config = index_config
|
41
41
|
@params = params
|
42
|
-
|
43
|
-
if params.include?(:sort)
|
44
|
-
@order = {}
|
45
|
-
params[:sort].each_pair { |k, v| @order[k] = (v == :desc) }
|
46
|
-
end
|
42
|
+
@order = params[:sort] if params.include?(:sort)
|
47
43
|
end
|
48
44
|
|
49
45
|
# Implements the Ruby +Enumerable+ interface
|
@@ -85,30 +81,26 @@ module Neo4j
|
|
85
81
|
# Performs a range query
|
86
82
|
# Notice that if you don't specify a type when declaring a property a String range query will be performed.
|
87
83
|
#
|
88
|
-
def between(lower, upper,
|
84
|
+
def between(lower, upper, lower_inclusive=false, upper_inclusive=false)
|
89
85
|
raise "Expected a symbol. Syntax for range queries example: index(:weight).between(a,b)" unless Symbol === @query
|
90
|
-
|
91
|
-
# check that we perform a range query on the same values as we have declared with the property :key, :type => ...
|
92
|
-
type = @index_config.decl_type_on(@query)
|
93
|
-
raise "find(#{@query}).between(#{lower}, #{upper}): #{lower} not a #{type}" if type && !type === lower.class
|
94
|
-
raise "find(#{@query}).between(#{lower}, #{upper}): #{upper} not a #{type}" if type && !type === upper.class
|
95
|
-
|
96
|
-
# Make it possible to convert those values
|
97
|
-
@query = range_query(@query, lower, upper, lower_incusive, upper_inclusive)
|
86
|
+
@query = range_query(@query, lower, upper, lower_inclusive, upper_inclusive)
|
98
87
|
self
|
99
88
|
end
|
100
89
|
|
101
|
-
def range_query(field, lower, upper,
|
102
|
-
|
103
|
-
|
90
|
+
def range_query(field, lower, upper, lower_inclusive, upper_inclusive)
|
91
|
+
type = @index_config.field_type(field)
|
92
|
+
raise "no index on field #{field}" unless type
|
93
|
+
# check that we perform a range query on the same values as we have declared with the property :key, :type => ...
|
94
|
+
raise "find(#{field}).between(#{lower}, #{upper}): #{lower} not a #{type}" unless type == lower.class
|
95
|
+
raise "find(#{field}).between(#{lower}, #{upper}): #{upper} not a #{type}" unless type == upper.class
|
104
96
|
|
105
97
|
case lower
|
106
98
|
when Fixnum
|
107
|
-
Java::OrgApacheLuceneSearch::NumericRangeQuery.new_long_range(field.to_s, lower, upper,
|
99
|
+
Java::OrgApacheLuceneSearch::NumericRangeQuery.new_long_range(field.to_s, lower, upper, lower_inclusive, upper_inclusive)
|
108
100
|
when Float
|
109
|
-
Java::OrgApacheLuceneSearch::NumericRangeQuery.new_double_range(field.to_s, lower, upper,
|
101
|
+
Java::OrgApacheLuceneSearch::NumericRangeQuery.new_double_range(field.to_s, lower, upper, lower_inclusive, upper_inclusive)
|
110
102
|
else
|
111
|
-
Java::OrgApacheLuceneSearch::TermRangeQuery.new(field.to_s, lower, upper,
|
103
|
+
Java::OrgApacheLuceneSearch::TermRangeQuery.new(field.to_s, lower, upper, lower_inclusive, upper_inclusive)
|
112
104
|
end
|
113
105
|
end
|
114
106
|
|
@@ -156,19 +148,28 @@ module Neo4j
|
|
156
148
|
# Sort descending the given fields.
|
157
149
|
# @param [Symbol] fields it should sort
|
158
150
|
def desc(*fields)
|
159
|
-
@order
|
151
|
+
@order ||= []
|
152
|
+
@order += fields.map { |f| [f, :desc] }
|
160
153
|
self
|
161
154
|
end
|
162
155
|
|
163
156
|
# Sort ascending the given fields.
|
164
157
|
# @param [Symbol] fields it should sort
|
165
158
|
def asc(*fields)
|
166
|
-
@order
|
159
|
+
@order ||= []
|
160
|
+
@order += fields.map { |f| [f, :asc] }
|
167
161
|
self
|
168
162
|
end
|
169
163
|
|
170
164
|
protected
|
171
165
|
|
166
|
+
def parse_query(query)
|
167
|
+
version = Java::OrgApacheLuceneUtil::Version::LUCENE_30
|
168
|
+
analyzer = Java::OrgApacheLuceneAnalysisStandard::StandardAnalyzer.new(version)
|
169
|
+
parser = Java::org.apache.lucene.queryParser.QueryParser.new(version, 'name', analyzer)
|
170
|
+
parser.parse(query)
|
171
|
+
end
|
172
|
+
|
172
173
|
def build_and_query(query)
|
173
174
|
build_composite_query(@left_and_query.build_query, query, Java::OrgApacheLuceneSearch::BooleanClause::Occur::MUST)
|
174
175
|
end
|
@@ -179,6 +180,9 @@ module Neo4j
|
|
179
180
|
|
180
181
|
def build_not_query(query)
|
181
182
|
right_query = @right_not_query.build_query
|
183
|
+
query = parse_query(query) if query.is_a?(String)
|
184
|
+
right_query = parse_query(right_query) if right_query.is_a?(String)
|
185
|
+
|
182
186
|
composite_query = Java::OrgApacheLuceneSearch::BooleanQuery.new
|
183
187
|
composite_query.add(query, Java::OrgApacheLuceneSearch::BooleanClause::Occur::MUST_NOT)
|
184
188
|
composite_query.add(right_query, Java::OrgApacheLuceneSearch::BooleanClause::Occur::MUST)
|
@@ -186,31 +190,27 @@ module Neo4j
|
|
186
190
|
end
|
187
191
|
|
188
192
|
def build_composite_query(left_query, right_query, operator) #:nodoc:
|
193
|
+
left_query = parse_query(left_query) if left_query.is_a?(String)
|
194
|
+
right_query = parse_query(right_query) if right_query.is_a?(String)
|
189
195
|
composite_query = Java::OrgApacheLuceneSearch::BooleanQuery.new
|
190
|
-
version = Java::OrgApacheLuceneUtil::Version::LUCENE_35
|
191
|
-
analyzer = org.apache.lucene.analysis.standard::StandardAnalyzer.new(version)
|
192
|
-
parser = Java::org.apache.lucene.queryParser.QueryParser.new(version,'name', analyzer )
|
193
|
-
|
194
|
-
left_query = parser.parse(left_query) if left_query.is_a?(String)
|
195
|
-
right_query = parser.parse(right_query) if right_query.is_a?(String)
|
196
|
-
|
197
196
|
composite_query.add(left_query, operator)
|
198
197
|
composite_query.add(right_query, operator)
|
199
198
|
composite_query
|
200
199
|
end
|
201
200
|
|
202
201
|
def build_sort_query(query) #:nodoc:
|
203
|
-
java_sort_fields = @order.
|
204
|
-
|
202
|
+
java_sort_fields = @order.inject([]) do |memo, val|
|
203
|
+
field = val[0]
|
204
|
+
field_type = @index_config.field_type(field)
|
205
205
|
type = case
|
206
|
-
when Float ==
|
206
|
+
when Float == field_type
|
207
207
|
Java::OrgApacheLuceneSearch::SortField::DOUBLE
|
208
|
-
when Fixnum ==
|
208
|
+
when Fixnum == field_type
|
209
209
|
Java::OrgApacheLuceneSearch::SortField::LONG
|
210
210
|
else
|
211
211
|
Java::OrgApacheLuceneSearch::SortField::STRING
|
212
212
|
end
|
213
|
-
memo << Java::OrgApacheLuceneSearch::SortField.new(field.to_s, type,
|
213
|
+
memo << Java::OrgApacheLuceneSearch::SortField.new(field.to_s, type, val[1] == :desc)
|
214
214
|
end
|
215
215
|
sort = Java::OrgApacheLuceneSearch::Sort.new(*java_sort_fields)
|
216
216
|
Java::OrgNeo4jIndexLucene::QueryContext.new(query).sort(sort)
|
@@ -220,18 +220,29 @@ module Neo4j
|
|
220
220
|
and_query = Java::OrgApacheLuceneSearch::BooleanQuery.new
|
221
221
|
|
222
222
|
query.each_pair do |key, value|
|
223
|
-
type = @index_config
|
224
|
-
if
|
223
|
+
type = @index_config.field_type(key)
|
224
|
+
if type != String
|
225
225
|
if Range === value
|
226
|
-
and_query.add(range_query(key, value.first, value.last, true, !value.exclude_end?), Java::
|
226
|
+
and_query.add(range_query(key, value.first, value.last, true, !value.exclude_end?), Java::OrgApacheLuceneSearch::BooleanClause::Occur::MUST)
|
227
|
+
elsif Array === value
|
228
|
+
value.each do |v|
|
229
|
+
and_query.add(range_query(key, v, v, true, true), Java::OrgApacheLuceneSearch::BooleanClause::Occur::SHOULD)
|
230
|
+
end
|
227
231
|
else
|
228
|
-
and_query.add(range_query(key, value, value, true, true), Java::
|
232
|
+
and_query.add(range_query(key, value, value, true, true), Java::OrgApacheLuceneSearch::BooleanClause::Occur::MUST)
|
229
233
|
end
|
230
234
|
else
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
+
if Array === value
|
236
|
+
value.each do |v|
|
237
|
+
term = Java::OrgApacheLuceneIndex::Term.new(key.to_s, v.to_s)
|
238
|
+
term_query = Java::OrgApacheLuceneSearch::TermQuery.new(term)
|
239
|
+
and_query.add(term_query, Java::OrgApacheLuceneSearch::BooleanClause::Occur::SHOULD)
|
240
|
+
end
|
241
|
+
else
|
242
|
+
term = Java::OrgApacheLuceneIndex::Term.new(key.to_s, value.to_s)
|
243
|
+
term_query = Java::OrgApacheLuceneSearch::TermQuery.new(term)
|
244
|
+
and_query.add(term_query, Java::OrgApacheLuceneSearch::BooleanClause::Occur::MUST)
|
245
|
+
end
|
235
246
|
end
|
236
247
|
end
|
237
248
|
and_query
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Core
|
3
|
+
|
4
|
+
module Index
|
5
|
+
|
6
|
+
# A Utility class that can be used to make it easier to create unique entities. It uses {Neo4j::Core::Index::Indexer#put_if_absent}.
|
7
|
+
#
|
8
|
+
# @see Indexer#put_if_absent
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# index = index_for_type(:exact)
|
12
|
+
# Neo4j::Core::Index::UniqueFactory.new(:email, index) { |k,v| Neo4j::Node.new(k => v) }.get_or_create(:email, 'foo@gmail.com')
|
13
|
+
#
|
14
|
+
class UniqueFactory
|
15
|
+
# @param [Symbol] key only one key is possible
|
16
|
+
# @param [Java::Neo4j] index the lucene index (see #index_for_type)
|
17
|
+
# @yield a proc for initialize each created entity
|
18
|
+
def initialize(key, index, &entity_creator_block)
|
19
|
+
@key = key
|
20
|
+
@index = index
|
21
|
+
@entity_creator_block = entity_creator_block || Proc.new{|k,v| Neo4j::Node.new(key.to_s => v)}
|
22
|
+
end
|
23
|
+
|
24
|
+
# Get the indexed entity, creating it (exactly once) if no indexed entity exists.
|
25
|
+
# There must be an index on the key
|
26
|
+
# @param [Symbol] key the key to find the entity under in the index.
|
27
|
+
# @param [String, Fixnum, Float] value the value the key is mapped to for the entity in the index.
|
28
|
+
# @param [Hash] props optional properties that the entity will have if created
|
29
|
+
# @yield optional, make it possible to initialize the created node in a block
|
30
|
+
def get_or_create(key, value, props=nil, &init_block)
|
31
|
+
tx = Neo4j::Transaction.new
|
32
|
+
result = @index.get(key.to_s, value).get_single
|
33
|
+
return result if result
|
34
|
+
|
35
|
+
created = @entity_creator_block.call(key,value)
|
36
|
+
result = @index.put_if_absent(created._java_entity, key.to_s, value)
|
37
|
+
if result.nil?
|
38
|
+
props.each_pair{|k,v| created[k.to_s] = v} if props
|
39
|
+
init_block.call(result) if init_block
|
40
|
+
result = created
|
41
|
+
else
|
42
|
+
created.del
|
43
|
+
end
|
44
|
+
tx.success
|
45
|
+
result
|
46
|
+
ensure
|
47
|
+
tx.finish
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -61,11 +61,11 @@ module Neo4j
|
|
61
61
|
end
|
62
62
|
|
63
63
|
# Loads a node or wrapped node given a native java node or an id.
|
64
|
-
# If there is a Ruby wrapper for the node then it will create a Ruby object that will
|
65
|
-
# wrap the java node
|
66
|
-
# To implement a wrapper you must implement a wrapper class method in the Neo4j::Node or Neo4j::Relationship.
|
64
|
+
# If there is a Ruby wrapper for the node then it will create and return a Ruby object that will
|
65
|
+
# wrap the java node.
|
67
66
|
#
|
68
|
-
# @
|
67
|
+
# @param [nil, #to_i] node_id the neo4j node id
|
68
|
+
# @return [Object, Neo4j::Node, nil] If the node does not exist it will return nil otherwise the loaded node or wrapped node.
|
69
69
|
def load(node_id, db = Neo4j.started_db)
|
70
70
|
node = _load(node_id, db)
|
71
71
|
node && node.wrapper
|
data/lib/neo4j-core/node/node.rb
CHANGED
@@ -31,14 +31,7 @@ module Neo4j
|
|
31
31
|
Neo4j::Node.exist?(self)
|
32
32
|
end
|
33
33
|
|
34
|
-
#
|
35
|
-
# This allows you to create a custom Ruby wrapper class around the Neo4j::Node.
|
36
|
-
# This is for example done in the <tt>neo4j<//t> ruby gem <tt>Neo4j::NodeMixin</tt>
|
37
|
-
# @return a wrapper object or self
|
38
|
-
def wrapper
|
39
|
-
self.class.respond_to?(:wrapper) ? self.class.wrapper(node) : self
|
40
|
-
end
|
41
|
-
|
34
|
+
# Overrides the class so that the java object feels like a Ruby object.
|
42
35
|
def class
|
43
36
|
Neo4j::Node
|
44
37
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Neo4j
|
2
|
+
module Core
|
3
|
+
module Property
|
4
|
+
# This module is only used for documentation purpose
|
5
|
+
# It simplify declares the java methods which are available Java org.neo4j.graphdb.PropertyContainer
|
6
|
+
# @see http://api.neo4j.org/1.6.1/org/neo4j/graphdb/PropertyContainer.html
|
7
|
+
module Java
|
8
|
+
|
9
|
+
|
10
|
+
# Get the GraphDatabaseService that this Node or Relationship belongs to.
|
11
|
+
# @return [Java::Neo4jGraphdbGraphDatabaseService]
|
12
|
+
def graph_database
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns the property value associated with the given key, or a default value.
|
16
|
+
# The value is of one of the valid property types, i.e. a Java primitive, a String or an array of any of the valid types.
|
17
|
+
# If there's no property associated with key an unchecked exception is raised.
|
18
|
+
# The idiomatic way to avoid an exception for an unknown key and instead get null back is to use a default value: Object valueOrNull = nodeOrRel.getProperty( key, null )
|
19
|
+
# @param [String] key the property key
|
20
|
+
# @param [String] default_value the default value that will be returned if no property value was associated with the given key
|
21
|
+
# @return [String,Fixnum,Boolean,Float,Array] ]the property value associated with the given key.
|
22
|
+
# @raise an exception if not given a default value and there is no property for the given key
|
23
|
+
# @see Neo4j::Core:Property#[]
|
24
|
+
def get_property(key, default_value = nil)
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return all existing property keys, or an empty iterable if this property container has no properties.
|
28
|
+
def property_keys
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
# Removes the property associated with the given key and returns the old value.
|
33
|
+
# @param [String] key the name of the property
|
34
|
+
# @return [String,Fixnum,Boolean,Float,Array, nil] The old value or <tt>nil</tt> if there's no property associated with the key.
|
35
|
+
def remove_property(key)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Sets the property value for the given key to value.
|
39
|
+
# The property value must be one of the valid property types, i.e:
|
40
|
+
# * boolean or boolean[]
|
41
|
+
# * byte or byte[]
|
42
|
+
# * short or short[]
|
43
|
+
# * int or int[]
|
44
|
+
# * long or long[]
|
45
|
+
# * float or float[]
|
46
|
+
# * double or double[]
|
47
|
+
# * char or char[]
|
48
|
+
# * java.lang.String or String[]
|
49
|
+
# Notice that JRuby does map Ruby primitive object (e.g. Fixnum) to java primitives automatically.
|
50
|
+
# Also, nil is not an accepted property value.
|
51
|
+
# @param [String] key the property key
|
52
|
+
# @param [String,Fixnum,Boolean,Float,Array] value
|
53
|
+
# @see Neo4j::Core::Property#[]=
|
54
|
+
def set_property(key, value)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|