Lucene、Elasticsearch、Kibana 入门教程和环境搭建
2020/7/3 17:27:14
本文主要是介绍Lucene、Elasticsearch、Kibana 入门教程和环境搭建,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
信息检索模型
信息检索模型最重要的概念就是倒排索引
,倒排索引是搜索引擎中常见的索引方法,用来存储在全文搜索下某个单词在一个文档中存储位置的映射。通过倒排索引,我们输入一个关键词,可以非常快地获取包含这个关键词的文档列表。
Lucene
Lucene 是一个基于 Java 的全文信息检索工具包,它不是一个完整的搜索应用程序,而是为你的应用程序提供索引和搜索功能。Lucene 目前是 Apache Jakarta 家族中的一个开源项目。也是目前最为流行的基于 Java 开源全文检索工具包。
Elasticsearch 就是基于 Lucene 的。
demo
官网:lucene.apache.org/core/downlo…
可以使用国内镜像下载:mirrors.tuna.tsinghua.edu.cn/apache/luce…
下面是 Java 代码的简单例子,Maven 配置文件:
<dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <version>8.5.2</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-queryparser</artifactId> <version>8.5.2</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-analyzers-common</artifactId> <version>8.5.2</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-analyzers-smartcn</artifactId> <version>8.5.2</version> </dependency> 复制代码
测试分词
注意下面使用的 SmartChineseAnalyzer 是包 lucene-analyzers-smartcn。
@Test public void testAnalyzer() throws IOException { String chinese = "中华人民共和国简称中国,是一个有13亿人口的国家"; Analyzer analyzer = new SmartChineseAnalyzer(); TokenStream tokenStream = analyzer.tokenStream(chinese, new StringReader(chinese)); tokenStream.reset(); CharTermAttribute attribute = tokenStream.getAttribute(CharTermAttribute.class); System.out.println("分词结果:"); while (tokenStream.incrementToken()) { System.out.print(attribute.toString() + "|"); } analyzer.close(); } 复制代码
程序输出:
分词结果: 中华人民共和国|简称|中国|是|一个|有|13|亿|人口|的|国家| 复制代码
测试索引
下面程序创建了3个包含 id, title, content 的文档,其中每个类型都是 FieldType,使用 SmartChineseAnalyzer。索引目录是 web 根目录下的 indexDir 文件夹。
@Test public void testIndex() throws IOException { List<String> titleList = Lists.newArrayList("中国房企洛杉矶丑闻:百万美元行贿案遭曝光", "2025年之前美国不会退出WTO了", "特朗普退出总统竞选?"); List<String> contentList = Lists.newArrayList( "据调查,惠泽尔从中国房企手里收取了超过150万美元的现金贿赂,合人民币超过1000万元。", "美国特朗普政府上台以来,每隔几月,便总要传出有关“美国要退出世贸组织(WTO)”的消息。那么究竟美国能不能退出WTO?", "“共和党的操盘手首次提出了这样的可能性”,即川普总统可能会退出2020年总统竞选"); Path indexPath = Paths.get("indexDir"); Directory dir = FSDirectory.open(indexPath); // 设置新闻ID索引并存储 FieldType idType = new FieldType(); idType.setIndexOptions(IndexOptions.DOCS); idType.setStored(true); // 设置新闻标题索引文档、此项频率、位移信息、偏移量,存储并词条化 FieldType titleType = new FieldType(); titleType.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS); titleType.setStored(true); titleType.setTokenized(true); FieldType contentType = new FieldType(); contentType.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS); contentType.setStored(true); contentType.setTokenized(true); contentType.setStoreTermVectors(true); contentType.setStoreTermVectorOffsets(true); contentType.setStoreTermVectorPayloads(true); contentType.setStoreTermVectorPositions(true); Analyzer analyzer = new SmartChineseAnalyzer(); IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer); indexWriterConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE); IndexWriter indexWriter = new IndexWriter(dir, indexWriterConfig); for (int i = 0; i < titleList.size(); i++) { Document doc = new Document(); doc.add(new Field("id", Integer.toString(i + 1), idType)); doc.add(new Field("title", titleList.get(i), titleType)); doc.add(new Field("content", contentList.get(i), contentType)); indexWriter.addDocument(doc); } indexWriter.commit(); indexWriter.close(); dir.close(); } 复制代码
在运行代码后,会在根目录生成 indexDir 文件夹(代码中指定),如下图所示。
搜索索引
@Test public void testSearch() throws Exception { Path indexPath = Paths.get("indexDir"); Directory dir = FSDirectory.open(indexPath); IndexReader reader = DirectoryReader.open(dir); IndexSearcher searcher = new IndexSearcher(reader); Analyzer analyzer = new SmartChineseAnalyzer(); QueryParser parser = new QueryParser("title", analyzer); parser.setDefaultOperator(QueryParser.Operator.AND); Query query = parser.parse("房企"); System.out.println("query : " + query.toString()); TopDocs topDocs = searcher.search(query, 10); for (ScoreDoc sd : topDocs.scoreDocs) { Document doc = searcher.doc(sd.doc); System.out.println("docId: " + sd.doc); System.out.println("id: " + doc.get("id")); System.out.println("title: " + doc.get("title")); System.out.println("content: " + doc.get("content")); System.out.println("文档评分:" + sd.score); } } 复制代码
会搜出关于房企的信息。
Elasticsearch
全文搜索属于最常见的需求,开源的 Elasticsearch (以下简称 Elastic)是目前全文搜索引擎的首选。
它可以快速地储存、搜索和分析海量数据。维基百科、Stack Overflow、Github 都采用它。
Elastic 的底层是开源库 Lucene。但是,你没法直接用 Lucene,必须自己写代码去调用它的接口。Elastic 是 Lucene 的封装,提供了 REST API 的操作接口,开箱即用。
入门教程推荐阮一峰的《全文搜索引擎 Elasticsearch 入门教程》
官网是:www.elastic.co/cn/,上面内容很全面…
Elastic Stack
原来是通过 Logstash 进行日志收集与解析,Elasticsearch 作为搜索引擎,Kibana 作为可视化分析平台。但是 Logstash 有CPU和内存性能问题,官方开发了 Beats 数据采集工具。本文通过一个例子使用 Java 直接向 Elasticsearch 发送消息,并搭建 Kibana 数据可视化查询。
Docker 搭建 Elasticsearch
说明:经过试验,本文不使用最新版本,而是使用 Elasticsearch 6.8.4 版本,因为 Spring boot data 2.3 集成的版本就是 6.8.4,同时 Kibana 也要和 Elasticsearch 版本完全一致,否则会出各种奇葩问题。
docker 拉取 6.8.4 版本镜像:
docker pull elasticsearch:6.8.4 复制代码
启动镜像:
docker run -d -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:6.8.4 复制代码
这里使用简单模式,9200是 HTTP rest 协议,9300 是 tcp 协议。启动完成后,可以在浏览器中输入网址 0.0.0.0:9200,返回一下内容说明启动成功:
{ "name": "_jhdsik", "cluster_name": "docker-cluster", "cluster_uuid": "mpaTnrRaSY2_e3LFPz4QXw", "version": { "number": "6.8.4", "build_flavor": "default", "build_type": "docker", "build_hash": "bca0c8d", "build_date": "2019-10-16T06:19:49.319352Z", "build_snapshot": false, "lucene_version": "7.7.2", "minimum_wire_compatibility_version": "5.6.0", "minimum_index_compatibility_version": "5.0.0" }, "tagline": "You Know, for Search" } 复制代码
如果要看 log,可以使用命令:
docker logs -f 44afc4738685 复制代码
其中 44afc4738685 是 CONTAINER ID(可通过 docker ps 查看)。
修改 Elasticsearch 配置:
docker exec -it epic_beaver /bin/bash 复制代码
其中 epic_beaver 是我的 docker Elasticsearch 容器名称。进入 config 目录修改 elasticsearch.yml 文件。
cluster.name: "docker-cluster" network.host: 0.0.0.0 # xpack.security.enabled: true 复制代码
其中 xpack.security.enabled
在设置密码时使用,暂时不做设置。
修改完配置文件,重启容器。
Docker 搭建 Kibana
由于 Elasticsearch 使用的是 6.8.4 版本,Kibana 也要使用这个版本。
docker 下载 Kibana 镜像:
docker pull kebana:6.8.4 复制代码
修改配置文件(本例是 /root/etc/kibana.yml)
server.name: kibana server.host: "0" elasticsearch.hosts: [ "http://0.0.0.0:9200" ] # xpack.monitoring.ui.container.elasticsearch.enabled: true 复制代码
注:这里的 elasticsearch.hosts
配置跟 docker 网络模式有关,因为 elasticsearch 和 kibana 是 2 个独立的 docker 容器,直接设置 http://0.0.0.0:9200 可能不通,需要额外配置。本例使用的是阿里云的服务器,配置成了公网 IP,配置中改成了 0.0.0.0,读者需要自行替换。
docker 启动 Kibana:
docker run -d --restart=always --log-driver json-file --log-opt max-size=100m --log-opt max-file=2 --name kibana -p 5601:5601 -v /root/etc/kibana.yml:/usr/share/kibana/config/kibana.yml kibana:6.8.4 复制代码
在浏览器输入 0.0.0.0:5601,如果出现下面的界面,则表示启动成功。
启动失败可以通过 docker logs -f kibana_container_id
查看日志。
demo
本例使用 Spring boot,Maven pom 引入:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> 复制代码
在 application.yml 中增加:
data: elasticsearch: cluster-nodes: 0.0.0.0:9300 cluster-name: docker-cluster 复制代码
写一个实体类 EsNewsEntity,indexName 设置为 news_test:
@Data @Builder @Document(indexName = "news_test") public class EsNewsEntity { @Id private String id; private String title; private String content; @DateTimeFormat(pattern = "yyyy-MM-dd") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") private Date time; } 复制代码
整体查询使用 ElasticsearchRepository,里面有 CRUD 的操作,还有分页和排序,Spring data 使各种数据查询有了统一的操作接口,使用起来也很方便。
本例中只是想 ES 中简单插入一些数据,repository 如下:
public interface EsNewsRepository extends ElasticsearchRepository<EsNewsEntity, String> { } 复制代码
插入数据的代码如下,其中插入了2条 title 为 “韩国男星” 的文章,1条 title 为 “特大暴雨”的文章:
@Test public void testEs() { EsNewsEntity newsEntity = EsNewsEntity.builder().id("1").title("韩国男星") .content("我很喜欢大神、金钟国、光洙").time(DateTime.now().toDate()).build(); esNewsRepository.save(newsEntity); newsEntity = EsNewsEntity.builder().id("2").title("特大暴雨") .content("特大暴雨夜袭四川冕宁:山洪摧毁村庄 一家5口遇难").time(DateTime.now().toDate()).build(); esNewsRepository.save(newsEntity); newsEntity = EsNewsEntity.builder().id("3").title("韩国男星") .content("韩国男星身材管理多严格?金秀贤 Rain有八块腹肌").time(DateTime.now().toDate()).build(); esNewsRepository.save(newsEntity); System.out.println("es save ..."); } 复制代码
运行之后,在 Kibana->Management->Create index pattern,输入上面 News 的 indexName:news_test,设置 Date 为时间索引。
之后刷新页面,可以根据时间搜索新插入的几条数据。
问题总结
- 本例的 es 和 Kibana 没有使用密码登录,在实际应用过程中 es 可以限制 ip 访问。我在研究的过程中,设置好 es 和 Kibana 的密码后,没法使用 Spring data 直接与 es 通信,暂时放弃。
- es 和 Kibana 的版本一定要一致!
- spring-boot-starter-data-elasticsearch 的 es 版本并不高,最新版本已经是 7.8,但是 spring-boot-starter-data-elasticsearch 集成的仍然是 6.8,需要注意。如果必须使用最新版,需要额外配置。
- Kibana 在分析日志、数据分析时很强大。
- 本示例是 demo 演示,不要在生产环境中使用。
- 可以直接在腾讯云、阿里云上购买 es 服务,不过真心贵……小站点或个人开发者还是自行搭建比较划算。
- 《Lucene Elasticsearch 全文检索实战》这本书不建议买,书的内容浅显,排版和内容问题很多。比如有的代码分隔符是中文标点,书的前几章代码是深色背景,后几章代码没有背景……
Github 地址
Github 地址
公众号
coding 笔记、点滴记录,以后的文章也会同步到公众号(Coding Insight)中,希望大家关注^_^
这篇关于Lucene、Elasticsearch、Kibana 入门教程和环境搭建的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-10-04el-table 开启定时器下,表格的选中状态会消失是什么原因-icode9专业技术文章分享
- 2024-10-03如何安装和初始化飞牛私有云 fnOS?-icode9专业技术文章分享
- 2024-10-03如何安装 App 并连接到飞牛 NAS?-icode9专业技术文章分享
- 2024-10-03如何安装飞牛 TV 并连接到影视服务器?-icode9专业技术文章分享
- 2024-10-03如何在PVE和ESXI上安装飞牛私有云 fnOS?-icode9专业技术文章分享
- 2024-10-03fnOS国产最强NAS安装系统异常情况处理-icode9专业技术文章分享
- 2024-10-03飞牛NAS如何创建存储空间?-icode9专业技术文章分享
- 2024-10-03fnOS国产最强NAS硬盘会自动休眠吗?-icode9专业技术文章分享
- 2024-10-03fnOS国产最强NAS如何安装飞牛影视和创建媒体库?-icode9专业技术文章分享
- 2024-10-03fnOS国产最强NAS如何为家人朋友开通影视账号?-icode9专业技术文章分享