Lucene基础(二)--索引的操作

索引的操作

我们建立所有就是要达到快速检索的目的,对数据能够方面便的查找,和数据库类似,索引也有自己的相关增删改查的操作。 
在索引的增删改查中,增删改属于写操作,主要是有IndexWrite提供的方法处理;而查显而易见,读操作,使用IndexSeacher 提供的方法来实现。在Lucene的官方文档找到 org.apache.lucene.index.IndexWriter 这个类,我们就可以看到他很多方法。

创建索引

如同上一章里面的代码,创建索引时先建立文件,创建索引的域,再使用IndexWriter的addDocument()方法就可以了,核心代码如下:

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);

}

索引删除

索引删除包括只删除索引下面的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) 删除过程中指明是否阻塞,直到操作完成

索引更新

更新操作也是一样,查看文档就有,这里截个图:

索引查询

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====================");
  }

}

时间: 2024-10-12 04:33:31

Lucene基础(二)--索引的操作的相关文章

OpenCV基础(二)---图像像素操作

图像像素操作 通过访问图像的像素,对灰度图像和RGB图像进行反差. 例如,在灰度图像中,某一个像素值为,pixel_value. 那么反差后的pixel_value = 255 - pixel_value. 对RGB图像处理类似,差别在于要对每一个颜色通道进行反差. 方法1: 1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace cv; 5 using namespace std; 6 7

Lucene全文检索之-Lucene基础

Lucene是全文检索引擎 一.在学习Lucene之前我们先思考下,Lucene存在的意义. 1.在之前我们的应用场景中,基于数据库的检索,我们使用like语法进行.但是基于like语法效率低下.达不到我们对应用的使用要求. 而使用Lucene对我们的数据建立索引效率高速度快,满足企业要求. 我们使用Lucene先对整个结构建立索引库,然后根据索引去查找我们需要匹配的内容,效率高速度快,方便我们快速检索信息-这也是Lucene存在的目的. 2.有些查找数据库做不了,比如我们想查找附件中内容的匹配

Python array,list,dataframe索引切片操作 2016年07月19日——智浪文档

array,list,dataframe索引切片操作 2016年07月19日——智浪文档 list,一维,二维array,datafrme,loc.iloc.ix的简单探讨 Numpy数组的索引和切片介绍: 从最基础的list索引开始讲起,我们先上一段代码和结果: a = [0,1,2,3,4,5,6,7,8,9] a[:5:-1] #step < 0,所以start = 9 a[0:5:-1] #指定了start = 0 a[1::-1] #step < 0,所以stop = 0 输出: [

Object Pascal 语法之语言基础(二)

1.5 数据类型与定义变量 Object Pascal 语言的最大特点是对数据类型的要求非常严谨.传递给过程或函数的参数值必须与形参的类型一致.在Object Pascal 语言中不会看到像C 语言编译器提示的“可疑的指针转换”等警告信息.由于Object Pascal 语言对数据类型比较严谨,因此它会对代码进行严格检查,以确保不会出现错误.变量是程序代码中代表一个内存地址的标识符,那么该地址的内存内容就可以在程序代码执行时被改变.每个变量都有一个名字和数据类型,名字可以用来引用变量,数据类型决

Lucene教程(四) 索引的更新和删除

这篇文章是基于上一篇文章来写的,使用的是IndexUtil类,下面的例子不在贴出整个类的内容,只贴出具体的方法内容. 3.5版本: 先写了一个check()方法来查看索引文件的变化: /** * 检查一下索引文件 */ public static void check() { IndexReader indexReader = null; try { Directory directory = FSDirectory.open(new File("F:/test/lucene/index&quo

DotNet二维码操作组件ThoughtWorks.QRCode

DotNet二维码操作组件ThoughtWorks.QRCode 在生活中有一种东西几乎已经快要成为我们的另一个电子"身份证",那就是二维码.无论是在软件开发的过程中,还是在普通用户的日常中,几乎都离不开二维码.二维码 (dimensional barcode) ,又称二维条码,是在一维条码的基础上扩展出的一种具有可读性的条码.设备扫描二维条码,通过识别条码的长度和宽度中所记载的二进制数据,可获取其中所包含的信息.相比一维条码,二维码记载更复杂的数据,比如图片.网络链接等. 今天介绍一

基础DOM和CSS操作

DOM简介 DOM是一种文档对象模型,方便开发者对HTML结构元素内容进行展示和修改.在JavaScript中,DOM不但内容庞大繁杂,而且我们开发的过程中需要考虑更多的兼容性.扩展性.在jQuery中,已经将最常用的DOM操作方法进行了有效封装,并且不需要考虑浏览器的兼容性. D表示的是页面文档Document.O表示对象,即一组含有独立特性的数据集合.M表示模型,即页面上的元素节点和文本节点. DOM有三种形式,标准DOM.HTML DOM.CSS DOM(难道不是XML DOM吗?),大部

Day2-Python基础2---集合和文件操作

一.集合操作 集合是一个无序的,不重复的数据组合,它的主要作用如下: 去重,把一个列表变成集合,就自动去重了 关系测试,测试两组数据之前的交集.差集.并集等关系 1 s = set([1,4,5,7,3,8,7,9,6]) #创建一个数值集合 2 3 t = set("Hello") #创建一个唯一字符的集合 4 5 6 a = t | s # t 和 s的并集 7 8 b = t & s # t 和 s的交集 9 10 c = t – s # 求差集(项在t中,但不在s中)

Bootstrap &lt;基础二十五&gt;警告(Alerts)

警告(Alerts)以及 Bootstrap 所提供的用于警告的 class.警告(Alerts)向用户提供了一种定义消息样式的方式.它们为典型的用户操作提供了上下文信息反馈. 您可以为警告框添加一个可选的关闭按钮.为了创建一个内联的可取消的警告框,请使用 警告(Alerts) jQuery 插件. 您可以通过创建一个 <div>,并向其添加一个 .alert class 和四个上下文 class(即 .alert-success..alert-info..alert-warning..ale