Lucene基礎(二)--索引的操做

索引的操做

咱們創建全部就是要達到快速檢索的目的,對數據可以方面便的查找,和數據庫相似,索引也有本身的相關增刪改查的操做。 
在索引的增刪改查中,增刪改屬於寫操做,主要是有IndexWrite提供的方法處理;而查顯而易見,讀操做,使用IndexSeacher 提供的方法來實現。在Lucene的官方文檔找到 org.apache.lucene.index.IndexWriter 這個類,咱們就能夠看到他不少方法。java

建立索引

如同上一章裏面的代碼,建立索引時先創建文件,建立索引的域,再使用IndexWriter的addDocument()方法就能夠了,核心代碼以下:數據庫

iwriter = new IndexWriter(directory, new IndexWriterConfig(version, new StandardAnalyzer(version))); apache

for(String text : content){ doc = new Document();測試

//使用的field 有不少類型,理解他們的區別 例如:TextField 和 StringField等 spa

doc.add(new TextField("content", text,Field.Store.YES)); 索引

iwriter.addDocument(doc); 圖片

}ip

 

索引刪除

索引刪除包括只刪除索引下面的document和刪除索引文件 
在IndexWriter有以下一些方法文檔

  1. deleteAll() 刪除索引中全部的documents
  2. deleteDocuments(Query… queries) 按照提供的Query 刪除documents
  3. deleteDocuments(Term… terms) 按照短語刪除documents
  4. deleteUnusedFiles() 刪除全部再也不使用index的文件
  5. forceMergeDeletes() 刪除處於已經刪除的狀態documents,因而可知,以前的刪除文檔的方法並無真正的刪除掉的documents,只是標記刪除,我我的理解是相似邏輯上的刪除
  6. forceMergeDeletes(boolean doWait) 刪除過程當中指明是否阻塞,直到操做完成

索引更新

更新操做也是同樣,查看文檔就有,這裏截個圖:get

這裏寫圖片描述

索引查詢

Query 
索引查詢的時候可使用Query的實現子類來建立查詢,執行IndexSearcher的search方法來查詢,也可使用QueryParse類來構造查詢.

分頁

  • 方式1:在scoreDoc中進行分頁,數據一次性查出來,在結果集分頁,結果集較大時容易溢出
  • 方式2:使用searcheAfter,等價查詢的次數,可是不會出現查詢結果溢出,推薦,相似數據庫中的分頁查詢

這個相似數據庫中的查詢,能夠對結果集分頁顯示,相似方式一,查詢的時候直接分頁,相似方式二 。

索引操做實例

package lucene_demo03;

import java.io.IOException;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;

/**
*
* 關於索引的查詢(分頁查詢) 方式1:在scoreDoc中進行分頁,數據一次性查出來,在結果集分頁,結果集較大時容易溢出
* 方式2:使用searcheAfter,等價查詢的次數,可是不會出現查詢結果溢出,推薦,相似數據庫中的分頁查詢
*
* @author YipFun
*/
public class LuceneDemo03
{

  private static final Version version = Version.LUCENE_4_9;
  private Directory directory = null;
  private DirectoryReader ireader = null;
  private IndexWriter iwriter = null;

  // 測試數據
  private String[] content = { "hello lucene", "I love coding", "I can play basketball", "I can play football", "I can play dota" };

  /**
  * 構造方法
  */
  public LuceneDemo03()
  {
    directory = new RAMDirectory();
  }

  /**
  * 建立索引
  */
  public void createIndex()
  {
    Document doc = null;
  try
  {
    iwriter = new IndexWriter(directory, new IndexWriterConfig(version, new StandardAnalyzer(version)));
    for (String text : content)
    {
      doc = new Document();
      // 使用的field 有不少類型,理解他們的區別 例如:TextField 和 StringField
      doc.add(new TextField("content", text, Field.Store.YES));
      iwriter.addDocument(doc);
    }

  } catch (IOException e)
  {
    e.printStackTrace();
  } finally
  {
    try
    {
      if (iwriter != null)
      iwriter.close();
    } catch (IOException e)
    {
      e.printStackTrace();
    }
  }

}

  public IndexSearcher getSearcher()
  {
  try
  {
    if (ireader == null)
    {
      ireader = DirectoryReader.open(directory);
    } else
    {
      DirectoryReader tr = DirectoryReader.openIfChanged(ireader);
      if (tr != null)
      {
        ireader.close();
        ireader = tr;
      }
    }
    return new IndexSearcher(ireader);
    } catch (CorruptIndexException e)
    {
      e.printStackTrace();
    } catch (IOException e)
    {
      e.printStackTrace();
    }
    return null;
  }

  /**
  *
  * @param field
  * @param term
  * @param num
  */
  public void searchByTerm(String field, String term, int num)
  {
    IndexSearcher isearcher = getSearcher();
    // 注意query的實現類和QueryParse的用法的區別
    TermQuery query = new TermQuery(new Term(field, term));
    ScoreDoc[] hits;
    try
    {
      // 注意searcher的幾個方法
      hits = isearcher.search(query, null, num).scoreDocs;
      // Iterate through the results:
      for (int i = 0; i < hits.length; i++)
      {
        Document hitDoc = isearcher.doc(hits[i].doc);
        System.out.println("This is the text to be indexed=" + hitDoc.get("content"));
      }
    } catch (IOException e)
    {
      e.printStackTrace();
    }
  }

  /**
  * 區別與上一種查詢,使用QueryParser的parse方法構造一個Query傳遞給方式使用
  *
  * @param query
  * @param num
  */
  public void searchByQueryParse(Query query, int num)
  {
    try
    {
      IndexSearcher searcher = getSearcher();
      TopDocs tds = searcher.search(query, num);
      System.out.println("一共查詢了:" + tds.totalHits);
      for (ScoreDoc sd : tds.scoreDocs)
      {
        Document doc = searcher.doc(sd.doc);
        System.out.println("This is the text to be indexed=" + doc.get("content"));
      }
    } catch (CorruptIndexException e)
    {
       e.printStackTrace();
    } catch (IOException e)
    {
      e.printStackTrace();
    }
  }

  /**
  * 第一中分頁方式,對ScoreDoc進行分頁
  *
  * @param query
  * @param pageIndex
  * 從1開始,即第一頁
  * @param pageSize
  * 分頁大小
  * @param num
  * search top n hits
  */
  public void searchForPage(Query query, int pageIndex, int pageSize, int num)
  {
    try
    {
      IndexSearcher searcher = getSearcher();
      TopDocs tds = searcher.search(query, num);
      System.out.println("一共查詢了:" + tds.totalHits);
      // 對ScoreDoc分頁
      int start = (pageIndex - 1) * pageSize;
      int end = pageIndex * pageSize;
      ScoreDoc scoreDocs[] = tds.scoreDocs;
      for (int i = start; i < end; i++)
      {
        Document doc = searcher.doc(scoreDocs[i].doc);
        System.out.println("This is the text to be indexed=" + doc.get("content"));
      }
    } catch (CorruptIndexException e)
    {
        e.printStackTrace();
    } catch (IOException e)
    {
      e.printStackTrace();
    }
  }

  /**
  * 使用searchAfter 實如今查詢的時候的分頁
  *
  * @param query
  * @param pageIndex
  * @param pageSize
  * @throws IOException
  */
  public void searchForPageByAfter(Query query, int pageIndex, int pageSize) throws IOException
  {
    IndexSearcher searcher = getSearcher();
    // 先獲取上一頁的最後一個元素
     ScoreDoc lastSd = getLastScoreDoc(pageIndex, pageSize, query, searcher);
    TopDocs tds = searcher.searchAfter(lastSd, query, pageSize);
    for (ScoreDoc sd : tds.scoreDocs)
    {
      Document doc = searcher.doc(sd.doc);
      System.out.println("This is the text to be indexed=" + doc.get("content"));
    }

  }

  /**
  * 返回分頁查詢的上一條
  *
  * @param pageIndex
  * @param pageSize
  * @param query
  * @param indexSearcher
  * @return
  */
  private ScoreDoc getLastScoreDoc(int pageIndex, int pageSize, Query query, IndexSearcher searcher)
  {
    if (pageIndex == 1)
    return null;// 若是是第一頁就返回空
    int num = pageSize * (pageIndex - 1);// 獲取上一頁的數量
    TopDocs tds = null;
    try
    {
      tds = searcher.search(query, num);
    } catch (IOException e)
    {
      e.printStackTrace();
  }
  return tds.scoreDocs[num - 1];
  }

  public static void main(String[] args) throws ParseException, IOException
  {
    LuceneDemo03 ld = new LuceneDemo03();
    ld.createIndex();
    ld.searchByTerm("content", "play", 500);
    System.out.println("==============1======================");

    QueryParser parser = new QueryParser(version, "content", new StandardAnalyzer(version));
    Query q = parser.parse("play");// 研究下parse的語法
    ld.searchByQueryParse(q, 500);
    System.out.println("===============2=====================");

    ld.searchForPage(q, 1, 2, 500);// 從第一頁開始
    System.out.println("================3====================");

    ld.searchForPageByAfter(q, 1, 2);// 從第一頁開始
    System.out.println("================4====================");
  }

}

相關文章
相關標籤/搜索