Class: Neo4j::Core::Index::Indexer

Inherits:
Object
  • Object
show all
Defined in:
lib/neo4j-core/index/indexer.rb

Overview

This class is delegated from the Neo4j::Core::Index::ClassMethod

See Also:

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ Indexer

Returns a new instance of Indexer.



11
12
13
14
15
16
# File 'lib/neo4j-core/index/indexer.rb', line 11

def initialize(config)
  @config = config
  @indexes = {} # key = type, value = java neo4j index
                # to enable subclass indexing to work properly, store a list of parent indexers and
                # whenever an operation is performed on this one, perform it on all
end

Instance Attribute Details

#configNeo4j::Core::Index::IndexConfig (readonly)



9
10
11
# File 'lib/neo4j-core/index/indexer.rb', line 9

def config
  @config
end

Instance Method Details

#add_index(entity, field, value) ⇒ Object

Adds an index on the given entity This is normally not needed since you can instead declare an index which will automatically keep the lucene index in sync.

See Also:



63
64
65
66
67
68
69
70
71
72
# File 'lib/neo4j-core/index/indexer.rb', line 63

def add_index(entity, field, value)
  return false unless index?(field)
  if (java_array?(value))
    conv_value = value.map{|x| indexed_value_for(field, x)}.to_java(Java::OrgNeo4jIndexLucene::ValueContext)
  else
    conv_value = indexed_value_for(field, value)
  end
  index = index_for_field(field.to_s)
  index.add(entity, field, conv_value)
end

#create_index_with(type, index_name) ⇒ Java::OrgNeo4jGraphdb::Index

Creates a new lucene index using the lucene configuration for the given index_name

Parameters:

  • type (:node, :relationship)

    relationship or node index

  • index_name (String)

    the (file) name of the index

Returns:

  • (Java::OrgNeo4jGraphdb::Index)

    for the given index type



241
242
243
244
245
246
247
248
249
# File 'lib/neo4j-core/index/indexer.rb', line 241

def create_index_with(type, index_name)
  db = Neo4j.started_db
  index_config = lucene_config(type)
  if config.entity_type == :node
    db.lucene.for_nodes(index_name, index_config)
  else
    db.lucene.for_relationships(index_name, index_config)
  end
end

#find(query, params = {}) ⇒ Neo4j::Core::Index::LuceneQuery

Note:

You must specify the index type :fulltext<tt>) if the property is index using that index (default is <tt>:exact)

Performs a Lucene Query.

In order to use this you have to declare an index on the fields first, see #index. Notice that you should close the lucene query after the query has been executed. You can do that either by provide an block or calling the Neo4j::Core::Index::LuceneQuery#close method. When performing queries from Ruby on Rails you do not need this since it will be automatically closed (by Rack).

Examples:

with a block

Person.find('name: kalle') {|query| puts "First item #{query.first}"}

using an exact lucene index

query = Person.find('name: kalle')
puts "First item #{query.first}"
query.close

using an fulltext lucene index

query = Person.find('name: kalle', :type => :fulltext)
puts "First item #{query.first}"
query.close

Sorting, descending by one property

Person.find({:name => 'kalle'}, :sort => {:name => :desc})

Sorting using the builder pattern

Person.find(:name => 'kalle').asc(:name)

Searching by a set of values, OR search

Person.find(:name => ['kalle', 'sune', 'jimmy'])

Compound queries and Range queries

Person.find('name: pelle').and(:age).between(2, 5)
Person.find(:name => 'kalle', :age => (2..5))
Person.find("name: 'asd'").and(:wheels => 8)

Using the lucene java object

# using the Neo4j query method directly
# see, http://api.neo4j.org/1.6.1/org/neo4j/graphdb/index/ReadableIndex.html#query(java.lang.Object)
MyIndex.find('description: "hej"', :type => :fulltext, :wrapped => false).get_single

Parameters:

  • query (String, Hash)

    the lucene query

  • params (Hash) (defaults to: {})

    lucene configuration parameters

Returns:



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/neo4j-core/index/indexer.rb', line 132

def find(query, params = {})
  index = index_for_type(params[:type] || :exact)
  query.delete(:sort) if query.is_a?(Hash) && query.include?(:sort)
  query = (params[:wrapped].nil? || params[:wrapped]) ? LuceneQuery.new(index, @config, query, params) : index.query(query)

  if block_given?
    begin
      ret = yield query
    ensure
      query.close
    end
    ret
  else
    query
  end
end

#has_index_type?(type) ⇒ true, false

Returns if there is an index of the given type defined.

Returns:

  • (true, false)

    if there is an index of the given type defined.



55
56
57
# File 'lib/neo4j-core/index/indexer.rb', line 55

def has_index_type?(type)
  @config.has_index_type?(type)
end

#index(*args) ⇒ Object

Add an index on a field so that it will be automatically updated by neo4j transactional events. Notice that if you want to numerical range queries then you should specify a field_type of either Fixnum or Float. The index type will by default be :exact. Index on property arrays are supported.

Examples:

MyIndex.index(:age, :field_type => Fixnum) # default :exact
MyIndex.index(:wheels, :field_type => Fixnum)
MyIndex.index(:description, :type => :fulltext)

See Also:



35
36
37
# File 'lib/neo4j-core/index/indexer.rb', line 35

def index(*args)
  @config.index(args)
end

#index?(field) ⇒ true, false

Returns if there is an index on the given field.

Returns:

  • (true, false)

    if there is an index on the given field.



40
41
42
# File 'lib/neo4j-core/index/indexer.rb', line 40

def index?(field)
  @config.index?(field)
end

#index_for_field(field) ⇒ Java::OrgNeo4jGraphdb::Index

Returns for the given field.

Returns:

  • (Java::OrgNeo4jGraphdb::Index)

    for the given field



212
213
214
215
216
# File 'lib/neo4j-core/index/indexer.rb', line 212

def index_for_field(field)
  type = @config.index_type(field)
  index_name = index_name_for_type(type)
  @indexes[index_name] ||= create_index_with(type, index_name)
end

#index_for_type(type) ⇒ Java::OrgNeo4jGraphdb::Index

Returns for the given index type.

Returns:

  • (Java::OrgNeo4jGraphdb::Index)

    for the given index type



219
220
221
222
# File 'lib/neo4j-core/index/indexer.rb', line 219

def index_for_type(type)
  index_name = index_name_for_type(type)
  @indexes[index_name] ||= create_index_with(type, index_name)
end

#index_name_for_type(type) ⇒ String

Returns the name of the index which are stored on the filesystem.

Returns:

  • (String)

    the name of the index which are stored on the filesystem



225
226
227
# File 'lib/neo4j-core/index/indexer.rb', line 225

def index_name_for_type(type)
  @config.index_name_for_type(type)
end

#index_type(field) ⇒ Symbol

Returns the type of index for the given field (e.g. :exact or :fulltext).

Returns:

  • (Symbol)

    the type of index for the given field (e.g. :exact or :fulltext)



50
51
52
# File 'lib/neo4j-core/index/indexer.rb', line 50

def index_type(field)
  @config.index_type(field)
end

#indexed_value_for(field, value) ⇒ Java::OrgNeo4jIndexLucene::ValueContext

Creates a wrapped ValueContext for the given value. Checks if it’s numeric value in the configuration.

Returns:

  • (Java::OrgNeo4jIndexLucene::ValueContext)

    a wrapped neo4j lucene value context



203
204
205
206
207
208
209
# File 'lib/neo4j-core/index/indexer.rb', line 203

def indexed_value_for(field, value)
  if @config.numeric?(field)
    Java::OrgNeo4jIndexLucene::ValueContext.new(value).indexNumeric
  else
    Java::OrgNeo4jIndexLucene::ValueContext.new(value)
  end
end

#java_array?(value) ⇒ Boolean

Returns:

  • (Boolean)


74
75
76
# File 'lib/neo4j-core/index/indexer.rb', line 74

def java_array?(value)
  value.respond_to?(:java_class) && value.java_class.to_s[0..0] == '['
end

#lucene_config(type) ⇒ Hash

Returns the lucene config for the given index type.

Returns:

  • (Hash)

    the lucene config for the given index type



230
231
232
233
234
# File 'lib/neo4j-core/index/indexer.rb', line 230

def lucene_config(type)
  conf = Neo4j::Config[:lucene][type.to_s]
  raise "unknown lucene type #{type}" unless conf
  conf
end

#on_neo4j_shutdownObject

Called when the neo4j shutdown in order to release references to indexes



184
185
186
# File 'lib/neo4j-core/index/indexer.rb', line 184

def on_neo4j_shutdown
  @indexes.clear
end

#put_if_absent(entity, key, value, index_type = :exact) ⇒ nil, ...

Add the entity to this index for the given key/value pair if this particular key/value pair doesn’t already exist. 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. One of those transactions will win and add it while the others will block, waiting for the winning transaction to finish. If the winning transaction was successful these other transactions will return the associated entity instead of adding it. If it wasn’t successful the waiting transactions will begin a new race to add it.

Parameters:

  • entity (Neo4j::Node, Neo4j::Relationship)

    the entity (i.e Node or Relationship) to associate the key/value pair with.

  • key (String, Symbol)

    the key in the key/value pair to associate with the entity.

  • value (String, Fixnum, Float)

    the value in the key/value pair to associate with the entity.

  • index_type (Symbol) (defaults to: :exact)

    the type of lucene index

Returns:

  • (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).

See Also:



161
162
163
164
# File 'lib/neo4j-core/index/indexer.rb', line 161

def put_if_absent(entity, key, value, index_type = :exact)
  index = index_for_type(index_type)
  index.put_if_absent(entity, key.to_s, value)
end

#remove_index_on(node, old_props) ⇒ Object

Called from the event handler when deleting a property



197
198
199
# File 'lib/neo4j-core/index/indexer.rb', line 197

def remove_index_on(node, old_props)
  @config.fields.each { |field| rm_index(node, field, old_props[field]) if old_props[field] }
end

#rm_index(entity, field, value) ⇒ Object

Removes an index on the given entity This is normally not needed since you can instead declare an index which will automatically keep the lucene index in sync.

See Also:



82
83
84
85
86
# File 'lib/neo4j-core/index/indexer.rb', line 82

def rm_index(entity, field, value)
  return false unless index?(field)
  #return value.each {|x| rm_index(entity, field, x)} if value.respond_to?(:each)
  index_for_field(field).remove(entity, field, value)
end

#rm_index_configObject

Delete all index configuration. No more automatic indexing will be performed



167
168
169
# File 'lib/neo4j-core/index/indexer.rb', line 167

def rm_index_config
  @config.rm_index_config
end

#rm_index_type(type = nil) ⇒ Object

delete the index, if no type is provided clear all types of indexes



172
173
174
175
176
177
178
179
180
181
# File 'lib/neo4j-core/index/indexer.rb', line 172

def rm_index_type(type=nil)
  if type
    key = @config.index_name_for_type(type)
    @indexes[key] && @indexes[key].delete
    @indexes[key] = nil
  else
    @indexes.each_value { |index| index.delete }
    @indexes.clear
  end
end

#to_sObject



19
20
21
# File 'lib/neo4j-core/index/indexer.rb', line 19

def to_s
  "Indexer @#{object_id} index on: [#{@config.fields.map { |f| @config.numeric?(f) ? "#{f} (numeric)" : f }.join(', ')}]"
end

#trigger_on?(props) ⇒ true, false

Returns if the.

Returns:

  • (true, false)

    if the



45
46
47
# File 'lib/neo4j-core/index/indexer.rb', line 45

def trigger_on?(props)
  @config.trigger_on?(props)
end

#update_index_on(node, field, old_val, new_val) ⇒ Object

Called from the event handler when a new node or relationships is about to be committed.



189
190
191
192
193
194
# File 'lib/neo4j-core/index/indexer.rb', line 189

def update_index_on(node, field, old_val, new_val)
  if index?(field)
    rm_index(node, field, old_val) if old_val
    add_index(node, field, new_val) if new_val
  end
end