Elasticsearch简介及SpringBoot整合ES实例

Elasticsearch简介

1.1 Elasticsearch以下简称ES定义

Elasticsearch 是一个开源的搜索引擎。 建立在全文搜索引擎库 Apache Lucene 基础之上。它的内部使用 Lucene 做索引与搜索,但是它的目的是使全文检索变得简单,通过隐藏 Lucene 的复杂性,取而代之的提供一套简单一致的 RESTful API。

Elasticsearch 不仅仅只是一个全文搜索引擎。 它可以被下面这样准确的形容:、

一个分布式的实时文档存储,每个字段可以被索引与搜索——作数据库用

一个分布式实时分析搜索引擎,能胜任上百个服务节点的扩展,并支持PB 级别的结构化或者非结构化数据

1.2 ES发展历程

Elasticsearch 后来作为一家公司(Elastic公司)进行运作,定位为数据搜索和分析平台。ES现在可以与Java、Ruby、Python、PHP、Perl、.NET等多种客户端集成。也可与Hadoop、Spark等大数据分析平台进行集成,功能十分强大。

基于Elasticsearch衍生出了一系列开源软件,统称为 Elatic Stack。

 

 

说明:

因为logstash比较耗内存,所以用Beats来替代。

为避免版本混乱,从5.0开始,Elastic公司将各组件的版本号统一。使用时,各组件版本号应一致(版本号形式:x.y.z,z可以不同)。

1.3 ES特性

官网的介绍: https://www.elastic.co/cn/products/elasticsearch

速度快、易扩展、弹性、灵活、操作简单、多语言客户端、X-Pack、hadoop/spark强强联手、开箱即用。

分布式:横向扩展非常灵活
全文检索:基于lucene的强大的全文检索能力;
近实时搜索和分析:数据进入ES,可达到近实时搜索,还可进行聚合分析
高可用:容错机制,自动发现新的或失败的节点,重组和重新平衡数据
模式自由:ES的动态mapping机制可以自动检测数据的结构和类型,创建索引并使数据可搜索。
RESTful API:JSON + HTTP

1.4 ES应用场景案例

 

维基百科使用Elasticsearch来进行全文搜做并高亮显示关键词,以及提供search-as-you-type、did-you-mean等搜索建议功能。

GitHub使用Elasticsearch来检索超过1300亿行代码

英国卫报使用Elasticsearch来处理访客日志,以便能将公众对不同文章的反应实时地反馈给各位编辑

1.5 ES架构

 

说明:

Gateway是ES用来存储索引的文件系统,支持多种类型。
Gateway的上层是一个分布式的lucene框架。
Lucene之上是ES的模块,包括:索引模块、搜索模块、映射解析模块等
ES模块之上是 Discovery、Scripting和第三方插件。Discovery是ES的节点发现模块,不同机器上的ES节点要组成集群需要进行消息通信,集群内部需要选举master节点,这些工作都是由Discovery模块完成。支持多种发现机制,如 Zen 、EC2、gce、Azure。Scripting用来支持在查询语句中插入javascript、python等脚本语言,scripting模块负责解析这些脚本,使用脚本语句性能稍低。ES也支持多种第三方插件。
再上层是ES的传输模块和JMX.传输模块支持多种传输协议,如 Thrift、memecached、http,默认使用http。JMX是java的管理框架,用来管理ES应用。
最上层是ES提供给用户的接口,可以通过RESTful接口和ES集群进行交互。

1.6 ES核心概念

Near Realtime(NRT) 近实时数据提交索引后,立马就可以搜索到。


Cluster 集群一个集群由一个唯一的名字标识,默认为“elasticsearch”。集群名称非常重要,具有相同集群名的节点才会组成一个集群。集群名称可以在配置文件中指定。


Node 节点:存储集群的数据,参与集群的索引和搜索功能。像集群有名字,节点也有自己的名称,默认在启动时会以一个随机的UUID的前七个字符作为节点的名字,你可以为其指定任意的名字。通过集群名在网络中发现同伴组成集群。一个节点也可是集群。


Index 索引一个索引是一个文档的集合(等同于solr中的集合)。每个索引有唯一的名字,通过这个名字来操作它。一个集群中可以有任意多个索引。
Type 类型:指在一个索引中,可以索引不同类型的文档,如用户数据、博客数据。从6.0.0 版本起已废弃,一个索引中只存放一类数据。
Document 文档:被索引的一条数据,索引的基本信息单元,以JSON格式来表示。
Shard 分片:在创建一个索引时可以指定分成多少个分片来存储。每个分片本身也是一个功能完善且独立的“索引”,可以被放置在集群的任意节点上。分片的好处:允许我们水平切分/扩展容量、可在多个分片上进行分布式的、并行的操作,提高系统的性能和吞吐量。

注意:分片数创建索引时指定,创建后不可改了。备份数可以随时改。
Replication 备份: 一个分片可以有多个备份(副本)。备份的好处:
高可用。一个主分片挂了,副本分片就顶上去
扩展搜索的并发能力、吞吐量。搜索可以在所有的副本上并行运行。-高并发下副本也可搜索

为了方便理解,一个ES和数据库的对比

RDBMS

Elasticsearch

数据库(database)

索引(index)

表(table)

类型(type)(6.0.0后废弃)

行(row)

文档(document)

列(column)

字段(field)

表结构(schema)

映射(mapping)

索引

反向索引

SQL

查询DSL

SELECT * FROM TABLE

GET http://...

INSERT INTO TABLE ,UPDATE TABLE

PUT http://...

DELETE

DELETE http://...

...

...

 

 

ES安装及使用

2.1安装

官网下载地址: https://www.elastic.co/downloads/elasticsearch

 

JDK版本: 1.8

2.2启动

解压安装包到相应路径,进入bin目录中双击elasticsearch.bat等待启动完毕。

打开浏览器,输入 http://localhost:9200 ,显式以下画面,说明ES安装成功。

 

 

2.3 ES配置说明

elasticsearch的config文件夹里面有两个配置件:elasticsearch.yml和logging.yml,第一个是es的基本配置文件,第二个是日志配置文件,es也是使用log4j来记录日 志的,所以logging.yml里的设置按普通log4j配置文件来设置就行了。下面主要说下elasticsearch.yml这个文件中的配置项:

 

cluster.name: elasticsearch

配置es的集群名称,默认是elasticsearch,es会自动发现在同一网段下的es,如果在同一网段下有多个集群,就可以用这个属性来区分不同的集群。

 

node.name: "Franz Kafka"

节点名,默认随机指定一个name列表中名字,该列表在es的jar包中config文件夹里name.txt文件中,其中有很多作者添加的有趣名字。

node.master: true

指定该节点是否有资格被选举成为node,默认是true,es是默认集群中的第一台机器为master,如果这台机挂了就会重新选举master。

node.data: true

指定该节点是否存储索引数据,默认为true。

index.number_of_shards: 5

设置默认索引分片个数,默认为5片。

index.number_of_replicas: 1

设置默认索引副本个数,默认为1个副本。

path.conf: /path/to/conf

设置配置文件的存储路径,默认是es根目录下的config文件夹。

path.data: /path/to/data

设置索引数据的存储路径,默认是es根目录下的data文件夹,可以设置多个存储路径,用逗号隔开,例:

path.data: /path/to/data1,/path/to/data2

path.work: /path/to/work

设置临时文件的存储路径,默认是es根目录下的work文件夹。

path.logs: /path/to/logs

设置日志文件的存储路径,默认是es根目录下的logs文件夹

path.plugins: /path/to/plugins

设置插件的存放路径,默认是es根目录下的plugins文件夹

下面是一些查询时的慢日志参数设置

index.search.slowlog.level: TRACE

index.search.slowlog.threshold.query.warn: 10s

index.search.slowlog.threshold.query.info: 5s

index.search.slowlog.threshold.query.debug: 2s

index.search.slowlog.threshold.query.trace: 500ms

index.search.slowlog.threshold.fetch.warn: 1s

index.search.slowlog.threshold.fetch.info: 800ms

index.search.slowlog.threshold.fetch.debug:500ms

index.search.slowlog.threshold.fetch.trace: 200ms

2.4 ES端口说明

9300端口: ES节点之间通讯使用,9300是tcp通讯端口,集群间和TCPClient  都走的它。
9200端口: ES节点和外部通讯使用,9200是http协议的RESTful接口。

 

2.5安装可视化工具Kibana

2.5.1 安装

下载安装包,需要和ES版本匹配:

https://www.elastic.co/downloads/kibana,解压到安装目录即可

2.5.2 配置

在目录config/kibana.yml中配置 elasticsearch.url的值为 ES的访问地址

 

2.5.3 启动

启动bin/kibana

访问地址:http://localhost:5601

 

2.6集成Ikanalyzer

2.6.1 安装

获取 ES-IKAnalyzer插件,需要和ES版本一致

地址: https://github.com/medcl/elasticsearch-analysis-ik/releases

将 ik的压缩包解压到 ES安装目录的plugins/目录下,重启ES,出现如下图说明安装成功

Springboot整合Elasticsearch案例

3.1 springboot配置

pom 文件配置:

s

<!--添加spring-data-elasticsearch的依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>e

application.yaml配置:

 

data:
  elasticsearch:
    cluster-name: elasticsearch #默认为elasticsearch
    cluster-nodes: 127.0.0.1:9300 #配置es节点信息,逗号分隔,如果没有指定,则启动ClientNode
  properties:
    path:
      logs: ./elasticsearch/log #elasticsearch日志存储目录
      data: ./elasticsearch/data #elasticsearch数据存储目录

3.2 数据存储

将D:\\Lucene_Document 路径下的文件解析存储到es中

@Document(indexName = "test-file",type = "file")
@Mapping(mappingPath= "index_file.json")
@Data
public class DocFile {

    @Id
    private String id;

    //@Field(analyzer = "ik_max_word",searchAnalyzer = "ik_max_word")
    private String fileName;

    //@Field(analyzer = "ik_max_word",searchAnalyzer = "ik_max_word")
    private String fileContent;

    //@Field
    private String filePath;

    private Integer sort;

}

 

public interface FileRepository extends ElasticsearchRepository<DocFile,String> {
    List<DocFile> findDocFileByFileContent(String content);
}

 

 

@Override
public void init() {
    //原始文件
    File file = new File("D:\\Lucene_Document");
    List<DocFile> list = new ArrayList<>();
    int count = 0;
    for (File f : file.listFiles()) {
        count ++;
        //文件名
        String fileName = f.getName();
        //文件内容
        String fileContent = TikaUtil.getContext(f);
        //文件路径
        String path = f.getPath();
        DocFile doc= new DocFile();
        doc.setId(UUID.randomUUID().toString());
        doc.setFileName(fileName);
        doc.setFileContent(fileContent);
        doc.setFilePath(path);
        doc.setSort(count);
        list.add(doc);
    }
    fileRepository.saveAll(list);
}

 

3.3 数据查询

public List<DocFile> query(String content) {
    BoolQueryBuilder builder = QueryBuilders.boolQuery();
    //builder下有must、should以及mustNot 相当于sql中的and、or以及not
    //设置要查询博客的标题中含有关键字
    builder.must(new QueryStringQueryBuilder(content));
    //按照博客的评论数的排序是依次降低
    FieldSortBuilder sort = SortBuilders.fieldSort("sort").order(SortOrder.DESC);
    //2.构建查询
    NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
    //将搜索条件设置到构建中
    nativeSearchQueryBuilder.withQuery(builder);
    //设置分页(从第一页开始,一页显示10条) 将分页设置到构建中
    nativeSearchQueryBuilder.withPageable(new PageRequest(0, 10));
    //将排序设置到构建中
    nativeSearchQueryBuilder.withSort(sort);
    //生产NativeSearchQuery
    SearchQuery query = nativeSearchQueryBuilder.build();
    //3.执行方法1
    Page<DocFile> page = fileRepository.search(query);
    //执行方法2:注意,这儿执行的时候还有个方法那就是使用elasticsearchTemplate
    //执行方法2的时候需要加上注解
    //@Autowired
    //private ElasticsearchTemplate elasticsearchTemplate;
    // List<DocFile> blogList = elasticsearchTemplate.queryForList(query, DocFile.class);
    //4.获取总条数(用于前端分页)
    int total = (int) page.getTotalElements();
    //5.获取查询到的数据内容(返回给前端)
    List<DocFile> list = page.getContent();
    return list;
}

 

@Override
public List<DocFile> search(String content) {
    QueryBuilder builder = new QueryStringQueryBuilder(content);
    //高亮显示规则
    HighlightBuilder highlightBuilder = new HighlightBuilder().field("fileName").field("fileContent").preTags("<span style='color:red'>").postTags("</span>");
    SearchQuery q = new NativeSearchQueryBuilder()
            //.withIndices("test-file").withTypes("file")
            .withSort(SortBuilders.fieldSort("sort").order(SortOrder.DESC))
            .withHighlightBuilder(highlightBuilder)
            .withHighlightFields(new HighlightBuilder.Field("fileName"),new HighlightBuilder.Field("fileContent"))
            .withQuery(builder).build();
    List<DocFile> fileList = elasticsearchTemplate.query(q, response -> {
        SearchHits hits = response.getHits();
        List<DocFile> bl = new ArrayList<>();
        if (hits.getHits().length <= 0) {
            return bl;
        }
        for (SearchHit searchHit : hits) {
            DocFile file = new DocFile();
            String bookJson = searchHit.getSourceAsString();
            if (bookJson == null || "".equals(bookJson)) {
                continue;
            }
            ObjectMapper mapper = new ObjectMapper();
            try {
                file =  mapper.readValue(bookJson,file.getClass());
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (searchHit.getHighlightFields().size() > 0) {
                if (searchHit.getHighlightFields().get("fileName") != null) {
                    String highLightName = searchHit.getHighlightFields().get("fileName").fragments()[0].toString();
                    file.setFileName(highLightName);
                }
                if (searchHit.getHighlightFields().get("fileContent") != null) {
                    String highLightContent = searchHit.getHighlightFields().get("fileContent").fragments()[0].toString();
                    file.setFileContent(highLightContent);
                }
            }
            bl.add(file);
        }
        return bl;
    });
    return fileList;
}

 

controller层:

@RequestMapping("/search")
@ResponseBody
public List<DocFile> search(String content) {
    return fileService.search(content);
}

页面返回结果:

 

  • 6
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值