Java微服务篇4——Elastic search

1、Elastic search安装配置

Elastic search官方:https://www.elastic.co/cn/products/elasticsearch

Elastic search6.2.4 百度云:https://pan.baidu.com/s/1JyQok8Nija4gYhcjh-HWcw提取码:isa2

解压即可

在config/elasticsearch.yml修改

# ----------------------------------- Paths ------------------------------------
#
# Path to directory where to store the data (separate multiple locations by comma):
#
path.data: /path/to/data
#
# Path to log files:
#
path.logs: /path/to/logs

启动bin目录下的elasticsearch.bat/elasticsearch.sh

访问

http://localhost:9200/

2、kibana安装

Kibana是一个基于Node.js的Elasticsearch索引库数据统计工具,可以利用Elasticsearch的聚合功能, 生成各种图表,如柱形图,线状图,饼图等。 而且还提供了操作Elasticsearch索引数据的控制台

kibana6.2.4 百度云:https://pan.baidu.com/s/1AlD34ZYvHqtVwaapRh3tPA提取码:p8gr

在config/kibana.yml修改

elasticsearch.url: "http://localhost:9200"

3、ik分词器

elasticsearch-analysis-ik-6.2.4 百度云:https://pan.baidu.com/s/1L4_fQIgLmLoLpKL8sXAAFw提取码:8k05

解压elasticsearch-analysis-ik-6.2.4.zip后,将解压后的文件夹拷贝到elasticsearch-6.2.4\plugins 下,并重命名文件夹为ik

重启即可

测试

GET /_analyze
{"text": "我是中国人"
}

GET /_analyze
{"analyzer": "ik_max_word","text": "我是中国人"
}

GET /_analyze
{"analyzer": "ik_min_word","text": "我是中国人"
}

4、elasticsearch-head

elasticsearch-head 百度云:https://pan.baidu.com/s/1JsOvr64gb5xNbkPPJafyag提取码:6khj

5、elastic search操作

映射属性数据类型

一级分类 二级分类 具体类型 类型描述
核心类型 字符串类型 text 当一个字段是要被全文搜索的,比如Email内容、产品描述,应该使用text类型
设置text类型以后,字段内容会被分析,在生成倒排索引以前,字符串会被分析器分成一个一个词项
text类型的字段不用于排序,很少用于聚合
keyword keyword类型适用于索引结构化的字段,比如email地址、主机名、状态码和标签
如果字段需要进行过滤(比如查找已发布博客中status属性为published的文章)、排序、聚合
keyword类型的字段只能通过精确值搜索到
整数类型 byte -128~127
short -32768~32767
integer -231~231-1
long -263~263-1
浮点类型 float 32位单精度IEEE 754浮点类型
double 64位双精度IEEE 754浮点类型
half_float 16位半精度IEEE 754浮点类型
scaled_float 缩放类型的的浮点数
逻辑类型 boolean true,false
日期类型 date (1)日期格式的字符串,比如 “2018-01-13” 或 “2018-01-13 12:10:30”
(2)long类型的毫秒数
(3)integer的秒数seconds-since-the-epoch
范围类型 range
二进制类型 binary 进制字段是指用base64来表示索引中存储的二进制数据,可用来存储二进制形式的数据,例如图像
复合类型 数组类型 array (1)字符数组: [ “one”, “two” ]
(2)整数数组: productid:[ 1, 2 ]
(3)对象(文档)数组: “user”:[ { “name”: “Mary”, “age”: 12 }, { “name”: “John”, “age”: 10 }]
对象类型 object JSON对象,文档会包含嵌套的对象
嵌套类型 nested 用于JSON对象数组
地理类型 地理坐标类型 geo_point 纬度/经度积分
地理地图 geo_shape 用于多边形等复杂形状
特殊类型 IP类型 ip 用于存储IPv4或者IPv6的地址
范围类型 completion 提供自动完成建议
令牌计数类型 token_count 计算字符串中令牌的数量

index

是否被索引

index的默认值就是true,也就是说你不进行任何配置,所有字段都会被索引,有些字段是我们不希望被索引的,比如商品的图片信息(URL),就需要手动设置index为false

stroe

是否额外存储

在lucene里,如果一个字段的store设置为false,那么在文档列表中就不会有这个字段的 值,用户的搜索结果中不会显示出来,但是在Elasticsearch中,即便store设置为false,也可以搜索到结果

原因是Elasticsearch在创建文档索引时,会将文档中的原始数据备份,保存到一个叫做 _source 的属性 中。而且我们可以通过过滤 _source 来选择哪些要显示,哪些不显示

如果设置store为true,就会在 _source 以外额外存储一份数据,多余,因此一般我们都会将store设 置为false,事实上,store的默认值就是false

在某些情况下,这对 store 某个领域可能是有意义的。例如,如果您的文档包含一个 title ,一个 date 和一个非常大的 content 字段,则可能只想检索the title 和the date 而不必从一个大 _source 字段中提取这些字段

boost

网站权重:网站权重是指搜索引擎给网站(包括网页)赋予一定的权威值,对网站(含网页)权威的评估评价。一 个网站权重越高,在搜索引擎所占的份量越大,在搜索引擎排名就越好。提高网站权重,不但利于网站(包括网 页)在搜索引擎的排名更靠前,还能提高整站的流量,提高网站信任度。所以提高网站的权重具有相当重要的意 义。 权重即网站在SEO中的重要性,权威性。英文:Page Strength。

  • 权重不等于排名
  • 权重对排名有着 非常大的影响
  • 整站权重的提高有利于内页的排名

5.1、库操作(database)

# 添加索引库
PUT /索引库名
# 获取索引库信息
GET /索引库名
# 删除索引库
DELETE /索引库名

5.2、类型及映射操作(表)

创建数据库表需要设置字段约束,索引库也一样,在创建索引库的类型时,需要知道这个类型下 有哪些字段,每个字段有哪些约束信息,这就叫做 字段映射(mapping)

# 添加类型及映射1(向索引库追加类型及映射)
PUT winkto/_mapping/goods
{"properties": {"title": {"type": "text","analyzer": "ik_max_word"},"images": {"type": "keyword","index": "false"},"price": {"type": "float"}}
}
# 添加类型及映射2(在索引库创建时添加类型及映射)
PUT /winkto2
{"settings": {},"mappings": {"goods": {"properties": {"title": {"type": "text","analyzer": "ik_max_word"}}}}
}
# 查看类型及映射
GET winkto/_mapping
GET winkto/_mapping/goods

5.3、追加数据

# 追加数据(随机id)
POST /winkto/goods/
{"title":"小米10","images":"http://image.lagou.com/12479122.jpg","price":2699.00
}

# 追加数据(指定id)
POST /winkto/goods/sadhsahduashfusahdi
{"title":"华为","images":"http://image.lagou.com/12479122.jpg","price":4699.00
}

# 获取数据
GET /winkto/goods/xqurVHsB1mHhNfuBSw0p

5.4、删除数据

DELETE /winkto/goods/sadhsahduashfusahdi

5.5、查询

语法

GET /索引库名/_search
{"query":{"查询类型":{"查询条件":"查询条件值"}}
}

5.5.1、查询所有

GET /winkto/_search
{"query":{"match_all":{}}
}
{"took": 2,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 2,"max_score": 1,"hits": [{"_index": "winkto","_type": "goods","_id": "xqurVHsB1mHhNfuBSw0p","_score": 1,"_source": {"title": "小米10","images": "http://image.lagou.com/12479122.jpg","price": 2699}},{"_index": "winkto","_type": "goods","_id": "kBFMWHsBy-koX7e_VW4W","_score": 1,"_source": {"title": "华为pro30","images": "http://image.lagou.com/12479122.jpg","price": 5699}}]}
}

5.5.2、条件查询

GET /winkto/_search
{"query":{"match":{"title": "小米"}}
}
{"took": 16,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 1,"max_score": 0.2876821,"hits": [{"_index": "winkto","_type": "goods","_id": "xqurVHsB1mHhNfuBSw0p","_score": 0.2876821,"_source": {"title": "小米10","images": "http://image.lagou.com/12479122.jpg","price": 2699}}]}
}

match 类型查询,会把查询条件进行分词,然后进行查询,多个词条之间是or的关系

GET /winkto/_search
{"query":{"match":{"title": "小米华为"}}
}
{"took": 355,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 2,"max_score": 0.2876821,"hits": [{"_index": "winkto","_type": "goods","_id": "xqurVHsB1mHhNfuBSw0p","_score": 0.2876821,"_source": {"title": "小米10","images": "http://image.lagou.com/12479122.jpg","price": 2699}},{"_index": "winkto","_type": "goods","_id": "kBFMWHsBy-koX7e_VW4W","_score": 0.2876821,"_source": {"title": "华为pro30","images": "http://image.lagou.com/12479122.jpg","price": 5699}}]}
}

但是有些时候我们希望分词关系为and

GET /winkto/_search
{"query":{"match":{"title": {"query": "小米华为","operator": "and"}}}
}
{"took": 8,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 1,"max_score": 0.5753642,"hits": [{"_index": "winkto","_type": "goods","_id": "kRFWWHsBy-koX7e_DW5_","_score": 0.5753642,"_source": {"title": "小米华为plusplus","images": "http://image.lagou.com/12479122.jpg","price": 2699}}]}
}

5.5.3、词条匹配

term 查询被用于精确值 匹配,这些精确值可能是数字、时间、布尔或者那些未分词的字符 串,keyword类型的字符串

GET /winkto/_search
{"query":{"term": {"price": 2699}}
}
{"took": 7,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 2,"max_score": 1,"hits": [{"_index": "winkto","_type": "goods","_id": "xqurVHsB1mHhNfuBSw0p","_score": 1,"_source": {"title": "小米10","images": "http://image.lagou.com/12479122.jpg","price": 2699}},{"_index": "winkto","_type": "goods","_id": "kRFWWHsBy-koX7e_DW5_","_score": 1,"_source": {"title": "小米华为plusplus","images": "http://image.lagou.com/12479122.jpg","price": 2699}}]}
}

5.5.4、布尔组合

bool 把各种其它查询通过 must (与)、 must_not (非)、 should (或)的方式进行组合

GET /winkto/_search
{"query":{"bool": {"must": [{"match": {"title": "小米"}}],"must_not": [{"match": {"title": "华为"}}],"should": [{"match": {"title": "10"}}]}}
}
{"took": 2,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 1,"max_score": 0.5753642,"hits": [{"_index": "winkto","_type": "goods","_id": "xqurVHsB1mHhNfuBSw0p","_score": 0.5753642,"_source": {"title": "小米10","images": "http://image.lagou.com/12479122.jpg","price": 2699}}]}
}

5.5.5、范围查询

GET /winkto/_search
{"query":{"range": {"price": {"gte": 2000,"lte": 6000}}}
}
{"took": 4,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 3,"max_score": 1,"hits": [{"_index": "winkto","_type": "goods","_id": "xqurVHsB1mHhNfuBSw0p","_score": 1,"_source": {"title": "小米10","images": "http://image.lagou.com/12479122.jpg","price": 2699}},{"_index": "winkto","_type": "goods","_id": "kBFMWHsBy-koX7e_VW4W","_score": 1,"_source": {"title": "华为pro30","images": "http://image.lagou.com/12479122.jpg","price": 5699}},{"_index": "winkto","_type": "goods","_id": "kRFWWHsBy-koX7e_DW5_","_score": 1,"_source": {"title": "小米华为plusplus","images": "http://image.lagou.com/12479122.jpg","price": 2699}}]}
}

5.6、结果过滤

默认情况下,elasticsearch在搜索的结果中,会把文档中保存在 _source 的所有字段都返回。但有时只想获取其中的部分字段,此时可以添加 _source 的过滤

5.6.1、直接指定字段

GET /winkto/_search
{"_source": ["title","price"], "query":{"match": {"title": "小米"}}
}
{"took": 9,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 2,"max_score": 0.2876821,"hits": [{"_index": "winkto","_type": "goods","_id": "xqurVHsB1mHhNfuBSw0p","_score": 0.2876821,"_source": {"price": 2699,"title": "小米10"}},{"_index": "winkto","_type": "goods","_id": "kRFWWHsBy-koX7e_DW5_","_score": 0.2876821,"_source": {"price": 2699,"title": "小米华为plusplus"}}]}
}

5.6.2、includes和excludes

  • includes:来指定想要显示的字段
  • excludes:来指定不想要显示的字段
GET /winkto/_search
{"_source": {"includes": ["title","images"],"excludes": ["price"]}, "query":{"match": {"title": "小米"}}
}
{"took": 2,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 2,"max_score": 0.2876821,"hits": [{"_index": "winkto","_type": "goods","_id": "xqurVHsB1mHhNfuBSw0p","_score": 0.2876821,"_source": {"images": "http://image.lagou.com/12479122.jpg","title": "小米10"}},{"_index": "winkto","_type": "goods","_id": "kRFWWHsBy-koX7e_DW5_","_score": 0.2876821,"_source": {"images": "http://image.lagou.com/12479122.jpg","title": "小米华为plusplus"}}]}
}

5.6.3、Filter

GET /winkto/_search
{"query":{"bool": {"must": [{"match": {"title": "小米"}}],"filter": {"range": {"price": {"gte": 1000,"lte": 3000}}}}}
}
{"took": 1,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 2,"max_score": 0.2876821,"hits": [{"_index": "winkto","_type": "goods","_id": "xqurVHsB1mHhNfuBSw0p","_score": 0.2876821,"_source": {"title": "小米10","images": "http://image.lagou.com/12479122.jpg","price": 2699}},{"_index": "winkto","_type": "goods","_id": "kRFWWHsBy-koX7e_DW5_","_score": 0.2876821,"_source": {"title": "小米华为plusplus","images": "http://image.lagou.com/12479122.jpg","price": 2699}}]}
}

如果一次查询只有过滤,没有查询条件,不希望进行评分,可以使用 constant_score 取代只有 filter 语句的 bool 查询

GET /winkto/_search
{"query":{"constant_score": {"filter": {"range": {"price": {"gte": 1000,"lte": 3000}}}}}
}
{"took": 4,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 2,"max_score": 1,"hits": [{"_index": "winkto","_type": "goods","_id": "xqurVHsB1mHhNfuBSw0p","_score": 1,"_source": {"title": "小米10","images": "http://image.lagou.com/12479122.jpg","price": 2699}},{"_index": "winkto","_type": "goods","_id": "kRFWWHsBy-koX7e_DW5_","_score": 1,"_source": {"title": "小米华为plusplus","images": "http://image.lagou.com/12479122.jpg","price": 2699}}]}
}

5.7、排序

GET /winkto/_search
{"query":{"match_all": {}},"sort": [{"price": {"order": "desc"}}]
}
{"took": 141,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 3,"max_score": null,"hits": [{"_index": "winkto","_type": "goods","_id": "kBFMWHsBy-koX7e_VW4W","_score": null,"_source": {"title": "华为pro30","images": "http://image.lagou.com/12479122.jpg","price": 5699},"sort": [5699]},{"_index": "winkto","_type": "goods","_id": "xqurVHsB1mHhNfuBSw0p","_score": null,"_source": {"title": "小米10","images": "http://image.lagou.com/12479122.jpg","price": 2699},"sort": [2699]},{"_index": "winkto","_type": "goods","_id": "kRFWWHsBy-koX7e_DW5_","_score": null,"_source": {"title": "小米华为plusplus","images": "http://image.lagou.com/12479122.jpg","price": 2699},"sort": [2699]}]}
}

5.8、分页

GET /winkto/_search
{"query":{"match_all": {}},"from": 0,"size": 2
}
{"took": 5,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 3,"max_score": 1,"hits": [{"_index": "winkto","_type": "goods","_id": "xqurVHsB1mHhNfuBSw0p","_score": 1,"_source": {"title": "小米10","images": "http://image.lagou.com/12479122.jpg","price": 2699}},{"_index": "winkto","_type": "goods","_id": "kBFMWHsBy-koX7e_VW4W","_score": 1,"_source": {"title": "华为pro30","images": "http://image.lagou.com/12479122.jpg","price": 5699}}]}
}

5.9、高亮显示

GET /winkto/_search
{"query":{"match": {"title": "小米"}},"highlight": {"pre_tags": "<em>","post_tags": "</em>","fields": {"title": {}}}
}
{"took": 69,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 2,"max_score": 0.2876821,"hits": [{"_index": "winkto","_type": "goods","_id": "xqurVHsB1mHhNfuBSw0p","_score": 0.2876821,"_source": {"title": "小米10","images": "http://image.lagou.com/12479122.jpg","price": 2699},"highlight": {"title": ["<em>小米</em>10"]}},{"_index": "winkto","_type": "goods","_id": "kRFWWHsBy-koX7e_DW5_","_score": 0.2876821,"_source": {"title": "小米华为plusplus","images": "http://image.lagou.com/12479122.jpg","price": 2699},"highlight": {"title": ["<em>小米</em>华为plusplus"]}}]}
}

5.10、聚合

聚合可以让我们极其方便的实现对数据的统计、分析

  • 桶(group by):是按照某种方式对数据进行分组,每一组数据在ES中称为一个 桶
  • 度量(聚合的结果):求平均值、最大、最小、求和等

预准备

PUT /car
{"mappings": {"orders": {"properties": {"color": {"type": "keyword"},"make": {"type": "keyword"}}}}
}
POST /car/orders/_bulk
{ "index": {}}
{ "price" : 10000, "color" : "红", "make" : "本田", "sold" : "2020-10-28" }
{ "index": {}}
{ "price" : 20000, "color" : "红", "make" : "本田", "sold" : "2020-11-05" }
{ "index": {}}
{ "price" : 30000, "color" : "绿", "make" : "福特", "sold" : "2020-05-18" }
{ "index": {}}
{ "price" : 15000, "color" : "蓝", "make" : "丰田", "sold" : "2020-07-02" }
{ "index": {}}
{ "price" : 12000, "color" : "绿", "make" : "丰田", "sold" : "2020-08-19" }
{ "index": {}}
{ "price" : 20000, "color" : "红", "make" : "本田", "sold" : "2020-11-05" }
{ "index": {}}
{ "price" : 80000, "color" : "红", "make" : "宝马", "sold" : "2020-01-01" }
{ "index": {}}
{ "price" : 25000, "color" : "蓝", "make" : "福特", "sold" : "2020-02-12" }

5.10.1、聚合为桶

GET /car/_search
{"size": 0,"aggs": {"popular_colors": {"terms": {"field": "color"}}}
}
{"took": 48,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 8,"max_score": 0,"hits": []},"aggregations": {"popular_colors": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": [{"key": "红","doc_count": 4},{"key": "绿","doc_count": 2},{"key": "蓝","doc_count": 2}]}}
}

5.10.2、聚合操作

GET /car/_search
{"size": 0,"aggs": {"popular_colors": {"terms": {"field": "color"},"aggs": {"avg_price": {"avg": {"field": "price"}}}}}
}
{"took": 8,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 8,"max_score": 0,"hits": []},"aggregations": {"popular_colors": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": [{"key": "红","doc_count": 4,"avg_price": {"value": 32500}},{"key": "绿","doc_count": 2,"avg_price": {"value": 21000}},{"key": "蓝","doc_count": 2,"avg_price": {"value": 20000}}]}}
}

6、Elastic search集群

6.1、集群解决的问题

  • 单台机器存储容量有限,无法实现高存储
  • 单服务器容易出现单点故障,无法实现高可用
  • 单服务的并发处理能力有限,无法实现高并发

6.2、数据分片

第一个问题就是数据量太大,单点存储量有限的问题,可以把数据拆分成多份,每一份存储到不同机器节点(node),从而实现减少每个节点数 据量的目的。这就是数据的分布式存储,也叫做: 数据分片(Shard)

数据分片解决了海量数据存储的问题,但是如果出现单点故障,那么分片数据就不再完整

给每个分片数据进行备 份,存储到其它节点,防止数据丢失,这就是数据备份,也叫 数据副本(replica)

数据备份可以保证高可用,但是每个分片备份一份,所需要的节点数量就会翻一倍,成本实在是太高

为了在高可用和成本间寻求平衡,首先对数据分片,存储到不同节点 然后对每个分片进行备份,放到对方节点,完成互相备份

6.3、集群搭建

node-0配置文件(node-1,node-2只需要修改node.name、http.port,transport.tcp.port,path.data,path.logs即可)

# ---------------------------------- Cluster -----------------------------------
# Use a descriptive name for your cluster:
cluster.name: my-application
# ------------------------------------ Node ------------------------------------
# Use a descriptive name for the node:
node.name: node-0
# Add custom attributes to the node:
#node.attr.rack: r1
# 是否可以为主节点
node.master: true
# ----------------------------------- Paths ------------------------------------
# Path to directory where to store the data (separate multiple locations by comma):
path.data: D:\es\elasticsearch-6.2.4-0\data
# Path to log files:
path.logs: D:\es\elasticsearch-6.2.4-0\data
# ----------------------------------- Memory -----------------------------------
# Lock the memory on startup:
#bootstrap.memory_lock: true
# Make sure that the heap size is set to about half the memory available
# on the system and that the owner of the process is allowed to use this
# limit.
# Elasticsearch performs poorly when the system is swapping the memory.
# ---------------------------------- Network -----------------------------------
# Set the bind address to a specific IP (IPv4 or IPv6):
network.host: 0.0.0.0
# Set a custom port for HTTP:
http.port: 9200
# For more information, consult the network module documentation.
# TCP协议对外端口 每个节点不一样,默认:9300
transport.tcp.port: 9201
# --------------------------------- Discovery ----------------------------------
# Pass an initial list of hosts to perform discovery when new node is started:
# The default list of hosts is ["127.0.0.1", "[::1]"]
#discovery.zen.ping.unicast.hosts: ["host1", "host2"]
# Prevent the "split brain" by configuring the majority of nodes (total number of master-eligible nodes / 2 + 1):
#discovery.zen.minimum_master_nodes:
# For more information, consult the zen discovery module documentation.
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9201","127.0.0.1:9301","127.0.0.1:9401"]
discovery.zen.minimum_master_nodes: 2
# ---------------------------------- Gateway -----------------------------------
# Block initial recovery after a full cluster restart until N nodes are started:
#gateway.recover_after_nodes: 3
# For more information, consult the gateway module documentation.
# ---------------------------------- Various -----------------------------------
# Require explicit names when deleting indices:
#action.destructive_requires_name: true
# ---------------------------------- Http -----------------------------------
#允许跨域名访问
http.cors.enabled: true
#当设置允许跨域,默认为*,表示支持所有域名
http.cors.allow-origin: "*"



创建索引winkto

PUT /winkto
{"settings": {"number_of_shards": 3,"number_of_replicas": 1},"mappings": {"items":{"properties": {"id": {"type": "keyword"},"title":{"type": "text","analyzer": "ik_max_word"},"category":{"type": "keyword"},"brand": {"type": "keyword"},"images":{"type": "keyword","index": false},"price":{"type": "double"}}}}
}

7、Elastic search API

预准备

PUT /winkto
{"settings": {"number_of_shards": 3,"number_of_replicas": 1},"mappings": {"items":{"properties": {"id": {"type": "keyword"},"title":{"type": "text","analyzer": "ik_max_word"},"category":{"type": "keyword"},"brand": {"type": "keyword"},"images":{"type": "keyword","index": false},"price":{"type": "double"}}}}
}

7.1、添加数据

导入依赖

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></dependency><!--ES高级Rest Client--><dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>6.5.4</version></dependency><dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>6.5.4</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency>
</dependencies>

实体类

public class Product {private Long id;private String title;private String category;private String brand;private Double price;private String images;
}

config

@Configuration
public class WinktoConfig {@Beanpublic ObjectMapper jackson(){return new ObjectMapper();}
}

测试

@SpringBootTest
class ElasticSearchApplicationTests {@AutowiredObjectMapper jackson;@Testvoid contextLoadsinsert() throws IOException {// 初始化HighLevel客户端RestHighLevelClient restHighLevelClient = new RestHighLevelClient(RestClient.builder(new HttpHost("127.0.0.1",9200),new HttpHost("127.0.0.1",9300),new HttpHost("127.0.0.1",9400)));// 文档数据Product product = new Product(1L,"华为P50、新款发布","手机","华为",5999.9,"http://image.huawei.com/1.jpg");IndexRequest indexRequest = new IndexRequest("winkto", "items", product.getId().toString());indexRequest.source(jackson.writeValueAsString(product), XContentType.JSON);IndexResponse response = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);System.out.println(response);// 关闭客户端restHighLevelClient.close();}
}

结果

IndexResponse[index=winkto,type=items,id=1,version=3,result=created,seqNo=2,primaryTerm=1,shards={"total":2,"successful":2,"failed":0}]

7.2、查询数据

@Test
void contextLoadsSelect() throws IOException {// 初始化HighLevel客户端RestHighLevelClient restHighLevelClient = new RestHighLevelClient(RestClient.builder(new HttpHost("127.0.0.1",9200),new HttpHost("127.0.0.1",9300),new HttpHost("127.0.0.1",9400)));GetRequest getRequest = new GetRequest("winkto","items","1");GetResponse documentFields = restHighLevelClient.get(getRequest,RequestOptions.DEFAULT);String sourceAsString = documentFields.getSourceAsString();Product product = jackson.readValue(sourceAsString, Product.class);System.out.println(product.toString());// 关闭客户端restHighLevelClient.close();
}
Product{id=1, title='华为P50、新款发布', category='手机', brand='华为', price=5999.9, images='http://image.huawei.com/1.jpg'}

7.3、修改文档

新增时,如果传递的id是已经存在的,则会完成修改操作,如果不存在,则是新增

7.4、删除文档

@Test
void contextLoadsDelete() throws IOException {// 初始化HighLevel客户端RestHighLevelClient restHighLevelClient = new RestHighLevelClient(RestClient.builder(new HttpHost("127.0.0.1",9200),new HttpHost("127.0.0.1",9300),new HttpHost("127.0.0.1",9400)));DeleteRequest deleteRequest = new DeleteRequest("winkto", "items", "1");DeleteResponse delete = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);// 关闭客户端restHighLevelClient.close();
}

7.5、match_all

@Test
void contextLoadsMatchAll() throws IOException {// 初始化HighLevel客户端RestHighLevelClient restHighLevelClient = new RestHighLevelClient(RestClient.builder(new HttpHost("127.0.0.1",9200),new HttpHost("127.0.0.1",9300),new HttpHost("127.0.0.1",9400)));SearchRequest searchRequest = new SearchRequest();SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();searchSourceBuilder.query(QueryBuilders.matchAllQuery());searchRequest.source(searchSourceBuilder);SearchResponse search = restHighLevelClient.search(searchRequest);SearchHits hits = search.getHits();SearchHit[] hits1 = hits.getHits();for (SearchHit documentFields : hits1) {String sourceAsString = documentFields.getSourceAsString();Product product = jackson.readValue(sourceAsString, Product.class);System.out.println(product);}// 关闭客户端restHighLevelClient.close();
}

7.6、match

@Test
void contextLoadsMatch() throws IOException {// 初始化HighLevel客户端RestHighLevelClient restHighLevelClient = new RestHighLevelClient(RestClient.builder(new HttpHost("127.0.0.1",9200),new HttpHost("127.0.0.1",9300),new HttpHost("127.0.0.1",9400)));SearchRequest searchRequest = new SearchRequest();SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();searchSourceBuilder.query(QueryBuilders.matchQuery("title","新款"));searchRequest.source(searchSourceBuilder);SearchResponse search = restHighLevelClient.search(searchRequest);SearchHits hits = search.getHits();SearchHit[] hits1 = hits.getHits();for (SearchHit documentFields : hits1) {String sourceAsString = documentFields.getSourceAsString();Product product = jackson.readValue(sourceAsString, Product.class);System.out.println(product);}// 关闭客户端restHighLevelClient.close();
}

7.7、range

@Test
void contextLoadsRange() throws IOException {// 初始化HighLevel客户端RestHighLevelClient restHighLevelClient = new RestHighLevelClient(RestClient.builder(new HttpHost("127.0.0.1",9200),new HttpHost("127.0.0.1",9300),new HttpHost("127.0.0.1",9400)));SearchRequest searchRequest = new SearchRequest();SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();searchSourceBuilder.query(QueryBuilders.rangeQuery("price").gt(2000).lt(4000));searchRequest.source(searchSourceBuilder);SearchResponse search = restHighLevelClient.search(searchRequest);SearchHits hits = search.getHits();SearchHit[] hits1 = hits.getHits();for (SearchHit documentFields : hits1) {String sourceAsString = documentFields.getSourceAsString();Product product = jackson.readValue(sourceAsString, Product.class);System.out.println(product);}// 关闭客户端restHighLevelClient.close();
}

7.8、source过滤

默认情况下,索引库中所有数据都会返回,如果我们想只返回部分字段,可以通过source filter来控制

@Test
void contextLoadsSource() throws IOException {// 初始化HighLevel客户端RestHighLevelClient restHighLevelClient = new RestHighLevelClient(RestClient.builder(new HttpHost("127.0.0.1",9200),new HttpHost("127.0.0.1",9300),new HttpHost("127.0.0.1",9400)));SearchRequest searchRequest = new SearchRequest();SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();searchSourceBuilder.query(QueryBuilders.rangeQuery("price").gt(2000).lt(4000));// 第一个参数想要包含的字段,第二个参数不想要包含的字段searchSourceBuilder.fetchSource(new String[]{"title","price"},null);searchRequest.source(searchSourceBuilder);SearchResponse search = restHighLevelClient.search(searchRequest);SearchHits hits = search.getHits();SearchHit[] hits1 = hits.getHits();for (SearchHit documentFields : hits1) {String sourceAsString = documentFields.getSourceAsString();Product product = jackson.readValue(sourceAsString, Product.class);System.out.println(product);}// 关闭客户端restHighLevelClient.close();
}

7.9、排序

@Test
void contextLoadsSort() throws IOException {// 初始化HighLevel客户端RestHighLevelClient restHighLevelClient = new RestHighLevelClient(RestClient.builder(new HttpHost("127.0.0.1",9200),new HttpHost("127.0.0.1",9300),new HttpHost("127.0.0.1",9400)));SearchRequest searchRequest = new SearchRequest();SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();searchSourceBuilder.query(QueryBuilders.rangeQuery("price").gt(2000).lt(4000));// 降序排序searchSourceBuilder.sort("price", SortOrder.DESC);searchRequest.source(searchSourceBuilder);SearchResponse search = restHighLevelClient.search(searchRequest);SearchHits hits = search.getHits();SearchHit[] hits1 = hits.getHits();for (SearchHit documentFields : hits1) {String sourceAsString = documentFields.getSourceAsString();Product product = jackson.readValue(sourceAsString, Product.class);System.out.println(product);}// 关闭客户端restHighLevelClient.close();
}

7.10、分页

@Test
void contextLoadsSort() throws IOException {// 初始化HighLevel客户端RestHighLevelClient restHighLevelClient = new RestHighLevelClient(RestClient.builder(new HttpHost("127.0.0.1",9200),new HttpHost("127.0.0.1",9300),new HttpHost("127.0.0.1",9400)));SearchRequest searchRequest = new SearchRequest();SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();searchSourceBuilder.query(QueryBuilders.matchAllQuery());// 降序排序searchSourceBuilder.sort("price", SortOrder.DESC);//searchSourceBuilder.from(0);searchSourceBuilder.size(2);searchRequest.source(searchSourceBuilder);SearchResponse search = restHighLevelClient.search(searchRequest);SearchHits hits = search.getHits();SearchHit[] hits1 = hits.getHits();for (SearchHit documentFields : hits1) {String sourceAsString = documentFields.getSourceAsString();Product product = jackson.readValue(sourceAsString, Product.class);System.out.println(product);}// 关闭客户端restHighLevelClient.close();
}

8、Spring Data Elastic search

Spring Data 的使命是给各种数据访问提供统一的编程接口,不管是关系型数据库(如MySQL),还是 非关系数据库(如Redis),或者类似Elasticsearch这样的索引数据库。从而简化开发人员的代码,提 高开发效率。

  • 支持Spring的基于 @Configuration 的java配置方式,或者XML配置方式
  • 提供了用于操作ES的便捷工具类 ElasticsearchTemplate 。包括实现文档到POJO之间的自动智能映射
  • 利用Spring的数据转换服务实现的功能丰富的对象映射
  • 基于注解的元数据映射方式,而且可扩展以支持更多不同的数据格式,可以定义JavaBean:类名、属性
  • 根据持久层接口自动生成对应实现方法,无需人工编写基本操作代码(类似mybatis,根据接口自 动得到实现)。当然,也支持人工定制查询

8.1、创建索引库

导入依赖

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies>
@Document(indexName = "winkto", type = "product", shards = 3, replicas = 1)
public class Product {@Idprivate Long id;@Field(type = FieldType.Text,analyzer = "ik_max_word")private String title;@Field(type = FieldType.Keyword)private String category;@Field(type = FieldType.Keyword)private String brand;@Field(type = FieldType.Double)private Double price;@Field(type = FieldType.Keyword)private String images;
}
@SpringBootTest
class EsDataApplicationTests {@Autowiredprivate ElasticsearchTemplate elasticsearchTemplate;@Testvoid contextLoadsIndex() {elasticsearchTemplate.createIndex(Product.class);}
}

application.yaml

spring:data:elasticsearch:cluster-name: my-applicationcluster-nodes: 127.0.0.1:9201,127.0.0.1:9301,127.0.0.1:9401


8.2、创建类型映射

@Test
void contextLoadsMapping() {elasticsearchTemplate.putMapping(Product.class);
}

8.3、索引数据CRUD

添加数据(单条)

@Test
void contextLoadsInsert() {Product product = new Product(1L, "小米手机7", "手机", "小米", 3299.00, "/13123.jpg");productMapper.save(product);
}


添加数据(多条)

@Test
void contextLoadsInsertAll() {List<Product> list = new ArrayList<>();list.add(new Product(2L, "坚果手机R1", "手机", "锤子", 3699.00, "/13123.jpg"));list.add(new Product(3L, "华为META10", "手机", "华为", 4499.00, "/13123.jpg"));list.add(new Product(4L, "小米Mix2S", "手机", "小米", 4299.00, "/13123.jpg"));list.add(new Product(5L, "荣耀V10", "手机", "华为", 2799.00, "/13123.jpg"));productMapper.saveAll(list);
}


根据id查询

@Test
void contextLoadsSelect() {Optional<Product> optionalProduct = productMapper.findById(1L);System.out.println(optionalProduct.orElse(null));
}

查询所有

@Test
void contextLoadsSelectAll() {Iterable<Product> all = productMapper.findAll();all.forEach(System.out::println);
}

根据id删除

@Test
void contextLoadsDelete() {productMapper.deleteById(1L);
}

Java微服务篇4——Elastic search相关推荐

  1. Java微服务篇5——Docker

    Java微服务篇5--Docker 1.虚拟化技术 虚拟化技术是一种计算机资源管理技术,是将计算机的各种实体资源,如服务器.网络.内存及存储 等,予以抽象.转换后呈现出来.虚拟化技术打破了计算机实体结 ...

  2. Java微服务篇3——Lucene

    Java微服务篇3--Lucene 1.数据分类 1.1.结构化数据 具有固定格式或有限长度的数据,如数据库,元数据等 常见的结构化数据也就是数据库中的数据,在数据库中搜索很容易实现,通常都是使用 s ...

  3. Java微服务篇2——SpringCloud

    Java微服务篇2--SpringCloud 1.微服务架构 1.1.单体应用架构 的⽤户量.数据量规模都⽐较⼩,项目所有的功能模块都放在一个工程中编码. 编译.打包并且部署在一个Tomcat容器中的 ...

  4. Java微服务篇1——SpringBoot

    Java微服务篇1--SpringBoot 1.什么是springboot 1.1.Spring出现的问题 Spring是Java企业版(Java Enterprise Edition,JEE,也称J ...

  5. java微服务开发(基础环境篇)

    java微服务开发(基础环境篇) 我们的目标是~~_浩瀚的宇宙 _~~全栈开发 俗话说的好 _工欲善其事 必先利其器 _对于一个开发者来说 一个好的开发环境可以带来的收益是巨大的 本篇的重点主要是li ...

  6. 《Java 后端面试经》微服务篇

    <Java 后端面试经>专栏文章索引: <Java 后端面试经>Java 基础篇 <Java 后端面试经>Java EE 篇 <Java 后端面试经>数 ...

  7. Java微服务——SpringCloud实战篇2:整合Gateway、Config、Bus

    Java微服务--SpringCloud实战篇2:整合Gateway.Config.Bus 如果小伙伴在阅读下列内容时,对于编写SpringCloud项目是零基础,那么请先阅读小编的另一篇博文:&qu ...

  8. 十款优质企业级Java微服务开源项目(开源框架,用于学习、毕设、公司项目、私活等,减少开发工作,让您只关注业务!)

    Java微服务开源项目 前言 一.pig 二.zheng 三.SpringBlade 四.SOP 五.matecloud 六.mall 七.jeecg-boot 八.Cloud-Platform 九. ...

  9. Java微服务开发指南-Java环境下的微服务

    本文涉及的内容,能让你学到什么? 本书适用于开发微服务的Java开发人员和架构师.我们在开始介绍微服务架构前,先讲述一些抽象的基本概念.不幸的是,使用新技术并不能神奇地解决分布式系统问题.但是我们通过 ...

最新文章

  1. mysql高可用之MMM
  2. java 按钮 事件_Java 添加按钮点击事件
  3. java框架篇---spring IOC依赖注入
  4. PhotoSwipe 图片浏览插件使用方法
  5. 2023届IC实习小结
  6. 大数据工作流_大数据和人工智能时代下的数字化工作流
  7. 17现代软件工程十五组第三次作业
  8. 犹太教、基督教和伊斯兰教的简单关系
  9. Authorware 函数说明
  10. iOS APP测试方法和测试工具 大揭秘
  11. stl文件用proe怎么打开_stl格式怎么打开
  12. 【转】“弱水三千 只取一瓢”(出处就不去考证了)
  13. 实战--接入最坑的支付宝
  14. Python GUI 设计(一)———Tkinter窗口创建、组件布局
  15. UEFI Boot Flow 系列之 SEC Phase
  16. 联想服务器bios查看网卡信息,如何通过BIOS检查确认硬盘信息可被正常识别
  17. 桌面右下角任务栏图标消失问题解决
  18. oracle mrp/rfs进程,挑战dataguard(3)——dataguard相关进程(RFS,LNSn,MRP,LSP)和参数配置...
  19. 活动二维码怎么制作?如何将活动内容做成二维码图片?
  20. 【SVN】新旧服务器更替,完成svn服务器迁移

热门文章

  1. C2的完整形式是什么?
  2. python线程同步锁_[python] 线程间同步之Lock RLock
  3. python计算结果传给spark_Spark入门:流计算简介(Python版)
  4. python学完面向对象之后_Python学完基础语法后,再往后应该学什么?
  5. Java Scanner nextLine()方法与示例
  6. Java类类getGenericSuperclass()方法及示例
  7. 面试官 | 说一下什么是代理模式?
  8. 90% 的人都会答错的面试题 == 和 equals 的区别
  9. 图片人脸检测——Dlib版(四)
  10. Dynamic_Performance_Tables_not_accessible_问题_解决不能动态统计