2012-07-18

CRUD in Lucene 3.6.0

直接看 code...

public class CrudTestCase extends TestCase {

  private static final Version VERSION = Version.LUCENE_36;
  private static final String F_TITLE = "title";
  private Directory directory = new RAMDirectory();
  private IndexWriter writer;
  private IndexReader reader;
  private IndexSearcher searcher;

  @Override
  protected void setUp() throws Exception {
    super.setUp();

    // create index
    this.writer = this.createWriter();
    this.writer.addDocument(this.createDocument(Field.Index.ANALYZED,
        "Lucene in action"));
    this.writer.addDocument(this.createDocument(Field.Index.ANALYZED,
        "Spring in action"));
    this.writer.addDocument(this.createDocument(Field.Index.ANALYZED,
        "Lucene in action, 2e"));
    // 資料太多時,可以分批 commit
    // commit後(沒有close)就可以使用 IndexReader
    this.writer.commit();
    // 沒有 close 或 commit,不能使用 IndexReader
    // this.closeWriter();
  }

  @Override
  protected void tearDown() throws Exception {
    super.tearDown();
    this.closeWriter();
    this.closeSearcher();
  }

  /**
   * 新增
   */
  public void testCreate() {
    System.out.println("testCreate...");
    try {
      assertEquals(3, this.writer.maxDoc()); // 全部的數量,包含已殺與未殺的
      assertEquals(3, this.writer.numDocs()); // 僅包含未殺的
    }
    catch (IOException e) {
      Assert.fail(e.getMessage());
    }
  }

  /**
   * 查詢
   */
  public void testRead() {
    System.out.println("testRead...");
    try {
      // reader
      this.reader = this.createReader();
      assertEquals(3, this.reader.maxDoc()); // 全部的數量,包含已殺與未殺的
      assertEquals(3, this.reader.numDocs()); // 僅包含未殺的
      this.closeReader();

      // search
      assertEquals(2, this.countTerm(new Term(CrudTestCase.F_TITLE, "lucene")));
    }
    catch (IOException e) {
      Assert.fail(e.getMessage());
    }
  }

  /**
   * 刪除
   */
  public void testDelete() {
    System.out.println("testDelete...");
    try {
      this.writer.deleteDocuments(new Term(CrudTestCase.F_TITLE, "spring"));

      // 未 commit 之前筆數不變
      assertTrue(this.writer.hasDeletions());
      assertEquals(3, this.writer.maxDoc()); // 全部的數量,包含已殺與未殺的
      assertEquals(3, this.writer.numDocs()); // 僅包含未殺的

      this.writer.commit();
      assertTrue(this.writer.hasDeletions()); // 還是 true
      assertEquals(3, this.writer.maxDoc()); // 總數量不變
      assertEquals(2, this.writer.numDocs()); // 未殺的少一筆

      this.writer.optimize(); // deprecated 了,不用再 optimize,多檔案查詢的效能已經提昇了
      assertFalse(this.writer.hasDeletions()); // false 了
      assertEquals(2, this.writer.maxDoc()); // 總數量少一筆
      assertEquals(2, this.writer.numDocs());
    }
    catch (IOException e) {
      Assert.fail(e.getMessage());
    }
  }

  /**
   * 更新 - Lucene 沒有所謂的更新,就是先 delete 再 add
   */
  public void testUpdate() {
    System.out.println("testUpdate...");
    try {
      this.writer.updateDocument(new Term(CrudTestCase.F_TITLE, "2e"),
          this.createDocument(Field.Index.ANALYZED,
              "Lucene in action, Second Edition"));
      this.writer.commit();
      assertEquals(0, this.countTerm(new Term(CrudTestCase.F_TITLE, "2e"))); // 殺掉了
      assertEquals(1, this.countTerm(new Term(CrudTestCase.F_TITLE, "second"))); // 新版的
    }
    catch (IOException e) {
      Assert.fail(e.getMessage());
    }
  }

  private int countTerm(Term term) throws CorruptIndexException, IOException {
    this.searcher = this.createSearcher();
    TopDocs results = this.searcher.search(new TermQuery(term), 10);
    return results.totalHits;
  }

  private Document createDocument(Index indexType, String value) {
    Document doc = new Document();
    doc.add(new Field(CrudTestCase.F_TITLE, value, Field.Store.YES, indexType));
    return doc;
  }

  private IndexWriter createWriter() throws CorruptIndexException,
      LockObtainFailedException, IOException {
    IndexWriterConfig config = new IndexWriterConfig(CrudTestCase.VERSION,
        new StandardAnalyzer(CrudTestCase.VERSION));
    config.setOpenMode(OpenMode.CREATE);
    return new IndexWriter(this.directory, config);
  }

  private IndexSearcher createSearcher() throws CorruptIndexException,
      IOException {
    return new IndexSearcher(this.createReader());
  }

  private IndexReader createReader() throws CorruptIndexException, IOException {
    return IndexReader.open(this.directory);
  }

  private void closeWriter() {
    if (this.writer != null) {
      try {
        this.writer.close();
      }
      catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  private void closeSearcher() {
    this.closeReader();
    if (this.searcher != null) {
      try {
        this.searcher.close();
      }
      catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  private void closeReader() {
    if (this.reader != null) {
      try {
        this.reader.close();
      }
      catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
}
---

沒有留言:

張貼留言