irpas技术客

教你快速入门ElasticSearch,超详细简单~_暗余_elasticsearch菜鸟教程

网络 773

教你快速入门ElasticSearch,超详细简单~ 一. 初探ElasticSearch 1.1 什么是ElasticSearch? ElasticSearch,简称为ES,它是一个开源的高扩展的分布式全文检索硬气,它可以近乎实时的存储、检索数据;它的扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。es也使用java开发并使用Lucene作为其核心来实现所有索引和搜索的功能。它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。 1.2 它与Solr的对比? Solr利用Zookeeper进行分布式管理,而ElasticSearch自身带有分布式协调管理的功能。Solr支持更多格式的数据,而ElasticSearch仅支持json文件格式。Solr官方提供的功能更多,而ElasticSearch本身更注重于核心功能,高级功能多依靠第三方插件提供。Solr在传统的搜索应用中表现好于ElasticSearch,但在实时搜索应用时效率明显低于ElasticSearch。 1.3 安装ElasticSearch ElasticSearch下载地址:下载地址bin目录中有windows和linux下的启动命令。启动(运行环境首先嘚要安装java,然后版本必须大于等于JDK1.8,它是基于Java运行的。)点击bin目录下的elasticsearch图标,即可执行成功,如果在linux环境下,则选择linux下的sh运行文件。如图所示: 启动成功过后,9300端口是Api对服务器的管理端口,9200是restful,http形式的端口。启动成功后如图所示: 页面进行访问: 1.4 安装ES的图形化界面插件 介绍: ElasticSearch不同于Solr自带图形化界面,我们可以通过安装ElasticSearch的head插件,完成图形化界面的效果,完成索引数据的查看。安装插件的方式有两种,在线安装和本地安装。本博客采用本地安装方式进行head插件的安装。(elasticsearch-50*以上版本安装head需要安装node和grunt) 安装步骤: 下载head插件:https://github.com/mobz/elasticsearch-head安装node.js,可参考博主之前的文章或者网上参考教程。(步骤为:官网下载node.js,然后按提示安装,输入node -v查看版本检查是否安装成功。)

它是运行在node.js上的,所以我们需要安装它。

将grunt安装为全局命令,Grunt是基于Node.js的项目构建工具,在cmd控制台输入如下执行命令:npm install -g grunt-cli 进入elasticsearch-head-master目录启动head,在命令提示符下输入命令:npm install grunt server

head是指的刚才下载的head插件。

启动成功后如图所示: 网页访问如图所示: 因为两个端口涉及到了跨域,在config/elasticsearch.yml中添加跨域配置: 添加好跨域后,重新启动es,然后在head上重新点击连接,图形界面安装完成。 1.5 ElasticSearch相关概念(术语) 概述: ElasticSearch是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在Elasticsearch中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。ElasticSearch比传统关系型数据库如下:Relational DB -> Databases -> Tables -> Rows -> Columns ElasticSearch -> Indices -> Types -> Documents -> Fields ElasticSearch核心概念: 索引Index: 一个索引就是一个拥有几分相似特征的文档的集合。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。在一个集群中,可以定义任意多的索引。 类型type: 在一个索引中,你可以定义一种或多种类型。一个类型是你的索引的一个逻辑上的分类/分区,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个类型。比如说,我们假设你运营一个博客平台并且将你所有的数据存储到一个索引中。在这个索引中你可以为用户数据定义一个类型,为博客数据定义另一个类型,当然,也可以为评论数据定义另一个类型。 字段Field: 相当于是数据表的字段,对文档数据根据不同的属性进行分类标识。 映射mapping mapping是处理数据的方式和规则方面做一些限制,如某个字段的数据类型、默认值、分析器、是否被索引等等,这些都是映射里面可以设置的,其它就是处理es里面数据的一些使用规则设置也叫做映射,按着最优规则处理数据对性能提高很大,因此才需要建立映射,并且需要思考如何建立映射才能对性能更好。 文档document 一个文档是一个可被索引的基础信息单元。比如,你可以拥有某一个客户的文档,某一个产品的一个文档,当然,也可以拥有某个订单的一个文档。文档以JSON(javascript Object Notation)格式来展示,而JSON是一个到处存在的互联网数据交互格式。在一个index/type里面,你可以存储任意多的文档。注意,尽管一个文档,物理上存在于一个索引之中,文档必须被索引/赋予一个索引的type. 接近实时NRT ElasticSearch是一个接近实时的搜索平台。这意味着,从索引一个文档直到这个文档能够被搜索到有一个轻微的延时(通常是1秒内)。 集群cluster: 集群就是由一个或多个节点组织在一起,它们共同持有整个的数据,并一起提供索引和搜索功能。 一个集群由一个唯一的名字标识,这个名字默认就是"ElasticSearch".这个名字是重要的,因为一个节点只能通过指定某个集群的名字,来加入这个集群。 节点node: 一个节点是集群中的一个服务器,作为集群的一部分,它存储数据,参与集群的索引和搜索功能。和集群类似,一个节点也是由一个名字来标识的,默认情况下,这个名字是一个随机的漫威漫画角色的名字,这个名字会在启动的时候赋予节点。这个名字对于管理工作来说挺重要的,因为在这个管理过程中,你会去确定网络中的哪些服务器对应于ElasticSearch集群中的哪些节点。一个节点可以通过配置集群的名称的方式来加入一个指定的集群。默认情况下,每个节点都会被安排加入到一个叫做"elasticsearch"的集群中,这意味着,如果你在你的网络中启动了若干个节点,并假定它们能够互相发现彼此,它们将会自动地形成并加入到一个叫做elasticsearch的集群中。在一个集群里,只要你想,可以拥有任意多个节点。而且,如果当前你的网络中没有运行任何elasticsearch节点,这时启动一个节点,会默认创建并加入一个叫做elasticsearch的集群。 分片和复制shards&replicas 二. 基于ElasticSearch常用功能演示 2.1 创建索引

使用图形化界面创建索引:

创建如图所示: 创建成功后,点击概览即可查看已创建成功的索引: 使用查询语句创建:

使用postman创建名称为:blog 的索引:

图示: 创建成功后,点击概览,发现新建的blog索引已创建成功:

使用mapping创建带field的索引:

创建索引后设置Mapping信息(创建type后为指定type设置mapping):

2.2 删除索引

图形化界面直接删除:

直接图标删除: 查询语句删除:

使用postman删除索引:

之前新增索引是put请求,所以此处删除索引则将请求改为delete,然后指定的索引名称不变即可删除。

2.3 添加文档 http方式添加: http方式添加: 查看已添加成功的数据: 注意:文档id可以不指定,为空时es会自动给我们分配一个随机字符串: 生成如图所示: 字符串如图所示: head图形界面添加: 添加如图所示: 使用数据浏览对字段过滤验证是否添加成功:

返回了需要查询的数据,说明添加成功!

2.4 删除文档 请求方式为delete,然后url中提供索引、类型、文档id,即可删除。图示如下:

删除的是_id这个,而不是内容中的id。_id这个才是文档的真正主键。

2.5 修改文档 图示:

修改文档跟新增的方式一样。如果此_id数据已存在,则会先删除老数据,然后再添加新的数据。如果此_id不存在,则会进行新增。

2.6 根据文档id查询文档

指定了index/type/field,所以能够查询到指定的文档数据。

2.7 根据关键词查询文档 查询: 查看返回结果: 2.8 查询文档-queryString查询 方法如图:

query条件任意写,default_field指代默认搜索域。它会先将查询的query内容先进行分词,然后再在默认的搜索域上进行查询。

2.9 使用head插件查询

2.10 分词器

标准分词器:

可以看到它是一个中文分成了每个字一个词,这不是我们想要的效果。我们需要的效果是:我、是、程序、程序员。

如何解决?

我们需要对中文支持良好的分词器的支持。支持中文分词器的分词有很多,word分词器、庖丁解牛、盘古分词、ansj分词等,但我们最常用的还是IK分词器。

IK分词器简介:

图示: 安装步骤: 网上下载Ik分词器,然后解压缩,放到es中的plugin文件夹中,然后重启es服务即可。

使用IK分词器效果:

概述:IK提供了两个分词算法ik_smart和ik_max_word.其中ik_smart为最少切分,ik_max_word为最细粒度切分。最小切分:在浏览器中输入地址:http://127.0.0.1:9200/_analyze?analyzer=ik_smart&pretty=true&text=我是程序员

分词结果为: 我,是,程序,程序员

最细粒度切分:在浏览器中输入地址:http://127.0.0.1:9200/_analyze?analyzer=ik_max_word&text=我是程序员

分词结果为: 我,是,程序,程序员,员。 说明它的拆分结果更细,分词结果更多。

ik分词器的使用:

创建索引库: 添加数据: 查询数据: 按条件查询: querystring查询: 使用head里面的搜索: 三. ElasticSearch集群 3.1 ElasticSearch架构及说明 概述: 集群架构说明: 3.2 集群架构搭建 准备工作: 删除data目录:(如果是单机版es升级到集群,我们首先查看data目录,保证data目录里面不能有数据(建立索引保存的数据信息))

不删除会导致集群搭建不成功

将我们单机版的es改名为elasticsearch-cluster,然后配置好ik分词器,cors跨域等配置,再复制三份,分别为如图所示:: >修改elasticsearch-cluster/node*/config/elasticsearch.yml文件: node1节点: node2节点: node3节点:

主要配置了节点名称和端口号。

分别各个节点启动,然后会自动连接起来变成集群,连接任意一个端口进行验证: 创建索引库: 创建索引: 查询分片验证: 四、使用java客户端简单操作es 4.1 使用java客户端完成创建索引库及文档的添加 大致步骤: 创建一个java工程编写jar包,添加maven的坐标编写测试方法实现创建索引库: 创建一个Settings对象,相当于是一个配置信息。主要配置集群的名称创建一个客户端Client对象使用client对象创建一个索引库关闭client对象 步骤如下:

pom.xml中引入es的依赖:

创建测试类并创建索引库:

public class ElasticSearchClientTest{ @Test public void createIndex() throws Exception{ //1. 创建一个Settings对象,相当于是一个配置信息。主要配置集群的名称。 Settings settings= Settings.builder() .put("cluster.name","my-elasticsearch") .build(); // 2. 创建一个客户端Client对象 TransportClient client= new PrebuiltTransportClient(settings); client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9301)); client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9302)); client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9303)); // 3. 使用client对象创建一个索引库 client.admin().indices().prepareCreate("index_hello")' // 执行操作 .get(); // 4. 关闭client对象 client.close(); } } 4.2 使用Java客户端设置Mappings 大致步骤: 创建一个Settings对象创建一个Client对象创建一个mapping信息,应该是一个json数据,可以是字符串,也可以是XContextBuilder对象使用client向es服务器发送mapping信息关闭client对象 具体测试代码:(在上面的Test类中新建一个Test方法):@Test public void setMappings() throws Exception{ //1. 创建一个Settings对象,相当于是一个配置信息。主要配置集群的名称。 Settings settings= Settings.builder() .put("cluster.name","my-elasticsearch") .build(); // 2. 创建一个客户端Client对象 TransportClient client= new PrebuiltTransportClient(settings); client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9301)); client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9302)); client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9303)); // 3. 创建一个Mappings信息 XContentBuilder builder = XContentFactory.jsonBuilder() .startObject() .startObject("article") .startObject("properties") .startObject("id") .field("type","long") .field("store",true) .endObject() .startObject("title") .field("type","text") .field("store",true) .field("analyzer","ik_smart") .endObject() .startObject("content") .field("type","text") .field("store",true) .field("analyzer","ik_smart") .endObject() .endObject() .endObject() .endObject() // 使用client把mapping信息设置到索引库中 client.admin().indices() // 设置要做映射的索引 .preparePutMapping("index_hello") // 设置要做映射的type .setType("article") // mapping信息,可以是XContentBuilder对象可以是json格式的字符串 .setSource(builder) // 执行操作 .get(); // 关闭连接 client.close(); } 4.3 使用java客户端完成文档新增 大致步骤: 创建一个Settings对象创建一个Client对象创建一个文档对象,创建一个json格式的字符串,或者使用XContentBuilder使用Client对象把文档添加到索引库中关闭Client 操作步骤: 我们每次都要创建Settings、Client对象,所以我们将这个操作进行提出来:public class ElasticSearchClientTest{ private TransportClient client; @Before public void init() throws Exception{ // 创建一个Settings对象 Settings settings = Settings.builder().put("cluster.name","my-elasticsearch").build(); // 创建一个TransPortClient对象 TransportClient client= new PreBuiltTransportClient(settings); client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9301)); client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9302)); client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9303)); } }

这样子在每次类被实例化之前就会自动init初始化client内的内容了。

创建文档:@Test public void testAddDocument() throws Exception{ // 创建一个文档对象 XContentBuilder builder = XContentFactory.jsonBuilder() .startObject() .field("id",1l) .field("title","这是数据的标题") .field("content","这是数据的内容") .endObject(); // 把文档对象添加到索引库 client.prepareIndex() // 设置索引名称 .setIndex("index_hello") // 设置type .setType("article") // 设置文档的id,如果不设置的话会自动生成一个 .setId("id") // 设置文档信息 .setSource(builder) // 执行操作 .get(); // 关闭客户端 client.close(); } 创建文档的第二种方式(使用对象的方式进行创建): pom.xml中引入jackson的相关依赖: 创建一个pojo类: 添加文档(先使用工具类把pojo转换成json字符串,然后把文档写入索引库) 五. 使用java客户端实现对es的搜索功能 5.1 根据id查询 大致步骤: 创建一个Client对象创建一个查询对象,可以使用QueryBuilders工具类创建QueryBilder对象。使用client执行查询得到查询的结果取查询结果的总记录数取查询结果列表关闭client 代码演示:public class SearchIndexTest{ private TransportClient client; @Before public void init() throws Exception{ // 创建一个Settings对象 Settings settings = Settings.builder().put("cluster.name","my-elasticsearch").build(); // 创建一个TransPortClient对象 TransportClient client= new PreBuiltTransportClient(settings); client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9301)); client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9302)); client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"),9303)); } @Test public void testSearchById() throws Exception{ // 创建一个查询对象 QueryBuilder queryBuilder = QueryBuilders.idsQuery().addIds("1","2"); // 执行查询 SearchResponse searchResponse = client.prepareSearch("index_hello") .setTypes("article") .setQuery(queryBuilder) .get(); // 取查询结果 SearchHits searchHits = searchResponse.getHits(); // 取查询结果的总记录数 System.out.println("查询结果总记录数:"+ searchHits.getTotalHits()); // 查询结果列表 Iterator<SearchHit> iterator = searchHits.iterator(); while(iterator.hasNext()){ SearchHit searchHit = iterator.next(); // 打印文档对象,以json格式输出 System.out.println(searchHit.getSourceAsString()); // 取文档的属性 Map<String,Object> document = searchHit.getSource(); System.out.println(document.get("id0")); System.out.println(document.get("title")); System.out.println(document.get("content")); } } } 5.2 根据Item查询 @Test public void testQueryByTerm() throws Exception{ // 创建一个QueryBuilder对象 // 参数1: 要搜索的字段 // 参数2: 要搜索的关键词 QueryBuilder queryBuilder = QueryBuilders.termQuery("title","北方") // 执行查询 SearchResponse searchResponse = client.prepareSearch("index_hello") .setTypes("article") .setQuery(queryBuilder) .get(); // 取查询结果 SearchHits searchHits = searchResponse.getHits(); // 取查询结果的总记录数 System.out.println("查询结果总记录数:"+ searchHits.getTotalHits()); // 查询结果列表 Iterator<SearchHit> iterator = searchHits.iterator(); while(iterator.hasNext()){ SearchHit searchHit = iterator.next(); // 打印文档对象,以json格式输出 System.out.println(searchHit.getSourceAsString()); // 取文档的属性 Map<String,Object> document = searchHit.getSource(); System.out.println(document.get("id0")); System.out.println(document.get("title")); System.out.println(document.get("content")); } } 5.3 根据queryString查询 @Test public void testQueryStringQuery() throws Exception { // 创建一个QueryBuilder对象 QueryBuilder queryBuilder = QueryBuilders.queryStringQuery("速度与激情").defaultField("title"); // 执行查询 SearchResponse searchResponse = client.prepareSearch("index_hello") .setTypes("article") .setQuery(queryBuilder) .get(); // 取查询结果 SearchHits searchHits = searchResponse.getHits(); // 取查询结果的总记录数 System.out.println("查询结果总记录数:"+ searchHits.getTotalHits()); // 查询结果列表 Iterator<SearchHit> iterator = searchHits.iterator(); while(iterator.hasNext()){ SearchHit searchHit = iterator.next(); // 打印文档对象,以json格式输出 System.out.println(searchHit.getSourceAsString()); // 取文档的属性 Map<String,Object> document = searchHit.getSource(); System.out.println(document.get("id0")); System.out.println(document.get("title")); System.out.println(document.get("content")); } } 5.4 分页查询 大致步骤: 在client对象执行查询之前,设置分页信息。然后再执行查询:// 执行查询 SearchResponse searchResponse = client.prepareSearch("index_hello") .setTypes("article") .setQuery(queryBuilder) // 设置分页信息 .setFrom(0) // 每页显示的行数 .setSize(5) .get(); 注意: 分页需要设置两个值,from和sizefrom: 起始行号,从0开始;size:每页显示的记录数 代码演示: 5.5 查询结果高亮显示 大致步骤: 高亮的配置: 设置高亮显示的字段设置高亮显示的前缀设置高亮显示的后缀 在client对象执行查询之前,设置高亮显示的信息。遍历结果列表时可以从结果中取高亮结果。 代码演示: 新增高亮对象: 查询client内设置高亮信息: 拿到查询结果时打印高亮信息: 获取更详细的高亮信息(改造步骤3): 六、使用Spring Data ElasticSearch操作ES 6.1 完成Spring Data ElasticSearch的环境搭建

什么是Spring Data?

Spring Data 是一个用于简化数据库访问,并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快捷,并支持map-reduce框架和云计算数据服务。Spring Data可以极大的简化JPA的写法,可以在几乎不用写实现的情况下,实现对数据的访问和操作。除了CRUD外,还包括分页、排序等一些常用的功能。Spring Data 的官网Spring Data 常用的功能模块如下:

什么是Spring Data ElasticSearch?

Spring Data ElasticSearch基于Spring Data API简化ElasticSearch操作,将原始操作ElasticSearch的客户端API进行封装。Spring Data为ElasticSearch项目提供集成搜索引擎。Spring Data ElasticSearch POJO的关键功能区域为中心的模型与ElasticSearch交互,可以轻松地编写一个存储数据访问层;官方网站

搭建步骤:

pom.xml引入Spring Data ElasticSearch: 方案一:在resource目录下创建配置文件,配置elasticSearch: 方案二:在application.yml中配置:spring: application: name: es-application data: elasticsearch: cluster-nodes: 192.168.227.136:9300 cluster-name: elasticsearch

推荐此方案

创建实体类: 创建一个Repository:

它继承了ElasticSearchRepository,里面会提供一些常用的方法

6.2 完成Spring Data ElasticSearch的基本增删改查操作

创建索引:

添加文档:

删除文档:

更新文档:

它会把原来的这个id匹配的文档给删除掉,然后再新增,就实现了类似更新的功能。

查询指定id的文档和查询所有:

6.3 自定义查询方法 常用查询命名规则: 根据规则定义findByTitle: 定义方法: 查询代码: 根据规则定义or查询方式: 定义方法: 查询代码: 根据规则定义or查询方式且带分页查询: 定义方法: 查询代码:

自定义查询方法,我们需要根据SpringDataES 的命名规则来命名,这样我们定义了接口就会自动实现功能。如果我们没有实现分页的话,无论es中匹配的有多少条数据,最多也只会默认给我们返回10条。如果需要指定分页,可以使用上面的带分页查询方式。

6.4 使用NativeSearchQuery查询

直接使用章节5.5中的查询方式,查询的内容比如:“我是程序员”,那么它不会再将结果进行分词,所以匹配的结果是我是程序员这个原子词汇。如果要对查询条件再分词,比如我是程序员分词,能够匹配到:我、是、程序、程序员、员的所有数据,我们需要使用queryString方式进行查询。

大致步骤:

创建一个NativeSearchQuery对象,设置查询条件,QueryBuiilder对象使用ElasticSearchTemplate 对象执行查询取查询结果

代码演示:

@Test public void testNativeSearchQuery() throws Exception{ // 创建一个查询对象 NativeSearchQuery query = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.queryStringQUery("Maven是一个构建工具").defaultField("title")) .withPageable(PageRequest.of(0,15)) .build(); // 执行查询 List<Article> articleList = template.queryForList(query,Article.class); articleList.forEach(a-> System.out.println(a)) }

稍微麻烦点,但是功能更强,灵活性更高


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #12