Object
This is a simplified interface to the index. See the TUTORIAL for more information on how to use this class.
If you create an Index without any options, it’ll simply create an index in memory. But this class is highly configurable and every option that you can supply to IndexWriter and QueryParser, you can also set here. Please look at the options for the constructors to these classes.
See;
default_input_field | Default: “id”. This specifies the default field that will be used when you add a simple string to the index using # or <<. |
id_field | Default: “id”. This field is as the field to search when doing searches on a term. For example, if you do a lookup by term “cat”, ie index[“cat”], this will be the field that is searched. |
key | Default: nil. Expert: This should only be used if you really know what you are doing. Basically you can set a field or an array of fields to be the key for the index. So if you add a document with a same key as an existing document, the existing document will be replaced by the new object. Using a multiple field key will slow down indexing so it should not be done if performance is a concern. A single field key (or id) should be find however. Also, you must make sure that your key/keys are either untokenized or that they are not broken up by the analyzer. |
auto_flush | Default: false. Set this option to true if you want the index automatically flushed every time you do a write (includes delete) to the index. This is useful if you have multiple processes accessing the index and you don’t want lock errors. Setting :auto_flush to true has a huge performance impact so don’t use it if you are concerned about performance. In that case you should think about setting up a DRb indexing service. |
lock_retry_time | Default: 2 seconds. This parameter specifies how long to wait before retrying to obtain the commit lock when detecting if the IndexReader is at the latest version. |
close_dir | Default: false. If you explicitly pass a Directory object to this class and you want Index to close it when it is closed itself then set this to true. |
use_typed_range_query | Default: true. Use TypedRangeQuery instead of the standard RangeQuery when parsing range queries. This is useful if you have number fields which you want to perform range queries on. You won’t need to pad or normalize the data in the field in anyway to get correct results. However, performance will be a lot slower for large indexes, hence the default. |
index = Index::Index.new(:analyzer => WhiteSpaceAnalyzer.new()) index = Index::Index.new(:path => '/path/to/index', :create_if_missing => false, :auto_flush => true) index = Index::Index.new(:dir => directory, :default_slop => 2, :handle_parse_errors => false)
You can also pass a block if you like. The index will be yielded and closed at the index of the box. For example;
Ferret::I.new() do |index| # do stuff with index. Most of your actions will be cached. end
# File lib/ferret/index.rb, line 91 91: def initialize(options = {}, &block) 92: super() 93: 94: if options[:key] 95: @key = options[:key] 96: if @key.is_a?(Array) 97: @key.flatten.map {|k| k.to_s.intern} 98: end 99: else 100: @key = nil 101: end 102: 103: if (fi = options[:field_infos]).is_a?(String) 104: options[:field_infos] = FieldInfos.load(fi) 105: end 106: 107: @close_dir = options[:close_dir] 108: if options[:dir].is_a?(String) 109: options[:path] = options[:dir] 110: end 111: if options[:path] 112: @close_dir = true 113: begin 114: @dir = FSDirectory.new(options[:path], options[:create]) 115: rescue IOError => io 116: @dir = FSDirectory.new(options[:path], 117: options[:create_if_missing] != false) 118: end 119: elsif options[:dir] 120: @dir = options[:dir] 121: else 122: options[:create] = true # this should always be true for a new RAMDir 123: @close_dir = true 124: @dir = RAMDirectory.new 125: end 126: 127: @dir.extend(MonitorMixin) unless @dir.kind_of? MonitorMixin 128: options[:dir] = @dir 129: options[:lock_retry_time]||= 2 130: @options = options 131: if (!@dir.exists?("segments")) || options[:create] 132: IndexWriter.new(options).close 133: end 134: options[:analyzer]||= Ferret::Analysis::StandardAnalyzer.new 135: if options[:use_typed_range_query].nil? 136: options[:use_typed_range_query] = true 137: end 138: 139: @searcher = nil 140: @writer = nil 141: @reader = nil 142: 143: @options.delete(:create) # only create the first time if at all 144: @auto_flush = @options[:auto_flush] || false 145: if (@options[:id_field].nil? and @key.is_a?(Symbol)) 146: @id_field = @key 147: else 148: @id_field = @options[:id_field] || :id 149: end 150: @default_field = (@options[:default_field]||= :*) 151: @default_input_field = options[:default_input_field] || @id_field 152: 153: if @default_input_field.respond_to?(:intern) 154: @default_input_field = @default_input_field.intern 155: end 156: @open = true 157: @qp = nil 158: if block 159: yield self 160: self.close 161: end 162: end
Adds a document to this index, using the provided analyzer instead of the local analyzer if provided. If the document contains more than IndexWriter::MAX_FIELD_LENGTH terms for a given field, the remainder are discarded.
There are three ways to add a document to the index. To add a document you can simply add a string or an array of strings. This will store all the strings in the “” (ie empty string) field (unless you specify the default_field when you create the index).
index << "This is a new document to be indexed" index << ["And here", "is another", "new document", "to be indexed"]
But these are pretty simple documents. If this is all you want to index you could probably just use SimpleSearch. So let’s give our documents some fields;
index << {:title => "Programming Ruby", :content => "blah blah blah"} index << {:title => "Programming Ruby", :content => "yada yada yada"}
Or if you are indexing data stored in a database, you’ll probably want to store the id;
index << {:id => row.id, :title => row.title, :date => row.date}
See FieldInfos for more information on how to set field properties.
# File lib/ferret/index.rb, line 263 263: def add_document(doc, analyzer = nil) 264: @dir.synchronize do 265: ensure_writer_open() 266: if doc.is_a?(String) or doc.is_a?(Array) 267: doc = {@default_input_field => doc} 268: end 269: 270: # delete existing documents with the same key 271: if @key 272: if @key.is_a?(Array) 273: query = @key.inject(BooleanQuery.new()) do |bq, field| 274: bq.add_query(TermQuery.new(field, doc[field].to_s), :must) 275: bq 276: end 277: query_delete(query) 278: else 279: id = doc[@key].to_s 280: if id 281: @writer.delete(@key, id) 282: end 283: end 284: end 285: ensure_writer_open() 286: 287: if analyzer 288: old_analyzer = @writer.analyzer 289: @writer.analyzer = analyzer 290: @writer.add_document(doc) 291: @writer.analyzer = old_analyzer 292: else 293: @writer.add_document(doc) 294: end 295: 296: flush() if @auto_flush 297: end 298: end
Merges all segments from an index or an array of indexes into this index. You can pass a single Index::Index, Index::Reader, Store::Directory or an array of any single one of these.
This may be used to parallelize batch indexing. A large document collection can be broken into sub-collections. Each sub-collection can be indexed in parallel, on a different thread, process or machine and perhaps all in memory. The complete index can then be created by merging sub-collection indexes with this method.
After this completes, the index is optimized.
# File lib/ferret/index.rb, line 757 757: def add_indexes(indexes) 758: @dir.synchronize do 759: ensure_writer_open() 760: indexes = [indexes].flatten # make sure we have an array 761: return if indexes.size == 0 # nothing to do 762: if indexes[0].is_a?(Index) 763: indexes.delete(self) # don't merge with self 764: indexes = indexes.map {|index| index.reader } 765: elsif indexes[0].is_a?(Ferret::Store::Directory) 766: indexes.delete(@dir) # don't merge with self 767: indexes = indexes.map {|dir| IndexReader.new(dir) } 768: elsif indexes[0].is_a?(IndexReader) 769: indexes.delete(@reader) # don't merge with self 770: else 771: raise ArgumentError, "Unknown index type when trying to merge indexes" 772: end 773: ensure_writer_open 774: @writer.add_readers(indexes) 775: end 776: end
Batch updates the documents in an index. You can pass either a Hash or an Array.
If you pass an Array then each value needs to be a Document or a Hash and each of those documents must have an :id_field which will be used to delete the old document that this document is replacing.
If you pass a Hash then the keys of the Hash will be considered the id’s and the values will be the new documents to replace the old ones with.If the id is an Integer then it is considered a Ferret document number and the corresponding document will be deleted. If the id is a String or a Symbol then the id will be considered a term and the documents that contain that term in the :id_field will be deleted.
Note: No error will be raised if the document does not currently exist. A new document will simply be created.
# will replace the documents with the +id+'s id:133 and id:254 @index.batch_update({ '133' => {:id => '133', :content => 'yada yada yada'}, '253' => {:id => '253', :content => 'bla bla bal'} }) # will replace the documents with the Ferret Document numbers 2 and 92 @index.batch_update({ 2 => {:id => '133', :content => 'yada yada yada'}, 92 => {:id => '253', :content => 'bla bla bal'} }) # will replace the documents with the +id+'s id:133 and id:254 # this is recommended as it guarantees no duplicate keys @index.batch_update([ {:id => '133', :content => 'yada yada yada'}, {:id => '253', :content => 'bla bla bal'} ])
docs | A Hash of id/document pairs. The set of documents to be updated |
# File lib/ferret/index.rb, line 626 626: def batch_update(docs) 627: @dir.synchronize do 628: ids = values = nil 629: case docs 630: when Array 631: ids = docs.collect{|doc| doc[@id_field].to_s} 632: if ids.include?(nil) 633: raise ArgumentError, "all documents must have an #{@id_field} " 634: "field when doing a batch update" 635: end 636: when Hash 637: ids = docs.keys 638: docs = docs.values 639: else 640: raise ArgumentError, "must pass Hash or Array, not #{docs.class}" 641: end 642: batch_delete(ids) 643: ensure_writer_open() 644: docs.each {|new_doc| @writer << new_doc } 645: flush() 646: end 647: end
Closes this index by closing its associated reader and writer objects.
# File lib/ferret/index.rb, line 202 202: def close 203: @dir.synchronize do 204: if not @open 205: raise(StandardError, "tried to close an already closed directory") 206: end 207: @searcher.close() if @searcher 208: @reader.close() if @reader 209: @writer.close() if @writer 210: @dir.close() if @close_dir 211: 212: @open = false 213: end 214: end
Deletes a document/documents from the index. The method for determining the document to delete depends on the type of the argument passed.
If arg is an Integer then delete the document based on the internal document number. Will raise an error if the document does not exist.
If arg is a String then search for the documents with arg in the id field. The id field is either :id or whatever you set :id_field parameter to when you create the Index object. Will fail quietly if the no document exists.
If arg is a Hash or an Array then a batch delete will be performed. If arg is an Array then it will be considered an array of id’s. If it is a Hash, then its keys will be used instead as the Array of document id’s. If the id is an Integer then it is considered a Ferret document number and the corresponding document will be deleted. If the id is a String or a Symbol then the id will be considered a term and the documents that contain that term in the :id_field will be deleted.
# File lib/ferret/index.rb, line 517 517: def delete(arg) 518: @dir.synchronize do 519: if arg.is_a?(String) or arg.is_a?(Symbol) 520: ensure_writer_open() 521: @writer.delete(@id_field, arg.to_s) 522: elsif arg.is_a?(Integer) 523: ensure_reader_open() 524: cnt = @reader.delete(arg) 525: elsif arg.is_a?(Hash) or arg.is_a?(Array) 526: batch_delete(arg) 527: else 528: raise ArgumentError, "Cannot delete for arg of type #{arg.class}" 529: end 530: flush() if @auto_flush 531: end 532: return self 533: end
Returns true if document n has been deleted
# File lib/ferret/index.rb, line 553 553: def deleted?(n) 554: @dir.synchronize do 555: ensure_reader_open() 556: return @reader.deleted?(n) 557: end 558: end
Retrieves a document/documents from the index. The method for retrieval depends on the type of the argument passed.
If arg is an Integer then return the document based on the internal document number.
If arg is a Range, then return the documents within the range based on internal document number.
If arg is a String then search for the first document with arg in the id field. The id field is either :id or whatever you set :id_field parameter to when you create the Index object.
# File lib/ferret/index.rb, line 451 451: def doc(*arg) 452: @dir.synchronize do 453: id = arg[0] 454: if id.kind_of?(String) or id.kind_of?(Symbol) 455: ensure_reader_open() 456: term_doc_enum = @reader.term_docs_for(@id_field, id.to_s) 457: return term_doc_enum.next? ? @reader[term_doc_enum.doc] : nil 458: else 459: ensure_reader_open(false) 460: return @reader[*arg] 461: end 462: end 463: end
iterate through all documents in the index. This method preloads the documents so you don’t need to call # on the document to load all the fields.
# File lib/ferret/index.rb, line 489 489: def each 490: @dir.synchronize do 491: ensure_reader_open 492: (0...@reader.max_doc).each do |i| 493: yield @reader[i].load unless @reader.deleted?(i) 494: end 495: end 496: end
Returns an Explanation that describes how doc scored against query.
This is intended to be used in developing Similarity implementations, and, for good performance, should not be displayed with every hit. Computing an explanation is as expensive as executing the query over the entire index.
# File lib/ferret/index.rb, line 823 823: def explain(query, doc) 824: @dir.synchronize do 825: ensure_searcher_open() 826: query = do_process_query(query) 827: 828: return @searcher.explain(query, doc) 829: end 830: end
Returns the field_infos object so that you can add new fields to the index.
# File lib/ferret/index.rb, line 842 842: def field_infos 843: @dir.synchronize do 844: ensure_writer_open() 845: return @writer.field_infos 846: end 847: end
Flushes all writes to the index. This will not optimize the index but it will make sure that all writes are written to it.
NOTE: this is not necessary if you are only using this class. All writes will automatically flush when you perform an operation that reads the index.
# File lib/ferret/index.rb, line 711 711: def flush() 712: @dir.synchronize do 713: if @reader 714: if @searcher 715: @searcher.close 716: @searcher = nil 717: end 718: @reader.commit 719: elsif @writer 720: @writer.close 721: @writer = nil 722: end 723: end 724: end
Returns true if any documents have been deleted since the index was last flushed.
# File lib/ferret/index.rb, line 698 698: def has_deletions?() 699: @dir.synchronize do 700: ensure_reader_open() 701: return @reader.has_deletions? 702: end 703: end
Returns an array of strings with the matches highlighted. The query can either a query String or a Ferret::Search::Query object. The doc_id is the id of the document you want to highlight (usually returned by the search methods). There are also a number of options you can pass;
field | Default: @options[:default_field]. The default_field is the field that is usually highlighted but you can specify which field you want to highlight here. If you want to highlight multiple fields then you will need to call this method multiple times. |
excerpt_length | Default: 150. Length of excerpt to show. Highlighted terms will be in the centre of the excerpt. Set to :all to highlight the entire field. |
num_excerpts | Default: 2. Number of excerpts to return. |
pre_tag | Default: “”. Tag to place to the left of the match. You’ll probably want to change this to a “” tag with a class. Try “033[36m” for use in a terminal. |
post_tag | Default: “”. This tag should close the :pre_tag. Try tag “033[m” in the terminal. |
ellipsis | Default: “…”. This is the string that is appended at the beginning and end of excerpts (unless the excerpt hits the start or end of the field. Alternatively you may want to use the HTML entity … or the UTF-8 string “342200246”. |
# File lib/ferret/index.rb, line 191 191: def highlight(query, doc_id, options = {}) 192: @dir.synchronize do 193: ensure_searcher_open() 194: @searcher.highlight(do_process_query(query), 195: doc_id, 196: options[:field]||@options[:default_field], 197: options) 198: end 199: end
optimizes the index. This should only be called when the index will no longer be updated very often, but will be read a lot.
# File lib/ferret/index.rb, line 729 729: def optimize() 730: @dir.synchronize do 731: ensure_writer_open() 732: @writer.optimize() 733: @writer.close() 734: @writer = nil 735: end 736: end
This is a simple utility method for saving an in memory or RAM index to the file system. The same thing can be achieved by using the Index::Index#add_indexes method and you will have more options when creating the new index, however this is a simple way to turn a RAM index into a file system index.
directory | This can either be a Store::Directory object or a String representing the path to the directory where you would like to store the index. |
create | True if you’d like to create the directory if it doesn’t exist or copy over an existing directory. False if you’d like to merge with the existing directory. This defaults to false. |
# File lib/ferret/index.rb, line 792 792: def persist(directory, create = true) 793: synchronize do 794: close_all() 795: old_dir = @dir 796: if directory.is_a?(String) 797: @dir = FSDirectory.new(directory, create) 798: elsif directory.is_a?(Ferret::Store::Directory) 799: @dir = directory 800: end 801: @dir.extend(MonitorMixin) unless @dir.kind_of? MonitorMixin 802: @options[:dir] = @dir 803: @options[:create_if_missing] = true 804: add_indexes([old_dir]) 805: end 806: end
Turn a query string into a Query object with the Index’s QueryParser
# File lib/ferret/index.rb, line 833 833: def process_query(query) 834: @dir.synchronize do 835: ensure_searcher_open() 836: return do_process_query(query) 837: end 838: end
Delete all documents returned by the query.
query | The query to find documents you wish to delete. Can either be a string (in which case it is parsed by the standard query parser) or an actual query object. |
# File lib/ferret/index.rb, line 540 540: def query_delete(query) 541: @dir.synchronize do 542: ensure_writer_open() 543: ensure_searcher_open() 544: query = do_process_query(query) 545: @searcher.search_each(query, :limit => :all) do |doc, score| 546: @reader.delete(doc) 547: end 548: flush() if @auto_flush 549: end 550: end
Update all the documents returned by the query.
query | The query to find documents you wish to update. Can either be a string (in which case it is parsed by the standard query parser) or an actual query object. |
new_val | The values we are updating. This can be a string in which case the default field is updated, or it can be a hash, in which case, all fields in the hash are merged into the old hash. That is, the old fields are replaced by values in the new hash if they exist. |
index << {:id => "26", :title => "Babylon", :artist => "David Grey"} index << {:id => "29", :title => "My Oh My", :artist => "David Grey"} # correct index.query_update('artist:"David Grey"', {:artist => "David Gray"}) index["26"] #=> {:id => "26", :title => "Babylon", :artist => "David Gray"} index["28"] #=> {:id => "28", :title => "My Oh My", :artist => "David Gray"}
# File lib/ferret/index.rb, line 674 674: def query_update(query, new_val) 675: @dir.synchronize do 676: ensure_writer_open() 677: ensure_searcher_open() 678: docs_to_add = [] 679: query = do_process_query(query) 680: @searcher.search_each(query, :limit => :all) do |id, score| 681: document = @searcher[id].load 682: if new_val.is_a?(Hash) 683: document.merge!(new_val) 684: else new_val.is_a?(String) or new_val.is_a?(Symbol) 685: document[@default_input_field] = new_val.to_s 686: end 687: docs_to_add << document 688: @reader.delete(id) 689: end 690: ensure_writer_open() 691: docs_to_add.each {|doc| @writer << doc } 692: flush() if @auto_flush 693: end 694: end
Get the reader for this index.
NOTE | This will close the writer from this index. |
# File lib/ferret/index.rb, line 218 218: def reader 219: ensure_reader_open() 220: return @reader 221: end
Run a query through the Searcher on the index, ignoring scoring and starting at :start_doc and stopping when :limit matches have been found. It returns an array of the matching document numbers.
There is a big performance advange when using this search method on a very large index when there are potentially thousands of matching documents and you only want say 50 of them. The other search methods need to look at every single match to decide which one has the highest score. This search method just needs to find :limit number of matches before it returns.
start_doc | Default: 0. The start document to start the search from. NOTE very carefully that this is not the same as the :offset parameter used in the other search methods which refers to the offset in the result-set. This is the document to start the scan from. So if you scanning through the index in increments of 50 documents at a time you need to use the last matched doc in the previous search to start your next search. See the example below. |
limit | Default: 50. This is the number of results you want returned, also called the page size. Set :limit to :all to return all results. |
TODO: add option to return loaded documents instead
start_doc = 0 begin results = @searcher.scan(query, :start_doc => start_doc) yield results # or do something with them start_doc = results.last # start_doc will be nil now if results is empty, ie no more matches end while start_doc
# File lib/ferret/index.rb, line 430 430: def scan(query, options = {}) 431: @dir.synchronize do 432: ensure_searcher_open() 433: query = do_process_query(query) 434: 435: @searcher.scan(query, options) 436: end 437: end
Run a query through the Searcher on the index. A TopDocs object is returned with the relevant results. The query is a built in Query object or a query string that can be parsed by the Ferret::QueryParser. Here are the options;
offset | Default: 0. The offset of the start of the section of the result-set to return. This is used for paging through results. Let’s say you have a page size of 10. If you don’t find the result you want among the first 10 results then set :offset to 10 and look at the next 10 results, then 20 and so on. |
limit | Default: 10. This is the number of results you want returned, also called the page size. Set :limit to :all to return all results |
sort | A Sort object or sort string describing how the field should be sorted. A sort string is made up of field names which cannot contain spaces and the word “DESC” if you want the field reversed, all separated by commas. For example; “rating DESC, author, title”. Note that Ferret will try to determine a field’s type by looking at the first term in the index and seeing if it can be parsed as an integer or a float. Keep this in mind as you may need to specify a fields type to sort it correctly. For more on this, see the documentation for SortField |
filter | a Filter object to filter the search results with |
filter_proc | a filter Proc is a Proc which takes the doc_id, the score and the Searcher object as its parameters and returns a Boolean value specifying whether the result should be included in the result set. |
# File lib/ferret/index.rb, line 332 332: def search(query, options = {}) 333: @dir.synchronize do 334: return do_search(query, options) 335: end 336: end
Run a query through the Searcher on the index. A TopDocs object is returned with the relevant results. The query is a Query object or a query string that can be validly parsed by the Ferret::QueryParser. The Searcher#search_each method yields the internal document id (used to reference documents in the Searcher object like this; +searcher[doc_id]+) and the search score for that document. It is possible for the score to be greater than 1.0 for some queries and taking boosts into account. This method will also normalize scores to the range 0.0..1.0 when the max-score is greater than 1.0. Here are the options;
offset | Default: 0. The offset of the start of the section of the result-set to return. This is used for paging through results. Let’s say you have a page size of 10. If you don’t find the result you want among the first 10 results then set :offset to 10 and look at the next 10 results, then 20 and so on. |
limit | Default: 10. This is the number of results you want returned, also called the page size. Set :limit to :all to return all results |
sort | A Sort object or sort string describing how the field should be sorted. A sort string is made up of field names which cannot contain spaces and the word “DESC” if you want the field reversed, all separated by commas. For example; “rating DESC, author, title”. Note that Ferret will try to determine a field’s type by looking at the first term in the index and seeing if it can be parsed as an integer or a float. Keep this in mind as you may need to specify a fields type to sort it correctly. For more on this, see the documentation for SortField |
filter | a Filter object to filter the search results with |
filter_proc | a filter Proc is a Proc which takes the doc_id, the score and the Searcher object as its parameters and returns a Boolean value specifying whether the result should be included in the result set. |
returns | The total number of hits. |
eg.
index.search_each(query, options = {}) do |doc, score| puts "hit document number #{doc} with a score of #{score}" end
# File lib/ferret/index.rb, line 384 384: def search_each(query, options = {}) # :yield: doc, score 385: @dir.synchronize do 386: ensure_searcher_open() 387: query = do_process_query(query) 388: 389: @searcher.search_each(query, options) do |doc, score| 390: yield doc, score 391: end 392: end 393: end
Get the searcher for this index.
NOTE | This will close the writer from this index. |
# File lib/ferret/index.rb, line 225 225: def searcher 226: ensure_searcher_open() 227: return @searcher 228: end
returns the number of documents in the index
# File lib/ferret/index.rb, line 739 739: def size() 740: @dir.synchronize do 741: ensure_reader_open() 742: return @reader.num_docs() 743: end 744: end
Retrieves the term_vector for a document. The document can be referenced by either a string id to match the id field or an integer corresponding to Ferret’s document number.
See Ferret::Index::IndexReader#term_vector
# File lib/ferret/index.rb, line 471 471: def term_vector(id, field) 472: @dir.synchronize do 473: ensure_reader_open() 474: if id.kind_of?(String) or id.kind_of?(Symbol) 475: term_doc_enum = @reader.term_docs_for(@id_field, id.to_s) 476: if term_doc_enum.next? 477: id = term_doc_enum.doc 478: else 479: return nil 480: end 481: end 482: return @reader.term_vector(id, field) 483: end 484: end
# File lib/ferret/index.rb, line 808 808: def to_s 809: buf = "" 810: (0...(size)).each do |i| 811: buf << self[i].to_s + "\n" if not deleted?(i) 812: end 813: buf 814: end
Update the document referenced by the document number id if id is an integer or all of the documents which have the term id if id is a term.. For batch update of set of documents, for performance reasons, see batch_update
id | The number of the document to update. Can also be a string representing the value in the id field. Also consider using the :key attribute. |
new_doc | The document to replace the old document with |
# File lib/ferret/index.rb, line 569 569: def update(id, new_doc) 570: @dir.synchronize do 571: ensure_writer_open() 572: delete(id) 573: if id.is_a?(String) or id.is_a?(Symbol) 574: @writer.commit 575: else 576: ensure_writer_open() 577: end 578: @writer << new_doc 579: flush() if @auto_flush 580: end 581: end
returns the new reader if one is opened
# File lib/ferret/index.rb, line 864 864: def ensure_reader_open(get_latest = true) 865: raise "tried to use a closed index" if not @open 866: if @reader 867: if get_latest 868: latest = false 869: begin 870: latest = @reader.latest? 871: rescue Lock::LockError => le 872: sleep(@options[:lock_retry_time]) # sleep for 2 seconds and try again 873: latest = @reader.latest? 874: end 875: if not latest 876: @searcher.close if @searcher 877: @reader.close 878: return @reader = IndexReader.new(@dir) 879: end 880: end 881: else 882: if @writer 883: @writer.close 884: @writer = nil 885: end 886: return @reader = IndexReader.new(@dir) 887: end 888: return false 889: end
# File lib/ferret/index.rb, line 891 891: def ensure_searcher_open() 892: raise "tried to use a closed index" if not @open 893: if ensure_reader_open() or not @searcher 894: @searcher = Searcher.new(@reader) 895: end 896: end
# File lib/ferret/index.rb, line 851 851: def ensure_writer_open() 852: raise "tried to use a closed index" if not @open 853: return if @writer 854: if @reader 855: @searcher.close if @searcher 856: @reader.close 857: @reader = nil 858: @searcher = nil 859: end 860: @writer = IndexWriter.new(@options) 861: end
If docs is a Hash or an Array then a batch delete will be performed. If docs is an Array then it will be considered an array of id’s. If it is a Hash, then its keys will be used instead as the Array of document id’s. If the id is an Integers then it is considered a Ferret document number and the corresponding document will be deleted. If the id is a String or a Symbol then the id will be considered a term and the documents that contain that term in the :id_field will be deleted.
docs | An Array of docs to be deleted, or a Hash (in which case the keys |
are used)
# File lib/ferret/index.rb, line 943 943: def batch_delete(docs) 944: docs = docs.keys if docs.is_a?(Hash) 945: raise ArgumentError, "must pass Array or Hash" unless docs.is_a? Array 946: ids = [] 947: terms = [] 948: docs.each do |doc| 949: case doc 950: when String then terms << doc 951: when Symbol then terms << doc.to_s 952: when Integer then ids << doc 953: else 954: raise ArgumentError, "Cannot delete for arg of type #{id.class}" 955: end 956: end 957: if ids.size > 0 958: ensure_reader_open 959: ids.each {|id| @reader.delete(id)} 960: end 961: if terms.size > 0 962: ensure_writer_open() 963: @writer.delete(@id_field, terms) 964: end 965: return self 966: end
# File lib/ferret/index.rb, line 921 921: def close_all() 922: @dir.synchronize do 923: @searcher.close if @searcher 924: @reader.close if @reader 925: @writer.close if @writer 926: @reader = nil 927: @searcher = nil 928: @writer = nil 929: end 930: end
# File lib/ferret/index.rb, line 899 899: def do_process_query(query) 900: if query.is_a?(String) 901: if @qp.nil? 902: @qp = Ferret::QueryParser.new(@options) 903: end 904: # we need to set this every time, in case a new field has been added 905: @qp.fields = 906: @reader.fields unless options[:all_fields] || options[:fields] 907: @qp.tokenized_fields = 908: @reader.tokenized_fields unless options[:tokenized_fields] 909: query = @qp.parse(query) 910: end 911: return query 912: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.