Lucene的基本使用

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica }

一、全文检索与Lucene介绍

1、全文检索

  将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。这部分从非结构化数据中提取出然后重新组织的信息,我们称之索引。
  这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-text Search)。

2、Lucene技术

  Lucene是apache下的一个开源的全文检索引擎工具包(类库)。它的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能。Lucene提供了完整的查询引擎和索引引擎,部分文本分析引擎。

3、Lucene实现全文检索的流程

全文检索的流程分为两大部分:索引流程、搜索流程。

  • 索引流程:即采集数据构建文档对象分析文档(分词)创建索引。
  • 搜索流程:即用户通过搜索界面输入创建查询执行搜索,搜索器从索引库搜索渲染搜索结果。

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: justify; font: 10.5px "PingFang SC" }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: justify; font: 10.5px Helvetica; color: #0433ff }
p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: justify; font: 10.5px Helvetica }
span.s1 { font: 10.5px Helvetica }
span.s2 { font: 10.5px "PingFang SC"; color: #000000 }
span.s3 { font: 10.5px Helvetica; text-decoration: underline }
span.s4 { font: 10.5px "PingFang SC" }

Lucene是开发全文检索功能的工具包,使用时从官方网站下载,并解压。

官方网站:http://lucene.apache.org/

下载地址:http://archive.apache.org/dist/lucene/java/

下载版本:4.10.3

JDK要求:1.7以上(从版本4.8开始,不支持1.7以下)

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica }

二、创建索引

 1 //创建索引
 2 @Test
 3 public void testIndex() throws IOException {
 4     //1.  采集数据:(jdbc采集数据通过BookDao调用方法得到结果集)
 5     BookDaoImpl dao = new BookDaoImpl();
 6     List<Book> bookList = dao.queryBookList();
 7
 8     //2.  遍历book结果集,组装Document数据列表
 9     for (Book book : bookList) {
10          Document doc = new Document();
11          //3.  构建Field域,说白了就是将要存储的数据字段需要用到new TextField对象三个参数的构造方法,book中有多个字段,所以创建多个Field对象。
12          //参数一:域的名称,可随意起;参数二:域对应的值;参数三:是否存储
13          /*Field id = new TextField("id", book.getId().toString(), Field.Store.YES);
14          Field name = new TextField("name",book.getName(), Field.Store.YES);
15          Field price = new TextField("price",book.getPrice().toString(), Field.Store.YES);
16          Field pic = new TextField("pic",book.getPic(), Field.Store.YES);
17          Field description = new TextField("description",book.getDescription(), Field.Store.YES);*/
18
19          //id不分词 要索引 要存储
20          Field id = new StringField("id", book.getId().toString(), Field.Store.YES);
21          // name 要分词 要索引 要存储
22          Field name = new TextField("name", book.getName(), Field.Store.YES);
23          // price 要分词 要索引 要存储,数字比较特殊
24          Field price = new FloatField("price", book.getPrice(), Field.Store.YES);
25          // pic 不分词 不索引 要存储
26          Field pic = new StoredField("pic", book.getPic());
27          // description 要分词 要索引 不存储
28          Field description = new TextField("description", book.getDescription(), Field.Store.NO);
29
30          //4.  将Field域所有对象,添加到文档对象中。调用Document.add
31          doc.add(id);
32          doc.add(name);
33          doc.add(price);
34          doc.add(pic);
35          doc.add(description);
36
37          //5.  创建一个标准分词器(Analyzer与StandardAnalyzer),对文档中的Field域进行分词
38          StandardAnalyzer analyzer = new StandardAnalyzer();
39          //6.  指定索引储存目录,使用FSDirectory.open()方法。
40          FSDirectory directory = FSDirectory.open(new File("/Users/Shared/index"));
41          //7.  创建IndexWriterConfig对象,直接new,用于接下来创建IndexWriter对象
42          IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer);
43          //8.  创建IndexWriter对象,直接new
44          IndexWriter writer = new IndexWriter(directory, config);
45          //9.  添加文档对象到索引库输出对象中,使用IndexWriter.addDocuments方法
46          writer.addDocument(doc);
47          //10.  释放资源IndexWriter.close();
48          writer.close();
49      }
50 }

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica }

三、搜索流程

 1 //搜索
 2 @Test
 3 public void testQuery() throws IOException {
 4      // 1.  创建一个Directory对象,FSDirectory.open指定索引库存放的位置
 5      FSDirectory directory = FSDirectory.open(new File("/Users/Shared/index"));
 6      // 2.  创建一个IndexReader对象,DirectoryReader.open需要指定Directory对象
 7      IndexReader indexReader = DirectoryReader.open(directory);
 8      // 3.  创建一个Indexsearcher对象,直接new,需要指定IndexReader对象
 9      IndexSearcher indexSearcher = new IndexSearcher(indexReader);
10      // 4.  创建一个TermQuery对象,直接new,指定查询的域和查询的关键词new Term(域名称,关键词)
11      TermQuery query = new TermQuery(new Term("name", "java"));
12      // 5.  执行查询,IndexSearcher.search,需要指定TermQuery对象与查询排名靠多少名前的记录数,得到结果TopDocs
13      TopDocs docs = indexSearcher.search(query, 10);
14      // 6.  遍历查询结果并输出,TopDocs.totalHits总记录数,topDocs.scoreDocs数据列表,通过scoreDoc.doc得到唯一id,再通过IndexSearcher.doc(id),得到文档对象Document再Document.get(域名称)得到结果
15      System.out.println("查询总记录数为:"+docs.totalHits);
16      for (ScoreDoc scoreDoc : docs.scoreDocs) {
17          //得到文档
18          int id = scoreDoc.doc;
19          Document doc = indexSearcher.doc(id);
20          System.out.println("id:"+doc.get("id"));
21          System.out.println("name:"+doc.get("name"));
22          System.out.println("price:"+doc.get("price"));
23          System.out.println("pic:"+doc.get("pic"));
24          System.out.println("description:"+doc.get("description"));
25       }
26      // 7.  关闭IndexReader对象
27      indexReader.close();
28 }

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica }

四、Field域

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica }

五、搜索

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Helvetica }

1、通过Query子类搜索

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Helvetica }

①通过MatchAllDocsQuery(查询所有文档)

1 @Test
2 public void testFindall() throws Exception{
3     //matachalldocsquery
4     Query query = new MatchAllDocsQuery();
5     //创建一个indexSearcher 对象
6     //通过indexSearcher 调用search方法查询
7     doSearcherBy(query);
8 }

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Helvetica }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Helvetica }

②TermQuery

1 @Test
2 public void testTermQuery() throws IOException {
3   TermQuery termQuery = new TermQuery(new Term("name", "apache"));
4   doSearchBy(termQuery);
5 }

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Helvetica }

③NumericRangeQuery

 1 @Test
 2 public void testNumbericRange() throws IOException{
 3   //第一个参数:域的名称
 4   //第二个参数:最小值
 5   //第三个参数:最大值
 6   //第四个参数:是否包含最小值
 7   //第五个参数:是否包含最大值
 8   NumericRangeQuery query = NumericRangeQuery.newFloatRange("price", 55f, 60f, false, false);
 9   doSearcherBy(query);
10 }

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Helvetica }

④BooleanQuery

 1 @Test
 2 publicvoid booleanQuery() throws Exception {
 3   BooleanQuery query = new BooleanQuery();
 4   Query query1 = new TermQuery(new Term("id", "3"));
 5   Query query2 = NumericRangeQuery.newFloatRange("price", 10f, 200f,true, true);
 6   //MUST:查询条件必须满足,相当于AND
 7   //SHOULD:查询条件可选,相当于OR
 8   //MUST_NOT:查询条件不能满足,相当于NOT非
 9   query.add(query1, Occur.MUST);
10   query.add(query2, Occur.SHOULD);
11   System.out.println(query);
12   doSearcherBy(query);
13 }

2、通过QueryParser搜索

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Helvetica }

①查询语法

查看语法,Query对象执行的查询语法可通过System.out.println(query),查看。

第一种简单的语法:

域名+":"+搜索的关键词 例如:name:java 表示搜索域名为name ,其关键词为java的文档对象。

第二种:查询所有的文档

*:*

第三种:数值范围的语法:

域名+“:”+[数值 TO 数值] 表示数值范围,并且包括数值。如果不包括数值 用"{}"比如:

price:[55.0 TO 70.0] 等同于 55=< price <=70
price:{55.0 TO 70.0] 等同于 55 < price <=70

  数值范围类的查询语法,不支持在queryparser中查询。语法是没有错误的。在solr中可以查询出来。
第四种:组合条件查询
  Occur.MUST 查询条件必须满足,相当于and
  +(加号)
  Occur.SHOULD 查询条件可选,相当于or

  空(不用符号)
  Occur.MUST_NOT 查询条件不能满足,相当于not非
  -(减号)

  1)+条件1 +条件2:两个条件之间是并且的关系and
  例如:+filename:apache +content:apache

  2)+条件1 条件2:必须满足第一个条件,忽略第二个条件
  例如:+filename:apache content:apache

  3)条件1 条件2:两个条件满足其一即可。
  例如:filename:apache content:apache

  4)-条件1 条件2:必须不满足条件1,要满足条件2
  例如:-filename:apache content:apache

第二种写法:

  • 条件1 AND 条件2
  • 条件1 OR 条件2
  • 条件1 NOT 条件2

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 10.0px Helvetica }

②MultiFieldQueryParser

 1 @Test
 2 publicvoidtestMultiFieldQueryParser() throws Exception {
 3   // 可以指定默认搜索的域是多个
 4   String[] fields = { "name", "description" };
 5   // 创建一个MulitFiledQueryParser对象
 6   QueryParser parser = new MultiFieldQueryParser(fields, new IKAnalyzer());
 7   // 指定查询语法,如果不指定域,就搜索默认的域
 8   Query query = parser.parse("lucene");
 9   // 2、执行搜索
10   doSearcherBy(query);
11 }

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica }
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: justify; font: 10.5px "Times New Roman"; min-height: 11.0px }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: justify; font: 10.5px "PingFang SC" }
li.li2 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: justify; font: 10.5px "PingFang SC" }
span.s1 { font: 10.5px "Lucida Grande" }
span.s2 { font: 10.5px Wingdings }
span.s3 { font: 10.5px Helvetica }
span.Apple-tab-span { white-space: pre }
ul.ul1 { list-style-type: disc }

原文地址:https://www.cnblogs.com/gdwkong/p/8821435.html

时间: 2024-10-18 07:31:01

Lucene的基本使用的相关文章

lucene中Field.Index,Field.Store的一些设置

lucene在doc.add(new Field("content",curArt.getContent(),Field.Store.NO,Field.Index.TOKENIZED)); Field有两个属性可选:存储和索引. 通过存储属性你可以控制是否对这个Field进行存储: 通过索引属性你可以控制是否对该Field进行索引. 事实上对这两个属性的正确组合很重要. Field.Index Field.Store 说明 TOKENIZED(分词) YES 被分词索引且存储 TOKE

Lucene 基础理论

1. 全文检索系统与Lucene简介 1.1 什么是全文检索与全文检索系统 全文检索是指计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式.这个过程类似于通过字典中的检索字表查字的过程. 全文检索的方法主要分为按字检索和按词检索两种.按字检索是指对于文章中的每一个字都建立索引,检索时将词分解为字的组合.对于各种不同的语言而言,字有不同的含义,比如英文中字与词实际上

一步一步跟我学习lucene(19)---lucene增量更新和NRT(near-real-time)Query近实时查询

这两天加班,不能兼顾博客的更新,请大家见谅. 有时候我们创建完索引之后,数据源可能有更新的内容,而我们又想像数据库那样能直接体现在查询中,这里就是我们所说的增量索引.对于这样的需求我们怎么来实现呢?lucene内部是没有提供这种增量索引的实现的: 这里我们一般可能会想到,将之前的索引全部删除,然后进行索引的重建.对于这种做法,如果数据源的条数不是特别大的情况下倒还可以,如果数据源的条数特别大的话,势必会造成查询数据耗时,同时索引的构建也是比较耗时的,几相叠加,势必可能造成查询的时候数据缺失的情况

一步一步跟我学习lucene(9)---lucene搜索之拼写检查和相似度查询提示(spellcheck)

suggest应用场景 用户的输入行为是不确定的,而我们在写程序的时候总是想让用户按照指定的内容或指定格式的内容进行搜索,这里就要进行人工干预用户输入的搜索条件了:我们在用百度谷歌等搜索引擎的时候经常会看到按键放下的时候直接会提示用户是否想搜索某些相关的内容,恰好lucene在开发的时候想到了这一点,lucene提供的suggest包正是用来解决上述问题的. suggest包联想词相关介绍 suggest包提供了lucene的自动补全或者拼写检查的支持: 拼写检查相关的类在org.apache.

Lucene的一个简单的标准测试(Lucene包基于3.5版本的)

Lucene编程一般分为:索引.分词.搜索 索引源代码: package lucene的一个标准测试; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.Date; import org.apache.lucene.anal

利用Lucene把文本的字体格式进行修改,然后输出到一个新的文件中

这里书中写的是charactorProcess(File file, String destFile) 这里被我改成,(String file,  String destFIle) 一个代表现有的文件和要新建的文件 代码: package com; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.

Lucene基本概念

Lucene基本概念: 1.  Index:索引库,文档的集合组成索引.和一般的数据库不一样,Lucene不支持定义主键,在Lucene中不存在一个叫做Index的类,通过IndexWriter来写索引,通过IndexReader来读索引.索引库在物理形式上一般是位于一个路径下的一系列文件. 2.  分析器:一段有意义的文字需要通过Analyzer分析器分割成一个个词语后才能按关键字搜索,StandardAnalyzer是Lucene中最常用的分析器.为了达到更好的搜索效果,不同的语言可以使用不

lucene分词器中的Analyzer,TokenStream, Tokenizer, TokenFilter

分词器的核心类: Analyzer:分词器 TokenStream: 分词器做好处理之后得到的一个流.这个流中存储了分词的各种信息,可以通过TokenStream有效的获取到分词单元. 以下是把文件流转换成分词流(TokenStream)的过程 首先,通过Tokenizer来进行分词,不同分词器有着不同的Tokenzier,Tokenzier分完词后,通过TokenFilter对已经分好词的数据进行过滤,比如停止词.过滤完之后,把所有的数据组合成一个TokenStream:以下这图就是把一个re

SpringMVC + Mybatis + SpringSecurity(权限控制到方法按钮) + Rest(服务) + Webservice(服务) + Quartz(定时调度)+ Lucene(搜索引擎) + HTML5 bootstrap + Maven项目构建绝对开源平台

框架整合: Springmvc + Mybatis + Shiro(权限) + REST(服务) + WebService(服务) + JMS(消息) + Lucene(搜搜引擎) + Quartz(定时调度) + Bootstrap Html5(支持PC.IOS.Android) 需要源码请加Q:3121026417   此处[源码获取地址] 框架简介: 项目Maven构建,真实大型互联网架构,做到高并发,大数据处理,整个项目使用定制化服务思想,提供模块化.服务化.原子化的方案,将功能模块进行

lucene搜索之高级查询

使用Query子类查询 MatchAllDocsQuery TermQuery NumericRangeQuery BooleanQuery 使用QueryParser QueryParser MulitFieldQueryParser 先抽取公共代码 private void dosearch(Query query) throws IOException { //给出索引库位置 FSDirectory directory = FSDirectory.open(new File("E:\\up