Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Impl. Indexing of Ruby Date object. Need some more test/docs and then…
… the ticket is resolved. Updated RDocs. [#2]
  • Loading branch information
andreasronge committed Dec 17, 2008
1 parent 94938a4 commit 899925e
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 34 deletions.
7 changes: 3 additions & 4 deletions lib/lucene/document.rb
Expand Up @@ -7,7 +7,7 @@ module Lucene
#
class Document

attr_reader :id_field, :field_infos
attr_reader :id_field, :field_infos, :props

def initialize(field_infos, props = {})
@id_field = field_infos.id_field
Expand All @@ -31,7 +31,6 @@ def [](key)
def self.convert(field_infos, java_doc)
fields = {}
field_infos.each_pair do |key, field|
#puts "Convert field #{key} store=#{field.store?}"
next unless field.store?
raise StandardError.new("expected field '#{key.to_s}' to exist in document") if java_doc.getField(key.to_s).nil?
value = java_doc.getField(key.to_s).stringValue
Expand Down Expand Up @@ -78,11 +77,11 @@ def java_document
if (value.kind_of?(Array))
value.each do |v|
field = field_info.java_field(key,v)
java_doc.add(field)
java_doc.add(field) unless field.nil?
end
else
field = field_info.java_field(key,value)
java_doc.add(field)
java_doc.add(field) unless field.nil?
end
end
java_doc
Expand Down
16 changes: 15 additions & 1 deletion lib/lucene/field_info.rb
Expand Up @@ -25,13 +25,24 @@ def []=(key,value)
end

def java_field(key, value)
store = store? ? org.apache.lucene.document.Field::Store::YES : org.apache.lucene.document.Field::Store::NO
# convert the ruby value to a string that lucene can handle
cvalue = convert_to_lucene(value)

# check if this field should be indexed
return nil if cvalue.nil?

# decide if the field should be stored in the lucene index or not
store = store? ? org.apache.lucene.document.Field::Store::YES : org.apache.lucene.document.Field::Store::NO

# decide if it should be tokenized/analyzed by lucene
token_type = tokenized? ? org.apache.lucene.document.Field::Index::ANALYZED : org.apache.lucene.document.Field::Index::NOT_ANALYZED
$LUCENE_LOGGER.debug{"java_field store=#{store} key='#{key.to_s}' value='#{cvalue}' token_type=#{token_type}"}

# create the new Field
org.apache.lucene.document.Field.new(key.to_s, cvalue, store, token_type ) #org.apache.lucene.document.Field::Index::NO_NORMS)
end


def convert_to_ruby(value)
if (value.kind_of?(Array))
value.collect{|v| convert_to_ruby(v)}
Expand All @@ -42,6 +53,7 @@ def convert_to_ruby(value)
when Float.to_s then value.to_f
when Date.to_s
return value if value.kind_of? Date
return nil if value.nil?
date = org.apache.lucene.document.DateTools.stringToDate(value)
seconds_since_1970 = date.getTime / 1000
Date.new(*Time.at(seconds_since_1970).to_a[3 .. 5].reverse)
Expand All @@ -54,6 +66,8 @@ def convert_to_ruby(value)
def convert_to_lucene(value)
if (value.kind_of?(Array))
value.collect{|v| convert_to_lucene(v)}
elsif value.nil?
value
else
case @info[:type].to_s # otherwise it will match Class
when Fixnum.to_s then sprintf('%011d',value) # TODO: configurable
Expand Down
6 changes: 2 additions & 4 deletions lib/lucene/index.rb
Expand Up @@ -158,8 +158,6 @@ def updated?(id)
@uncommited[id.to_s]
end

#
#
# Writes to the index files
# Open and closes an lucene IndexWriter
# Close the IndexSearcher so that it will read the updated index next time.
Expand Down Expand Up @@ -260,7 +258,7 @@ def exist?
def update_documents
index_writer = org.apache.lucene.index.IndexWriter.new(@index_info.storage, org.apache.lucene.analysis.standard.StandardAnalyzer.new, ! exist?)
@uncommited.each_value do |doc|
# removes the document and adds it
# removes the document and adds it again
doc.update(index_writer)
end
ensure
Expand All @@ -276,7 +274,7 @@ def delete_documents
id_field = @index_info.infos[@index_info.id_field]

@deleted_ids.each do |id|
converted_value = id_field.convert_to_lucene(id)
converted_value = id_field.convert_to_lucene(id)
writer.deleteDocuments(org.apache.lucene.index.Term.new(@index_info.id_field.to_s, converted_value))
end
ensure
Expand Down
4 changes: 2 additions & 2 deletions lib/lucene/transaction.rb
Expand Up @@ -18,10 +18,10 @@ def initialize
def to_s
"Transaction [commited=#@commited, rollback=#@rollback, indexes=#{@indexes.size}, object_id=#{object_id}]"
end
#


# Commits all registered Indexes.
# Stops this transaction (running? will be false)
# TODO rename commit method to finish ?
#
def commit
if !@rollback
Expand Down
36 changes: 22 additions & 14 deletions lib/neo4j/mixins/node.rb
Expand Up @@ -17,15 +17,16 @@ module NodeMixin

extend TransactionalMixin

#

# Initialize the the neo node for this instance.
# Will create a new transaction if one is not already running.
# If a block is given a new transaction will be created.
#
# Does
# * sets the neo property 'classname' to self.class.to_s
# * creates a neo node java object (in @internal_node)
#
#
# :api: public
def initialize(*args)
# was a neo java node provided ?
if args.length == 1 and args[0].kind_of?(org.neo4j.api.core.Node)
Expand All @@ -43,19 +44,19 @@ def initialize(*args)
super()
end

#

# Inits this node with the specified java neo node
#
# :api: private
def init_with_node(node)
@internal_node = node
self.classname = self.class.to_s unless @internal_node.hasProperty("classname")
$NEO_LOGGER.debug {"loading node '#{self.class.to_s}' node id #{@internal_node.getId()}"}
end


#
# Inits when no neo java node exists. Must create a new neo java node first.
#
# :api: private
def init_without_node
@internal_node = Neo4j.instance.create_node
self.classname = self.class.to_s
Expand Down Expand Up @@ -236,47 +237,47 @@ def lucene_index
self.class.lucene_index
end

#
# Deletes this node.
# Invoking any methods on this node after delete() has returned is invalid and may lead to unspecified behavior.
# Runs in a new transaction if one is not already running.
#
# :api: public
def delete
self.class.fire_event(NodeDeletedEvent.new(self))
relations.each {|r| r.delete}
@internal_node.delete
lucene_index.delete(neo_node_id)
end


# :api: private
def classname
get_property('classname')
end


# :api: private
def classname=(value)
set_property('classname', value)
end

#

# Returns a relation traverser for traversing all types of relation from and to this node
# @see Neo4j::Relations::RelationTraverser
#
# :api: public
def relations
Relations::RelationTraverser.new(@internal_node)
end

#
# Mark this node to be reindex by lucene after the transaction finishes
#
# @api private
def reindex
Transaction.current.reindex(self)
end

#
# Reindex this node now
#
# @api private
#
def reindex!
doc = {:id => neo_node_id }
self.class.index_updaters.each_value do |updater|
Expand Down Expand Up @@ -458,11 +459,18 @@ def value_object
@value_class ||= create_value_class
end

# Index a property a relationship.
# Index a property or a relationship.
# If the rel_prop arg contains a '.' then it will index the relationship.
# For example "friends.name" will index each node with property name in the relationship friends.
# For example "name" will index the name property of this NodeMixin class.
#
# ==== Example
# class Person
# include Neo4j::NodeMixin
# property :name
# index :name
# end
#
# :api: public
def index(*rel_type_props)
if rel_type_props.size == 2 and rel_type_props[1].kind_of?(Hash)
Expand Down Expand Up @@ -523,7 +531,7 @@ def index_relation(index_key, rel_type, prop)

type = relations_info[rel_type.to_sym][:type] # this or the other node we index ?
rel_type = type.to_sym unless type.nil?

# updater - called when index needs to be updated
updater = lambda do |my_node, doc|
values = []
Expand Down
11 changes: 5 additions & 6 deletions lib/neo4j/transaction.rb
Expand Up @@ -167,18 +167,17 @@ def placebo
# upon invocation of finish() unless failure() has or will be invoked before then.
#
# :api: public
#
def success
raise NotInTransactionError.new unless Transaction.running?
$NEO_LOGGER.info{"success #{self.to_s}"}
@neo_tx.success
end


# Commits or marks this transaction for rollback, depending on whether success() or failure() has been previously invoked.
# Commits or marks this transaction for rollback, depending on whether
# success() or failure() has been previously invoked.
#
# :api: public
#
def finish
raise NotInTransactionError.new unless Transaction.running?
unless failure?
Expand All @@ -204,8 +203,8 @@ def finish
$NEO_LOGGER.info{"finished #{self.to_s}"}
end

# Marks this transaction as failed, which means that it will inexplicably
# be rolled back upon invocation of finish().
# Marks this transaction as failed, which means that it will inexplicably
# be rolled back upon invocation of finish().
#
# :api: public
def failure
Expand All @@ -215,9 +214,9 @@ def failure
$NEO_LOGGER.info{"failure #{self.to_s}"}
end

#
# Marks a node to be reindexed before the transaction ends
#
# :api: private
def reindex(node)
@nodes_to_be_reindexed[node.neo_node_id] = node
end
Expand Down
15 changes: 15 additions & 0 deletions test/lucene/index_spec.rb
Expand Up @@ -444,6 +444,21 @@
setup_lucene
@index = Index.new('myindex')
end

it "should remove the field if set to nil" do
# given
@index << {:id => 'a', :name=>'andreas'}
@index.commit
@index.find(:name => 'andreas').size.should == 1

# when
@index << {:id => 'a', :name=>nil}
@index.commit

# then
@index.find(:name => 'andreas').size.should == 0
end


it "should not find the old field if the field has been changed" do
# given
Expand Down
19 changes: 16 additions & 3 deletions test/neo4j/node_lucene_spec.rb
Expand Up @@ -336,21 +336,34 @@ class TestNode
end

describe "Find Nodes using Lucene date index" do
before(:all) do
before(:each) do
undefine_class :PersonNode
start
class PersonNode
include Neo4j::NodeMixin
properties :name, :born
property :name
property :born, :type => Date
index :name
index :born, :type => Date
end
end

after(:all) do
after(:each) do
stop
end

it "should find using a date query" do
result = PersonNode.find("born:[20080427 TO 20100203]")
result.size.should == 0
node = PersonNode.new
node.born.should be_nil
node.name = 'kalle'
node.born = Date.new 2008,05,06

# when
result = PersonNode.find("born:[20080427 TO 20100203]")
result.size.should == 1
end
end
end

0 comments on commit 899925e

Please sign in to comment.