Lucene学习笔记

Lucene学习笔记

#

  1. 概念
    • lucene本质上是一个jar包,专注于底层,提供了很多API供java实现对索引库的维护
    • 索引库采用的是倒排索引的的技术:先查索引,如果有就会获得文档ID;拿到文档ID去文档数据中找到文档数据

2.相关依赖:

<dependencies>
    <!-- Junit单元测试 -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <!-- lucene核心库 -->
    <dependency>
        <groupId>org.apache.lucene</groupId>
        <artifactId>lucene-core</artifactId>
        <version>4.10.2</version>
    </dependency>
    <!-- Lucene的查询解析器 -->
    <dependency>
        <groupId>org.apache.lucene</groupId>
        <artifactId>lucene-queryparser</artifactId>
        <version>4.10.2</version>
    </dependency>
    <!-- lucene的默认分词器库 -->
    <dependency>
        <groupId>org.apache.lucene</groupId>
        <artifactId>lucene-analyzers-common</artifactId>
        <version>4.10.2</version>
    </dependency>
    <!-- lucene的高亮显示 -->
    <dependency>
        <groupId>org.apache.lucene</groupId>
        <artifactId>lucene-highlighter</artifactId>
        <version>4.10.2</version>
    </dependency>
    <!-- IK分词器,适用于中文分词 -->
    <dependency>
        <groupId>com.janeluo</groupId>
        <artifactId>ikanalyzer</artifactId>
        <version>2012_u6</version>
    </dependency>

</dependencies>

3.索引写入

  • 相关API

    • Document:文档对象,原始数据,对象中的每一个记录,就是一个Field
    • Store:枚举类型
      • Store.No : 当前字段不在文档数据去存储,但是建立索引
      • Store.YES : 当前字段在文档区存储,且建立索引
    • Field:字段,即document中的记录,常用的有StringField(不分词),TextField(分词)等
    • Directory:指定索引要存储的位置
      • FSDirectory:文件系统目录:会把索引库保存到本地磁盘。特点:速度略慢,但是比较安全
      • RAMDirectory:内存目录,将索引库保存到内存。特点:速度快,但是不安全
    • IndexWriterConfig:设置配置信息,lucene的版本和分词器类型
    • IndexWriter:索引写入器:
    • Analyzer:分词器
  • 代码实现

  • `public void indexCreate() throws IOException {
    // 创建文档对象
    Document document = new Document();
    // 添加字段,参数Field是一个接口,要new实现类的对象(StringField, TextField)
    // StringField的实例化需要3个参数:1-字段名,2-字段值,3-是否保存到文档,Store.YES存储,NO不存储
    document.add(new StringField("id", "1", Store.YES));
    // TextField:创建索引并提供分词,StringField创建索引但不分词
    document.add(new TextField("title", "谷歌地图之父跳槽FaceBook", Store.YES));
    
    // 创建目录对象,指定索引库的存放位置;FSDirectory文件系统;RAMDirectory内存
    Directory directory = FSDirectory.open(new File("C:\\tmp\\indexDir"));
    // 创建分词器对象
    Analyzer analyzer = new StandardAnalyzer();
    // 创建索引写入器配置对象,第一个参数版本VerSion.LATEST,第一个参数分词器
    IndexWriterConfig conf = new IndexWriterConfig(Version.LATEST, analyzer);
    // 创建索引写入器
    IndexWriter indexWriter = new IndexWriter(directory , conf);
    // 向索引库写入文档对象
    indexWriter.addDocument(document);
    // 提交
    indexWriter.commit();
    // 关闭
    indexWriter.close();
    }`
    

4.查询

  • 相关API:
    • QueryParser:单一字段解析器
    • MultiFieldQueryParser:多域字段解析器
      • MultiFieldQueryParser pasrer =new MultiFieldQueryParser(new String[]{"id","content"},new IKAnalyzer);
        Query query = parser.parse("2");
    • Query:查询对象
    • IndexSearcher:索引搜索对象
    • IndexReader:索引读取对象
    • TopDocs:查询结果对象
    • ScoreDoc:得分文档
  • 代码实现

    public void testSearcher() throws IOException, ParseException{      
    // 初始化索引库对象
    Directory directory = FSDirectory.open(new File("C:\\tmp\\index"));     
    // 索引读取工具
    IndexReader indexReader = DirectoryReader.open(directory);
    // 索引搜索对象
    IndexSearcher indexSearcher = new IndexSearcher(indexReader);       
    // 创建查询解析器对象
    QueryParser parser = new QueryParser("title", new IKAnalyzer());
    // 创建查询对象
    Query query = parser.parse("谷歌");
    // 执行搜索操作,返回值topDocs包含命中数,得分文档
    TopDocs topDocs = indexSearcher.search(query, Integer.MAX_VALUE);
    // 打印命中数
    System.out.println("一共命中:"+topDocs.totalHits+"条数据");
    // 获得得分文档数组对象,得分文档对象包含得分和文档编号
    ScoreDoc[] scoreDocs = topDocs.scoreDocs;
    for (ScoreDoc scoreDoc : scoreDocs) {
        System.out.println("得分:"+scoreDoc.score);
        // 文档的编号
        int doc = scoreDoc.doc;
        System.out.println("编号:"+doc);
        // 获取文档对象,通过索引读取工具
        Document document = indexReader.document(doc);
        System.out.println("id:"+document.get("id"));
        System.out.println("title:"+document.get("title"));
    }
    

    }

  • 几种特殊查询query。
    • 字段查询 Query query = new TermQuery(new Term("title", "谷歌"));
      // 执行搜索操作
      searcher(query);
    • 通配符查询 Query query = new WildcardQuery(new Term("title", "*歌*"));
      search(query);
    • 模糊查询 Query query = new FuzzyQuery(new Term("title", "facebook"), 1);
      search(query);
    • 数值范围查询 Query query = NumericRangeQuery.newLongRange("id", 2l, 4l, true, true);
      search(query);
    • 组合查询 BooleanQuery query = new BooleanQuery();
      // 交集: Occur.MUST + Occur.MUST
      // 并集:Occur.SHOULD + Occur.SHOULD
      // 非:Occur.MUST_NOT
      query.add(query1, Occur.SHOULD);
      query.add(query2, Occur.SHOULD);

5.修改删除索引

  • 修改索引:实质上是先删后加

    • 代码实现

      `// 创建文档对象
      Document document = new Document();
      document.add(new StringField("id", "9", Store.YES));
      document.add(new TextField("title", "谷歌地图之父跳槽FaceBook", Store.YES));        
      // 索引库对象
      Directory directory = FSDirectory.open(new File("C:\\tmp\\index"));
      // 索引写入器配置对象
      IndexWriterConfig conf = new IndexWriterConfig(Version.LATEST, new IKAnalyzer());
      // 索引写入器对象
      IndexWriter indexWriter = new IndexWriter(directory, conf);     
      // 执行更新操作
      indexWriter.updateDocument(new Term("id", "1"), document);
      // 提交
      indexWriter.commit();
      // 关闭
      indexWriter.close();
      

===========================
查询到所有 id 符合 1 的文档,并删除,然后将新的文档添加进去。`

  • 删除索引:

    • 代码实现

      // 创建目录对象
      Directory directory = FSDirectory.open(new File("C:\\tmp\\indexDir"));
      // 创建索引写入器配置对象
      IndexWriterConfig conf = new IndexWriterConfig(Version.LATEST, new IKAnalyzer());
      // 创建索引写入器对象
      IndexWriter indexWriter = new IndexWriter(directory, conf);
      // 执行删除操作(根据词条),要求id字段必须是字符串类型
      // indexWriter.deleteDocuments(new Term("id", "5"));
      // 根据查询条件删除
      // indexWriter.deleteDocuments(NumericRangeQuery.newLongRange("id", 2l, 4l, true, false));
      // 删除所有
      indexWriter.deleteAll();
      indexWriter.commit();
      indexWriter.close();
      

6.其他功能

  • 高亮显示:本质是给查询结果添加一个前后坠

    • 代码实现

      ....
      
      // 格式化器  设置查询结果的前缀后缀
      Formatter formatter = new SimpleHTMLFormatter("<em>", "</em>");
      Scorer scorer = new QueryScorer(query);
      // 准备高亮工具
      Highlighter highlighter = new Highlighter(formatter, scorer);
      ....
      
      ScoreDoc[] scoreDocs = topDocs.scoreDocs;
      for (ScoreDoc scoreDoc : scoreDocs) {
      ...
      
      String title = doc.get("title");
      // 用高亮工具处理普通的查询结果,参数:分词器,要高亮的字段的名称,高亮字段的原始值
      String hTitle = highlighter.getBestFragment(new IKAnalyzer(), "title", title);
      System.out.println("title: " + hTitle);
      }
      
  • 排序搜索:

    • 代码实现

       // 创建排序对象,需要排序字段SortField,参数:字段的名称、字段的类型、是否反转:如果是false,升序,true降序
      Sort sort = new Sort(new SortField("id", Type.LONG, true));
      // 搜索,搜索结果即为指定排序的顺序
      TopDocs topDocs = searcher.search(query, 10,sort);
      
  • 分页查询

    • 代码实现

          // 实际上Lucene本身不支持分页。因此我们需要自己进行逻辑分页。我们要准备分页参数:
      int pageSize = 2;                                   // 每页条数
      int pageNum = 3;                                    // 当前页码
      int start = (pageNum - 1) * pageSize;               // 当前页的起始条数
      int end = start + pageSize;                         // 当前页的结束条数(不能包含)
      // 创建排序对象,需要排序字段SortField,参数:字段的名称、字段的类型、是否反转如果是false,升序。true降序
      Sort sort = new Sort(new SortField("id", Type.LONG, false));
      // 搜索数据,查询0~end条
      TopDocs topDocs = searcher.search(query, end,sort);
      
  • 得分算法

    • 代码实现

      //lucene会对搜索结果打分,用来表示文档与词条关联性的强弱,得分越高,表示查询的匹配度越高,结果中出现的位置越靠前
      //创建文档对象
      Document document1 = new Document();
      //添加字段,参数1-字段名,2-字段值,3-是否保存,Store枚举,
      document1.add(new StringField("id","1",Store.YES));
      TextField field = newTextField("title","谷歌致富");
      field.setBoost(100);
      document1.add(field);
      

7.IK分词器配置

  • 在resource资源路径下新建:IKAnalyzer.cfg.xml

    • 具体配置

      `<?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">  
      <properties>  
      <comment>IK Analyzer 扩展配置</comment>
      <!--用户可以在这里配置自己的扩展字典 -->
      <entry key="ext_dict">ext.dic;</entry> 
      <!--用户可以在这里配置自己的扩展停止词字典-->
      <entry key="ext_stopwords">stopword.dic;</entry> 
      </properties>`
      
  • 扩展词典配置:按cfg.xml文件中配置的文件地址创建,直接在内容中写明需要识别为分词的词语即可,停止词词典同。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值