adding some strings
[moodle-linuxchix.git] / search / Zend / Search / Lucene.php
blob1f15c9a0ba12239e247a3ac1cc48284ccb449115
1 <?php
2 /**
3 * Zend Framework
5 * LICENSE
7 * This source file is subject to the new BSD license that is bundled
8 * with this package in the file LICENSE.txt.
9 * It is also available through the world-wide-web at this URL:
10 * http://framework.zend.com/license/new-bsd
11 * If you did not receive a copy of the license and are unable to
12 * obtain it through the world-wide-web, please send an email
13 * to license@zend.com so we can send you a copy immediately.
15 * @category Zend
16 * @package Zend_Search_Lucene
17 * @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
18 * @license http://framework.zend.com/license/new-bsd New BSD License
22 /** Zend_Search_Lucene_Exception */
23 require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Exception.php';
25 /** Zend_Search_Lucene_Document */
26 require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Document.php';
28 /** Zend_Search_Lucene_Document_Html */
29 require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Document/Html.php';
31 /** Zend_Search_Lucene_Storage_Directory */
32 require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Storage/Directory/Filesystem.php';
34 /** Zend_Search_Lucene_Storage_File_Memory */
35 require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Storage/File/Memory.php';
37 /** Zend_Search_Lucene_Index_Term */
38 require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/Term.php';
40 /** Zend_Search_Lucene_Index_TermInfo */
41 require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/TermInfo.php';
43 /** Zend_Search_Lucene_Index_SegmentInfo */
44 require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/SegmentInfo.php';
46 /** Zend_Search_Lucene_Index_FieldInfo */
47 require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/FieldInfo.php';
49 /** Zend_Search_Lucene_Index_Writer */
50 require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/Writer.php';
52 /** Zend_Search_Lucene_Search_QueryParser */
53 require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryParser.php';
55 /** Zend_Search_Lucene_Search_QueryHit */
56 require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/QueryHit.php';
58 /** Zend_Search_Lucene_Search_Similarity */
59 require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Search/Similarity.php';
61 /** Zend_Search_Lucene_Index_SegmentInfoPriorityQueue */
62 require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Index/SegmentInfoPriorityQueue.php';
65 /** Zend_Search_Lucene_Interface */
66 require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Interface.php';
68 /** Zend_Search_Lucene_Proxy */
69 require_once $CFG->dirroot.'/search/Zend/Search/Lucene/Proxy.php';
72 /**
73 * @category Zend
74 * @package Zend_Search_Lucene
75 * @copyright Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
76 * @license http://framework.zend.com/license/new-bsd New BSD License
78 class Zend_Search_Lucene implements Zend_Search_Lucene_Interface
80 /**
81 * Default field name for search
83 * Null means search through all fields
85 * @var string
87 private static $_defaultSearchField = null;
89 /**
90 * File system adapter.
92 * @var Zend_Search_Lucene_Storage_Directory
94 private $_directory = null;
96 /**
97 * File system adapter closing option
99 * @var boolean
101 private $_closeDirOnExit = true;
104 * Writer for this index, not instantiated unless required.
106 * @var Zend_Search_Lucene_Index_Writer
108 private $_writer = null;
111 * Array of Zend_Search_Lucene_Index_SegmentInfo objects for this index.
113 * @var array Zend_Search_Lucene_Index_SegmentInfo
115 private $_segmentInfos = array();
118 * Number of documents in this index.
120 * @var integer
122 private $_docCount = 0;
125 * Flag for index changes
127 * @var boolean
129 private $_hasChanges = false;
133 * Index lock object
135 * @var Zend_Search_Lucene_Storage_File
137 private $_lock;
140 * Signal, that index is already closed, changes are fixed and resources are cleaned up
142 * @var boolean
144 private $_closed = false;
147 * Number of references to the index object
149 * @var integer
151 private $_refCount = 0;
155 * Create index
157 * @param mixed $directory
158 * @return Zend_Search_Lucene_Interface
160 public static function create($directory)
162 return new Zend_Search_Lucene_Proxy(new Zend_Search_Lucene($directory, true));
166 * Open index
168 * @param mixed $directory
169 * @return Zend_Search_Lucene_Interface
171 public static function open($directory)
173 return new Zend_Search_Lucene_Proxy(new Zend_Search_Lucene($directory, false));
177 * Opens the index.
179 * IndexReader constructor needs Directory as a parameter. It should be
180 * a string with a path to the index folder or a Directory object.
182 * @param mixed $directory
183 * @throws Zend_Search_Lucene_Exception
185 public function __construct($directory = null, $create = false)
187 if ($directory === null) {
188 throw new Zend_Search_Exception('No index directory specified');
191 if ($directory instanceof Zend_Search_Lucene_Storage_Directory_Filesystem) {
192 $this->_directory = $directory;
193 $this->_closeDirOnExit = false;
194 } else {
195 $this->_directory = new Zend_Search_Lucene_Storage_Directory_Filesystem($directory);
196 $this->_closeDirOnExit = true;
200 // Get a shared lock to the index
201 $this->_lock = $this->_directory->createFile('index.lock');
203 $this->_segmentInfos = array();
205 if ($create) {
206 // Throw an exception if index is under processing now
207 if (!$this->_lock->lock(LOCK_EX, true)) {
208 throw new Zend_Search_Lucene_Exception('Can\'t create index. It\'s under processing now');
211 // Writer will create segments file for empty segments list
212 $this->_writer = new Zend_Search_Lucene_Index_Writer($this->_directory, $this->_segmentInfos, true);
214 if (!$this->_lock->lock(LOCK_SH)) {
215 throw new Zend_Search_Lucene_Exception('Can\'t reduce lock level from Exclusive to Shared');
217 } else {
218 // Wait if index is under switching from one set of segments to another (Index_Writer::_updateSegments())
219 if (!$this->_lock->lock(LOCK_SH)) {
220 throw new Zend_Search_Lucene_Exception('Can\'t obtain shared index lock');
222 $this->_writer = null;
226 $segmentsFile = $this->_directory->getFileObject('segments');
228 $format = $segmentsFile->readInt();
230 if ($format != (int)0xFFFFFFFF) {
231 throw new Zend_Search_Lucene_Exception('Wrong segments file format');
234 // read version
235 // $segmentsFile->readLong();
236 $segmentsFile->readInt(); $segmentsFile->readInt();
238 // read segment name counter
239 $segmentsFile->readInt();
241 $segments = $segmentsFile->readInt();
243 $this->_docCount = 0;
245 // read segmentInfos
246 for ($count = 0; $count < $segments; $count++) {
247 $segName = $segmentsFile->readString();
248 $segSize = $segmentsFile->readInt();
249 $this->_docCount += $segSize;
251 $this->_segmentInfos[] =
252 new Zend_Search_Lucene_Index_SegmentInfo($segName,
253 $segSize,
254 $this->_directory);
259 * Close current index and free resources
261 private function _close()
263 if ($this->_closed) {
264 // index is already closed and resources are cleaned up
265 return;
268 $this->commit();
270 // Free shared lock
271 $this->_lock->unlock();
273 if ($this->_closeDirOnExit) {
274 $this->_directory->close();
277 $this->_directory = null;
278 $this->_writer = null;
279 $this->_segmentInfos = null;
281 $this->_closed = true;
285 * Add reference to the index object
287 * @internal
289 public function addReference()
291 $this->_refCount++;
295 * Remove reference from the index object
297 * When reference count becomes zero, index is closed and resources are cleaned up
299 * @internal
301 public function removeReference()
303 $this->_refCount--;
305 if ($this->_refCount == 0) {
306 $this->_close();
311 * Object destructor
313 public function __destruct()
315 $this->_close();
319 * Returns an instance of Zend_Search_Lucene_Index_Writer for the index
321 * @internal
322 * @return Zend_Search_Lucene_Index_Writer
324 public function getIndexWriter()
326 if (!$this->_writer instanceof Zend_Search_Lucene_Index_Writer) {
327 $this->_writer = new Zend_Search_Lucene_Index_Writer($this->_directory, $this->_segmentInfos);
330 return $this->_writer;
335 * Returns the Zend_Search_Lucene_Storage_Directory instance for this index.
337 * @return Zend_Search_Lucene_Storage_Directory
339 public function getDirectory()
341 return $this->_directory;
346 * Returns the total number of documents in this index (including deleted documents).
348 * @return integer
350 public function count()
352 return $this->_docCount;
356 * Returns one greater than the largest possible document number.
357 * This may be used to, e.g., determine how big to allocate a structure which will have
358 * an element for every document number in an index.
360 * @return integer
362 public function maxDoc()
364 return $this->count();
368 * Returns the total number of non-deleted documents in this index.
370 * @return integer
372 public function numDocs()
374 $numDocs = 0;
376 foreach ($this->_segmentInfos as $segmentInfo) {
377 $numDocs += $segmentInfo->numDocs();
380 return $numDocs;
384 * Checks, that document is deleted
386 * @param integer $id
387 * @return boolean
388 * @throws Zend_Search_Lucene_Exception Exception is thrown if $id is out of the range
390 public function isDeleted($id)
392 if ($id >= $this->_docCount) {
393 throw new Zend_Search_Lucene_Exception('Document id is out of the range.');
396 $segmentStartId = 0;
397 foreach ($this->_segmentInfos as $segmentInfo) {
398 if ($segmentStartId + $segmentInfo->count() > $id) {
399 break;
402 $segmentStartId += $segmentInfo->count();
405 return $segmentInfo->isDeleted($id - $segmentStartId);
409 * Set default search field.
411 * Null means, that search is performed through all fields by default
413 * Default value is null
415 * @param string $fieldName
417 public static function setDefaultSearchField($fieldName)
419 self::$_defaultSearchField = $fieldName;
423 * Get default search field.
425 * Null means, that search is performed through all fields by default
427 * @return string
429 public static function getDefaultSearchField()
431 return self::$_defaultSearchField;
435 * Retrieve index maxBufferedDocs option
437 * maxBufferedDocs is a minimal number of documents required before
438 * the buffered in-memory documents are written into a new Segment
440 * Default value is 10
442 * @return integer
444 public function getMaxBufferedDocs()
446 return $this->getIndexWriter()->maxBufferedDocs;
450 * Set index maxBufferedDocs option
452 * maxBufferedDocs is a minimal number of documents required before
453 * the buffered in-memory documents are written into a new Segment
455 * Default value is 10
457 * @param integer $maxBufferedDocs
459 public function setMaxBufferedDocs($maxBufferedDocs)
461 $this->getIndexWriter()->maxBufferedDocs = $maxBufferedDocs;
465 * Retrieve index maxMergeDocs option
467 * maxMergeDocs is a largest number of documents ever merged by addDocument().
468 * Small values (e.g., less than 10,000) are best for interactive indexing,
469 * as this limits the length of pauses while indexing to a few seconds.
470 * Larger values are best for batched indexing and speedier searches.
472 * Default value is PHP_INT_MAX
474 * @return integer
476 public function getMaxMergeDocs()
478 return $this->getIndexWriter()->maxMergeDocs;
482 * Set index maxMergeDocs option
484 * maxMergeDocs is a largest number of documents ever merged by addDocument().
485 * Small values (e.g., less than 10,000) are best for interactive indexing,
486 * as this limits the length of pauses while indexing to a few seconds.
487 * Larger values are best for batched indexing and speedier searches.
489 * Default value is PHP_INT_MAX
491 * @param integer $maxMergeDocs
493 public function setMaxMergeDocs($maxMergeDocs)
495 $this->getIndexWriter()->maxMergeDocs = $maxMergeDocs;
499 * Retrieve index mergeFactor option
501 * mergeFactor determines how often segment indices are merged by addDocument().
502 * With smaller values, less RAM is used while indexing,
503 * and searches on unoptimized indices are faster,
504 * but indexing speed is slower.
505 * With larger values, more RAM is used during indexing,
506 * and while searches on unoptimized indices are slower,
507 * indexing is faster.
508 * Thus larger values (> 10) are best for batch index creation,
509 * and smaller values (< 10) for indices that are interactively maintained.
511 * Default value is 10
513 * @return integer
515 public function getMergeFactor()
517 return $this->getIndexWriter()->mergeFactor;
521 * Set index mergeFactor option
523 * mergeFactor determines how often segment indices are merged by addDocument().
524 * With smaller values, less RAM is used while indexing,
525 * and searches on unoptimized indices are faster,
526 * but indexing speed is slower.
527 * With larger values, more RAM is used during indexing,
528 * and while searches on unoptimized indices are slower,
529 * indexing is faster.
530 * Thus larger values (> 10) are best for batch index creation,
531 * and smaller values (< 10) for indices that are interactively maintained.
533 * Default value is 10
535 * @param integer $maxMergeDocs
537 public function setMergeFactor($mergeFactor)
539 $this->getIndexWriter()->mergeFactor = $mergeFactor;
543 * Performs a query against the index and returns an array
544 * of Zend_Search_Lucene_Search_QueryHit objects.
545 * Input is a string or Zend_Search_Lucene_Search_Query.
547 * @param mixed $query
548 * @return array Zend_Search_Lucene_Search_QueryHit
549 * @throws Zend_Search_Lucene_Exception
551 public function find($query)
553 if (is_string($query)) {
554 $query = Zend_Search_Lucene_Search_QueryParser::parse($query);
557 if (!$query instanceof Zend_Search_Lucene_Search_Query) {
558 throw new Zend_Search_Lucene_Exception('Query must be a string or Zend_Search_Lucene_Search_Query object');
561 $this->commit();
563 $hits = array();
564 $scores = array();
565 $ids = array();
567 $query = $query->rewrite($this)->optimize($this);
569 $query->execute($this);
571 $topScore = 0;
573 foreach ($query->matchedDocs() as $id => $num) {
574 $docScore = $query->score($id, $this);
575 if( $docScore != 0 ) {
576 $hit = new Zend_Search_Lucene_Search_QueryHit($this);
577 $hit->id = $id;
578 $hit->score = $docScore;
580 $hits[] = $hit;
581 $ids[] = $id;
582 $scores[] = $docScore;
584 if ($docScore > $topScore) {
585 $topScore = $docScore;
590 if (count($hits) == 0) {
591 // skip sorting, which may cause a error on empty index
592 return array();
595 if ($topScore > 1) {
596 foreach ($hits as $hit) {
597 $hit->score /= $topScore;
601 if (func_num_args() == 1) {
602 // sort by scores
603 array_multisort($scores, SORT_DESC, SORT_NUMERIC,
604 $ids, SORT_ASC, SORT_NUMERIC,
605 $hits);
606 } else {
607 // sort by given field names
609 $argList = func_get_args();
610 $fieldNames = $this->getFieldNames();
611 $sortArgs = array();
613 for ($count = 1; $count < count($argList); $count++) {
614 $fieldName = $argList[$count];
616 if (!is_string($fieldName)) {
617 throw new Zend_Search_Lucene_Exception('Field name must be a string.');
620 if (!in_array($fieldName, $fieldNames)) {
621 throw new Zend_Search_Lucene_Exception('Wrong field name.');
624 $valuesArray = array();
625 foreach ($hits as $hit) {
626 try {
627 $value = $hit->getDocument()->getFieldValue($fieldName);
628 } catch (Zend_Search_Lucene_Exception $e) {
629 if (strpos($e->getMessage(), 'not found') === false) {
630 throw $e;
631 } else {
632 $value = null;
636 $valuesArray[] = $value;
639 $sortArgs[] = $valuesArray;
641 if ($count + 1 < count($argList) && is_integer($argList[$count+1])) {
642 $count++;
643 $sortArgs[] = $argList[$count];
645 if ($count + 1 < count($argList) && is_integer($argList[$count+1])) {
646 $count++;
647 $sortArgs[] = $argList[$count];
648 } else {
649 if ($argList[$count] == SORT_ASC || $argList[$count] == SORT_DESC) {
650 $sortArgs[] = SORT_REGULAR;
651 } else {
652 $sortArgs[] = SORT_ASC;
655 } else {
656 $sortArgs[] = SORT_ASC;
657 $sortArgs[] = SORT_REGULAR;
661 // Sort by id's if values are equal
662 $sortArgs[] = $ids;
663 $sortArgs[] = SORT_ASC;
664 $sortArgs[] = SORT_NUMERIC;
666 // Array to be sorted
667 $sortArgs[] = &$hits;
669 // Do sort
670 call_user_func_array('array_multisort', $sortArgs);
673 return $hits;
678 * Returns a list of all unique field names that exist in this index.
680 * @param boolean $indexed
681 * @return array
683 public function getFieldNames($indexed = false)
685 $result = array();
686 foreach( $this->_segmentInfos as $segmentInfo ) {
687 $result = array_merge($result, $segmentInfo->getFields($indexed));
689 return $result;
694 * Returns a Zend_Search_Lucene_Document object for the document
695 * number $id in this index.
697 * @param integer|Zend_Search_Lucene_Search_QueryHit $id
698 * @return Zend_Search_Lucene_Document
700 public function getDocument($id)
702 if ($id instanceof Zend_Search_Lucene_Search_QueryHit) {
703 /* @var $id Zend_Search_Lucene_Search_QueryHit */
704 $id = $id->id;
707 if ($id >= $this->_docCount) {
708 throw new Zend_Search_Lucene_Exception('Document id is out of the range.');
711 $segmentStartId = 0;
712 foreach ($this->_segmentInfos as $segmentInfo) {
713 if ($segmentStartId + $segmentInfo->count() > $id) {
714 break;
717 $segmentStartId += $segmentInfo->count();
720 $fdxFile = $segmentInfo->openCompoundFile('.fdx');
721 $fdxFile->seek( ($id-$segmentStartId)*8, SEEK_CUR );
722 $fieldValuesPosition = $fdxFile->readLong();
724 $fdtFile = $segmentInfo->openCompoundFile('.fdt');
725 $fdtFile->seek($fieldValuesPosition, SEEK_CUR);
726 $fieldCount = $fdtFile->readVInt();
728 $doc = new Zend_Search_Lucene_Document();
729 for ($count = 0; $count < $fieldCount; $count++) {
730 $fieldNum = $fdtFile->readVInt();
731 $bits = $fdtFile->readByte();
733 $fieldInfo = $segmentInfo->getField($fieldNum);
735 if (!($bits & 2)) { // Text data
736 $field = new Zend_Search_Lucene_Field($fieldInfo->name,
737 $fdtFile->readString(),
738 'UTF-8',
739 true,
740 $fieldInfo->isIndexed,
741 $bits & 1 );
742 } else { // Binary data
743 $field = new Zend_Search_Lucene_Field($fieldInfo->name,
744 $fdtFile->readBinary(),
746 true,
747 $fieldInfo->isIndexed,
748 $bits & 1,
749 true );
752 $doc->addField($field);
755 return $doc;
760 * Returns true if index contain documents with specified term.
762 * Is used for query optimization.
764 * @param Zend_Search_Lucene_Index_Term $term
765 * @return boolean
767 public function hasTerm(Zend_Search_Lucene_Index_Term $term)
769 foreach ($this->_segmentInfos as $segInfo) {
770 if ($segInfo->getTermInfo($term) instanceof Zend_Search_Lucene_Index_TermInfo) {
771 return true;
775 return false;
779 * Returns IDs of all the documents containing term.
781 * @param Zend_Search_Lucene_Index_Term $term
782 * @return array
784 public function termDocs(Zend_Search_Lucene_Index_Term $term)
786 $result = array();
787 $segmentStartDocId = 0;
789 foreach ($this->_segmentInfos as $segInfo) {
790 $termInfo = $segInfo->getTermInfo($term);
792 if (!$termInfo instanceof Zend_Search_Lucene_Index_TermInfo) {
793 $segmentStartDocId += $segInfo->count();
794 continue;
797 $frqFile = $segInfo->openCompoundFile('.frq');
798 $frqFile->seek($termInfo->freqPointer,SEEK_CUR);
799 $docId = 0;
800 for( $count=0; $count < $termInfo->docFreq; $count++ ) {
801 $docDelta = $frqFile->readVInt();
802 if( $docDelta % 2 == 1 ) {
803 $docId += ($docDelta-1)/2;
804 } else {
805 $docId += $docDelta/2;
806 // read freq
807 $frqFile->readVInt();
810 $result[] = $segmentStartDocId + $docId;
813 $segmentStartDocId += $segInfo->count();
816 return $result;
821 * Returns an array of all term freqs.
822 * Result array structure: array(docId => freq, ...)
824 * @param Zend_Search_Lucene_Index_Term $term
825 * @return integer
827 public function termFreqs(Zend_Search_Lucene_Index_Term $term)
829 $result = array();
830 $segmentStartDocId = 0;
831 foreach ($this->_segmentInfos as $segmentInfo) {
832 $result += $segmentInfo->termFreqs($term, $segmentStartDocId);
834 $segmentStartDocId += $segmentInfo->count();
837 return $result;
841 * Returns an array of all term positions in the documents.
842 * Result array structure: array(docId => array(pos1, pos2, ...), ...)
844 * @param Zend_Search_Lucene_Index_Term $term
845 * @return array
847 public function termPositions(Zend_Search_Lucene_Index_Term $term)
849 $result = array();
850 $segmentStartDocId = 0;
851 foreach ($this->_segmentInfos as $segmentInfo) {
852 $result += $segmentInfo->termPositions($term, $segmentStartDocId);
854 $segmentStartDocId += $segmentInfo->count();
857 return $result;
862 * Returns the number of documents in this index containing the $term.
864 * @param Zend_Search_Lucene_Index_Term $term
865 * @return integer
867 public function docFreq(Zend_Search_Lucene_Index_Term $term)
869 $result = 0;
870 foreach ($this->_segmentInfos as $segInfo) {
871 $termInfo = $segInfo->getTermInfo($term);
872 if ($termInfo !== null) {
873 $result += $termInfo->docFreq;
877 return $result;
882 * Retrive similarity used by index reader
884 * @return Zend_Search_Lucene_Search_Similarity
886 public function getSimilarity()
888 return Zend_Search_Lucene_Search_Similarity::getDefault();
893 * Returns a normalization factor for "field, document" pair.
895 * @param integer $id
896 * @param string $fieldName
897 * @return float
899 public function norm($id, $fieldName)
901 if ($id >= $this->_docCount) {
902 return null;
905 $segmentStartId = 0;
906 foreach ($this->_segmentInfos as $segInfo) {
907 if ($segmentStartId + $segInfo->count() > $id) {
908 break;
911 $segmentStartId += $segInfo->count();
914 if ($segInfo->isDeleted($id - $segmentStartId)) {
915 return 0;
918 return $segInfo->norm($id - $segmentStartId, $fieldName);
922 * Returns true if any documents have been deleted from this index.
924 * @return boolean
926 public function hasDeletions()
928 foreach ($this->_segmentInfos as $segmentInfo) {
929 if ($segmentInfo->hasDeletions()) {
930 return true;
934 return false;
939 * Deletes a document from the index.
940 * $id is an internal document id
942 * @param integer|Zend_Search_Lucene_Search_QueryHit $id
943 * @throws Zend_Search_Lucene_Exception
945 public function delete($id)
947 if ($id instanceof Zend_Search_Lucene_Search_QueryHit) {
948 /* @var $id Zend_Search_Lucene_Search_QueryHit */
949 $id = $id->id;
952 if ($id >= $this->_docCount) {
953 throw new Zend_Search_Lucene_Exception('Document id is out of the range.');
956 $segmentStartId = 0;
957 foreach ($this->_segmentInfos as $segmentInfo) {
958 if ($segmentStartId + $segmentInfo->count() > $id) {
959 break;
962 $segmentStartId += $segmentInfo->count();
964 $segmentInfo->delete($id - $segmentStartId);
966 $this->_hasChanges = true;
972 * Adds a document to this index.
974 * @param Zend_Search_Lucene_Document $document
976 public function addDocument(Zend_Search_Lucene_Document $document)
978 $this->getIndexWriter()->addDocument($document);
979 $this->_docCount++;
984 * Update document counter
986 private function _updateDocCount()
988 $this->_docCount = 0;
989 foreach ($this->_segmentInfos as $segInfo) {
990 $this->_docCount += $segInfo->count();
995 * Commit changes resulting from delete() or undeleteAll() operations.
997 * @todo undeleteAll processing.
999 public function commit()
1001 if ($this->_hasChanges) {
1002 foreach ($this->_segmentInfos as $segInfo) {
1003 $segInfo->writeChanges();
1006 $this->_hasChanges = false;
1009 if ($this->_writer !== null) {
1010 $this->_writer->commit();
1012 $this->_updateDocCount();
1018 * Optimize index.
1020 * Merges all segments into one
1022 public function optimize()
1024 // Commit changes if any changes have been made
1025 $this->commit();
1027 if (count($this->_segmentInfos) > 1 || $this->hasDeletions()) {
1028 $this->getIndexWriter()->optimize();
1029 $this->_updateDocCount();
1035 * Returns an array of all terms in this index.
1037 * @return array
1039 public function terms()
1041 $result = array();
1043 $segmentInfoQueue = new Zend_Search_Lucene_Index_SegmentInfoPriorityQueue();
1045 foreach ($this->_segmentInfos as $segmentInfo) {
1046 $segmentInfo->reset();
1048 // Skip "empty" segments
1049 if ($segmentInfo->currentTerm() !== null) {
1050 $segmentInfoQueue->put($segmentInfo);
1054 while (($segmentInfo = $segmentInfoQueue->pop()) !== null) {
1055 if ($segmentInfoQueue->top() === null ||
1056 $segmentInfoQueue->top()->currentTerm()->key() !=
1057 $segmentInfo->currentTerm()->key()) {
1058 // We got new term
1059 $result[] = $segmentInfo->currentTerm();
1062 $segmentInfo->nextTerm();
1063 // check, if segment dictionary is finished
1064 if ($segmentInfo->currentTerm() !== null) {
1065 // Put segment back into the priority queue
1066 $segmentInfoQueue->put($segmentInfo);
1070 return $result;
1074 /*************************************************************************
1075 @todo UNIMPLEMENTED
1076 *************************************************************************/
1078 * Undeletes all documents currently marked as deleted in this index.
1080 * @todo Implementation
1082 public function undeleteAll()