class Neo4j::Index::Indexer

Attributes

entity_type[R]
field_types[R]
index_types[R]
indexer_for[R]
parent_indexers[R]
via_relationships[R]

Public Instance Methods

add_index(entity, field, value) click to toggle source

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 #index

# File lib/neo4j/index/indexer.rb, line 187
def add_index(entity, field, value)
  return false unless @field_types.has_key?(field)
  conv_value = indexed_value_for(field, value)
  index = index_for_field(field.to_s)
  index.add(entity, field, conv_value)
  @parent_indexers.each { |i| i.add_index(entity, field, value) }
end
delete_index_type(type=nil) click to toggle source

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

# File lib/neo4j/index/indexer.rb, line 266
def delete_index_type(type=nil)
  if type
    #raise "can't clear index of type '#{type}' since it does not exist ([#{@field_types.values.join(',')}] exists)" unless index_type?(type)
    key = index_key(type)
    @indexes[key] && @indexes[key].delete
    @indexes[key] = nil
  else
    @indexes.each_value { |index| index.delete }
    @indexes.clear
  end
end
find(query, params = {}) { |query| ... } click to toggle source

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::Index::LuceneQuery#close method. When performing queries from Ruby on Rails you do not need this since it will be automatically closed (by Rack).

Example, with a block

Person.find('name: kalle') {|query| puts "#{[*query].join(', )"}

Example

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

Return Value

It will return a Neo4j::Index::LuceneQuery object

# File lib/neo4j/index/indexer.rb, line 241
def find(query, params = {})
  # we might need to know what type the properties are when indexing and querying
  @decl_props ||= @indexer_for.respond_to?(:_decl_props) && @indexer_for._decl_props

  index       = index_for_type(params[:type] || :exact)
  if query.is_a?(Hash) && (query.include?(:conditions) || query.include?(:sort))
    params.merge! query.except(:conditions)
    query.delete(:sort)
    query = query.delete(:conditions) if query.include?(:conditions)
  end
  query = (params[:wrapped].nil? || params[:wrapped]) ? LuceneQuery.new(index, @decl_props, query, params) : index.query(query)

  if block_given?
    begin
      ret = yield query
    ensure
      query.close
    end
    ret
  else
    query
  end
end
index(*args) click to toggle source
Add an index on a field so that it will be automatically updated by neo4j transactional events.

The index method takes an optional configuration hash which allows you to:

=== Add an index on an a property

Example:
  class Person
    include Neo4j::NodeMixin
    index :name
  end

When the property name is changed/deleted or the node created it will keep the lucene index in sync.
You can then perform a lucene query like this: Person.find('name: andreas')

=== Add index on other nodes.

Example:

  class Person
    include Neo4j::NodeMixin
    has_n(:friends).to(Contact)
    has_n(:known_by).from(:friends)
    index :user_id, :via => :known_by
  end

Notice that you *must* specify an incoming relationship with the via key, as shown above.
In the example above an index <tt>user_id</tt> will be added to all Person nodes which has a <tt>friends</tt> relationship
that person with that user_id. This allows you to do lucene queries on your friends properties.

=== Set the type value to index
By default all values will be indexed as Strings.
If you want for example to do a numerical range query you must tell Neo4j.rb to index it as a numeric value.
You do that with the key <tt>type</tt> on the property.

Example:
  class Person
    include Neo4j::NodeMixin
    property :height, :weight, :type => Float
    index :height, :weight
  end

Supported values for <tt>:type</tt> is <tt>String</tt>, <tt>Float</tt>, <tt>Date</tt>, <tt>DateTime</tt> and <tt>Fixnum</tt>

=== For more information
* See Neo4j::Index::LuceneQuery
* See #find
# File lib/neo4j/index/indexer.rb, line 82
def index(*args)
  conf = args.last.kind_of?(Hash) ? args.pop : {}
  conf_no_via = conf.reject { |k,v| k == :via } # avoid endless recursion

  args.uniq.each do | field |
    if conf[:via]
      rel_dsl = @indexer_for._decl_rels[conf[:via]]
      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
      raise "Only incoming relationship are possible to define index on. Check class '#{@indexer_for}': index :#{field}, via=>:#{conf[:via]}" unless rel_dsl.incoming?
      via_indexer               = rel_dsl.target_class._indexer

      field                     = field.to_s
      @via_relationships[field] = rel_dsl
      via_indexer.index(field, conf_no_via)
    else
      @field_types[field.to_s] = conf[:type] || :exact
    end
  end
end
index?(field) click to toggle source

Returns true if there is an index on the given field.

# File lib/neo4j/index/indexer.rb, line 167
def index?(field)
  @field_types.include?(field.to_s)
end
index_key(type) click to toggle source
# File lib/neo4j/index/indexer.rb, line 303
def index_key(type)
  index_names[type] + type.to_s
end
index_names() click to toggle source
# File lib/neo4j/index/indexer.rb, line 323
def index_names
  @index_names ||= Hash.new do |hash, index_type|
    default_filename = index_prefix + @indexer_for.to_s.gsub('::', '_')
    hash.fetch(index_type) {"#{default_filename}_#{index_type}"}
  end
end
index_type?(type) click to toggle source

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

# File lib/neo4j/index/indexer.rb, line 179
def index_type?(type)
  @field_types.values.include?(type)
end
indexed_value_for(field, value) click to toggle source
# File lib/neo4j/index/indexer.rb, line 195
def indexed_value_for(field, value)
  # we might need to know what type the properties are when indexing and querying
  @decl_props ||= @indexer_for.respond_to?(:_decl_props) && @indexer_for._decl_props

  type        = @decl_props && @decl_props[field.to_sym] && @decl_props[field.to_sym][:type]
  return value unless type

  if String != type
    org.neo4j.index.lucene.ValueContext.new(value).indexNumeric
  else
    org.neo4j.index.lucene.ValueContext.new(value)
  end
end
rm_field_type(type=nil) click to toggle source

Removes the cached lucene index, can be useful for some RSpecs which needs to restart the Neo4j.

# File lib/neo4j/index/indexer.rb, line 286
def rm_field_type(type=nil)
  if type
    @field_types.delete_if { |k, v| v == type }
  else
    @field_types.clear
  end
end
rm_index(entity, field, value) click to toggle source

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 #index

# File lib/neo4j/index/indexer.rb, line 213
def rm_index(entity, field, value)
  return false unless @field_types.has_key?(field)
  index_for_field(field).remove(entity, field, value)
  @parent_indexers.each { |i| i.rm_index(entity, field, value) }
end
to_s() click to toggle source
# File lib/neo4j/index/indexer.rb, line 30
def to_s
  "Indexer @#{object_id} [index_for:#{@indexer_for}, field_types=#{@field_types.keys.join(', ')}, via=#{@via_relationships.inspect}]"
end

Protected Instance Methods

index_prefix() click to toggle source
# File lib/neo4j/index/indexer.rb, line 331
def index_prefix
  return "" unless Neo4j.running?
  return "" unless @indexer_for.respond_to?(:ref_node_for_class)
  ref_node = @indexer_for.ref_node_for_class.wrapper
  prefix = ref_node.send(:_index_prefix) if ref_node.respond_to?(:_index_prefix)
  prefix ||= ref_node[:name] # To maintain backward compatiblity
  prefix.blank? ? "" : prefix + "_"
end