lucene

Lucene介绍及核心概念

什么是Lucene

Lucene是一套用于全文检索和搜索的开放源代码程序库,由Apache软件基金会支持和提供。Lucene提供了一个简单却强大的应用程序接口,能够做全文索引和搜索,在Java开发环境里Lucene是一个成熟的免费开放源代码工具;就其本身而论,Lucene是现在并且是这几年,最受欢迎的免费Java信息检索程序库。

lucene可以做什么

Lucene允许你向自己的应用程序中添加搜索功能。Lucene能够把你从文本中解析出来的数据进行索引和搜索。Lucene并不关心你的数据来源,格式,甚至不关心数据的语种。

Lucene的优点

  • Lucene作为一个全文检索引擎,其具有如下突出的优点:

(1)索引文件格式独立于应用平台。Lucene定义了一套以8位字节为基础的索引文件格式,使得兼容系统或者不同平台的应用能够共享建立的索引文件。

(2)在传统全文检索引擎的倒排索引的基础上,实现了分块索引,能够针对新的文件建立小文件索引,提升索引速度。然后通过与原有索引的合并,达到优化的目的。

(3)优秀的面向对象的系统架构,使得对于Lucene扩展的学习难度降低,方便扩充新功能。

(4)设计了独立于语言和文件格式的文本分析接口,索引器通过接受Token流完成索引文件的创立,用户扩展新的语言和文件格式,只需要实现文本分析的接口。

(5)已经默认实现了一套强大的查询引擎,用户无需自己编写代码即使系统可获得强大的查询能力,Lucene的查询实现中默认实现了布尔操作、模糊查询(Fuzzy Search[11])、分组查询等等。

Lucene相关名词解释

1、IndexWriter

lucene中最重要的的类之一,它主要是用来将文档加入索引,同时控制索引过程中的一些参数使用。

2、Analyzer

分析器,主要用于分析搜索引擎遇到的各种文本。常用的有StandardAnalyzer分析器,StopAnalyzer分析器,WhitespaceAnalyzer分析器等。

3、Directory

索引存放的位置;lucene提供了两种索引存放的位置,一种是磁盘,一种是内存。一般情况将索引放在磁盘上;相应地lucene提供了FSDirectory和RAMDirectory两个类。

4、Document

文档;Document相当于一个要进行索引的单元,任何可以想要被索引的文件都必须转化为Document对象才能进行索引。

5、Field

类似于数据库中的一个字段,存储了key-value值。

6、IndexSearcher

是lucene中最基本的检索工具,所有的检索都会用到IndexSearcher工具;

7、Query

Query类似关系型数据库中的SQL语句。与关系型数据库类似,Lucene提供了以下的基本查询:精确查询xxx = ? TermQuery、范围查询 xxx BETWEEN? AND ? PointRangeQuery、模糊查询 xxx LIKE '%?%' PrefixQuery、RegexpQuery、组合查询 (...) AND (...) OR (...) BooleanQuery

8、QueryParser

是一个解析用户输入的工具,可以通过扫描用户输入的字符串,生成Query对象。

9、Hits

在搜索完成之后,需要把搜索结果返回并显示给用户,只有这样才算是完成搜索的目的。在Lucene中,搜索的结果的集合是用Hits类的实例来表示的。

什么是正向索引、什么是倒排索引?

正向索引(forward index),反向索引(inverted index)更熟悉的名字是倒排索引。

在搜索引擎中每个文件都对应一个文件ID,文件内容被表示为一系列关键词的集合(实际上在搜索引擎索引库中,关键词也已经转换为关键词ID)。例如“文档1”经过分词,提取了20个关键词,每个关键词都会记录它在文档中的出现次数和出现位置,得到正向索引的结构如下:

doc1 ---> word1:出现次数,出现位置列表;单词2:出现次数,出现位置列表...

doc2 ---> word1:出现次数,出现位置列表;单词2:出现次数,出现位置列表...

当用户在主页上搜索关键词“苹果手机”时,假设只存在正向索引(forward index),那么就需要扫描索引库中的所有文档,找出所有包含关键词“苹果手机”的文档,再根据打分模型进行打分,排出名次后呈现给用户。因为互联网上收录在搜索引擎中的文档的数目是个天文数字,这样的索引结构根本无法满足实时返回排名结果的要求。

所以,搜索引擎会将正向索引重新构建为倒排索引,即把文件ID对应到关键词的映射转换为关键词到文件ID的映射,每个关键词都对应着一系列的文件,这些文件中都出现这个关键词,得到倒排索引的结构如下:

word1 ---> doc3、doc2、doc7、doc6.....

word2 ---> doc1、doc2、doc5、doc6.....

lucene java客户端

/**
* <p>
*
* @author leone
* @since: 2018-11-23
**/
public class Book { private int bookId; private String name; private float price; private String picture; private String description; public Book() {
} public Book(int bookId, String name, float price, String picture, String description) {
this.bookId = bookId;
this.name = name;
this.price = price;
this.picture = picture;
this.description = description;
} public int getBookId() {
return bookId;
} public void setBookId(int bookId) {
this.bookId = bookId;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public float getPrice() {
return price;
} public void setPrice(float price) {
this.price = price;
} public String getPicture() {
return picture;
} public void setPicture(String picture) {
this.picture = picture;
} public String getDescription() {
return description;
} public void setDescription(String description) {
this.description = description;
}
}
package com.andy.lucene;

import org.apache.commons.io.FileUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.*;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
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.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; /**
* <p>
*
* @author leone
* @since: 2018-11-23
**/
public class BookMain { private static final Logger logger = LoggerFactory.getLogger(BookMain.class); private static List<Book> books = new ArrayList<>(); private static String docPath = "E:\\tmp\\lucene\\docDir";
private static String indexPath = "E:\\tmp\\lucene\\indexDir"; static {
books.add(new Book(1, "Java核心编程思想", 23, "http://www.taobao.com/image.jpg", "Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程"));
books.add(new Book(2, "mysql数据库设计", 47, "http://www.taobao.com/image.jpg", "MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件。"));
books.add(new Book(3, "JavaWeb进阶", 75, "http://www.jd.com/image.jpg", "Java Web,是用Java技术来解决相关web互联网领域的技术总和。web包括:web服务器和web客户端两部分。Java在客户端的应用有java applet,不过使用得很少,Java在服务器端的应用非常的丰富,比如Servlet,JSP和第三方框架等等。Java技术对Web领域的发展注入了强大的动力。"));
books.add(new Book(4, "spring入门", 38, "http://www.tianmao.com/image.jpg", "Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建。简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架"));
books.add(new Book(5, "springCloud微服务实战", 42, "http://www.yamaxun.com/image.jpg", "Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。"));
books.add(new Book(5, "JavaScript高级", 71, "http://www.tianmao.com/image.jpg", "JavaScript 是属于网络的脚本语言 JavaScript 被数百万计的网页用来改进设计、验证表单、检测浏览器、创建cookies,以及更多的应用。"));
} public static void main(String[] args) throws Exception { Map<String, String> doc = new HashMap<>();
doc.put("文件名称", "fileName");
doc.put("文件大小", "fileSize");
doc.put("文件路径", "filePath");
doc.put("文件内容", "fileContent"); Map<String, String> book = new HashMap<>();
book.put("商品ID", "book_id");
book.put("商品名称", "name");
book.put("商品价格", "price");
book.put("商品图片地址", "picture");
book.put("商品描述", "description"); long start = System.currentTimeMillis();
// createIndex();
// indexSearch("description:spring");
logger.info("一共花费了:{}毫秒!", (System.currentTimeMillis() - start));
} private static void createIndex() throws IOException {
// 将采集到的数据封装到Document对象中
List<Document> docList = new ArrayList<>();
Document document;
for (Book book : books) {
document = new Document();
// store:如果是yes,则说明存储到文档域中 // 图书ID
Field bookId = new TextField("book_id", Integer.toString(book.getBookId()), Field.Store.YES);
// 图书名称
Field name = new TextField("name", book.getName(), Field.Store.YES);
// 图书价格
Field price = new TextField("price", Float.toString(book.getPrice()), Field.Store.YES);
// 图书图片地址
Field picture = new TextField("picture", book.getPicture(), Field.Store.YES);
// 图书描述
Field description = new TextField("description", book.getDescription(), Field.Store.YES);
// 将field域设置到Document对象中
document.add(bookId);
document.add(name);
document.add(price);
document.add(picture);
document.add(description);
docList.add(document);
}
// 创建分词器,标准分词器
Analyzer analyzer = new StandardAnalyzer();
// 创建IndexWriter
IndexWriterConfig cfg = new IndexWriterConfig(analyzer);
// 指定索引库的地址
Directory directory = FSDirectory.open(FileSystems.getDefault().getPath(indexPath));
// 创建索引writer
IndexWriter writer = new IndexWriter(directory, cfg);
// 清除以前的index
writer.deleteAll();
// 通过IndexWriter对象将Document写入到索引库中
for (Document doc : docList) {
writer.addDocument(doc);
}
// 关闭writer
writer.close();
} /**
* @param query
* @throws IOException
*/
private static void searchDocument(Query query, Map<String, String> map) throws IOException {
// 1.创建DirectoryJDK 1.7以后 open只能接收Path
Directory directory = FSDirectory.open(FileSystems.getDefault().getPath(indexPath));
IndexReader reader = DirectoryReader.open(directory);
IndexSearcher searcher = new IndexSearcher(reader);
// 通过searcher来搜索索引库,第二个参数指定需要显示的顶部记录的N条
TopDocs topDocs = searcher.search(query, 10); // 根据查询条件匹配出的记录总数
int count = topDocs.totalHits; System.out.println("匹配出的记录总数:[ " + count + " ]\n==========================");
// 根据查询条件匹配出的记录
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
for (ScoreDoc scoreDoc : scoreDocs) {
// 获取文档的ID
int docId = scoreDoc.doc;
// 通过ID获取文档
Document doc = searcher.doc(docId);
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + ":" + doc.get(entry.getValue()));
}
System.out.println("==========================");
}
// 关闭资源
reader.close(); } public static void indexSearch(String name, Map<String, String> map) throws Exception {
// 创建query对象
Analyzer analyzer = new StandardAnalyzer();
// 使用QueryParser搜索时,需要指定分词器,搜索时的分词器要和索引时的分词器一致,第一个参数:默认搜索的域的名称
QueryParser parser = new QueryParser("description", analyzer);
// 参数:输入的lucene的查询语句(关键字一定要大写)
Query query = parser.parse(name);
searchDocument(query, map);
} }

lucene 核心概念及入门的更多相关文章

  1. Spring 核心概念以及入门教程

    初始Spring 在学习Spring之前我们首先要了解一下企业级应用.企业级应用是指那些为商业组织,大型企业而创建并部署的解决方案及应用. 这些大型企业级应用的结构复杂,涉及的外部资源众多,事务密集, ...

  2. hadoop 核心概念及入门

    Hadoop Hadoop背景 什么是HADOOP HADOOP是apache旗下的一套开源软件平台HADOOP提供利用服务器集群,根据用户的自定义业务逻辑,对海量数据进行分布式处理,HADOOP的核 ...

  3. Elasticsearch入门教程(二):Elasticsearch核心概念

    原文:Elasticsearch入门教程(二):Elasticsearch核心概念 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:ht ...

  4. JAVAEE——BOS物流项目13:Quartz入门案例、核心概念、cron 表达式的格式(了解)

    1.quartz入门案例 本入门案例基于spring和quartz整合完成. 第一步:创建maven工程,导入spring和quartz相关依赖 第二步:创建任务类 第三步:在spring配置文件中配 ...

  5. ElasticSearch入门及核心概念介绍

      Elasticsearch研究有一段时间了,现特将Elasticsearch相关核心知识和原理以初学者的角度记录下来,如有不当,烦请指正! 0. 带着问题上路——ES是如何产生的? (1)思考:大 ...

  6. JAVA入门(1.JAVA平台应用 2.核心概念:JVM,JDK,JRE 3.搭建JAVA开发环境 4.学习JAVA的原则)

    主要内容: 1.JAVA平台应用 2.核心概念:JVM,JDK,JRE 3.搭建JAVA开发环境 4.学习JAVA的原则 JAVA的平台应用 JAVA的平台应用分为3个部分: 一.JAVA SE,主要 ...

  7. Mycat入门核心概念

      Mycat中的核心概念     Mycat中的核心概念 1.数据库中间件    Mycat 是一个开源的分布式数据库系统,但是由于真正的数据库需要存储引擎,而 Mycat 并没有 存储引擎,所以并 ...

  8. 从零开始入门 K8s| 阿里技术专家详解 K8s 核心概念

    作者| 阿里巴巴资深技术专家.CNCF 9个 TCO 之一 李响 一.什么是 Kubernetes Kubernetes,从官方网站上可以看到,它是一个工业级的容器编排平台.Kubernetes 这个 ...

  9. ZooKeeper入门实战教程(一)-介绍与核心概念

    1.ZooKeeper介绍与核心概念1.1 简介ZooKeeper最为主要的使用场景,是作为分布式系统的分布式协同服务.在学习zookeeper之前,先要对分布式系统的概念有所了解,否则你将完全不知道 ...

随机推荐

  1. 2017-2018-1 20155205 嵌入式C语言——时钟

    2017-2018-1 20155205 嵌入式C语言--时钟 题目要求 基础知识 插入位(以分钟为例) 提取位(以分钟为例) 在提取分钟时,运用到了位运算,位运算有以下规律: &0 --&g ...

  2. 分享Azure DevOps技术,来微信群吧!

    现在QQ用户越来越少,基本上都转移到微信上了. 讨论问题,动不动就来一个微信群.下面这样几百人的微信群,专门讨论Azure DevOps (TFS)技术,你加入了么? 还等什么,扫描吧!

  3. ASP.NET MVC下使用AngularJs语言(九):日期时间处理与显示

    当在angularjs去显示一个时间时,如原原本本去显示这个值,它将显示一个怪怪的字符串,其实它就是被系列化json之后的字符串.如:一个空值显示为日期时间: 如果非空值显示为日期时间的情形: 为了能 ...

  4. AJPFX:什么是外汇交易

    外汇交易是对货币对的一种买卖,是以一个国家货币与另外一个国家货币进行交换,即您在买入一国货币的同时,您也卖出了另一国的货币.所以在外汇市场上,人们的交易对象就是“货币对“,比如欧元/美元,美元/日元, ...

  5. Python 绝技 —— UDP 服务器与客户端

    i春秋作家:wasrehpic 0x00 前言 在上一篇文章「Python 绝技 —— TCP 服务器与客户端」中,介绍了传输层的核心协议 TCP ,并运用 Python 脚本的 socket 模块演 ...

  6. https网页加载http资源导致的页面报错及解决方案

    https是当下的网站的主流趋势,甚至像苹果这样的大公司,则完全要求用户必须使用https地址. 然而对于以前http链接来说,我们往往就存在一个兼容性问题,因为你不可能一下就全部切换过去,应该在很长 ...

  7. javascript 异步解析

    js 异步解析 一 .js单线程分析 我们都知道js的一大特点是单线程,也就是同一时间点,只能处理一件事,一句js代码.那为什么js要设计成单线程而不是多线程呢?这主要和js的用途有关,js作为浏览器 ...

  8. Liferay7 BPM门户开发之6: Activiti数据库换为mysql

    第一步: 在mysql中创建数据库名字叫 'activiti' 执行D:\activiti-5.21.0\database\create下的脚本 第二步: 打开=> apache-tomcat/ ...

  9. laravel5.5 __construct函数 无法使用session() 解决方法和实例

    从网上查询资料得知,在laravel中使用__construct方法的时候,session还没开启,此时就需要用到中间件来解决. $this->middleware(function ($req ...

  10. list源码3(参考STL源码--侯捷):push_front、push_back、erase、pop_front、pop_back、clear、remove、unique

    list源码1(参考STL源码--侯捷):list节点.迭代器.数据结构 list源码2(参考STL源码--侯捷):constructor.push_back.insert list源码3(参考STL ...