Blage's Coding Blage's Coding
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
  • SpringCloudAlibaba

  • MQ消息队列

  • Nginx

  • Elasticsearch

    • Elasticsearch使用
      • 1.倒排索引
      • 2.安装
      • 3.DSL索引库操作
        • mappings
        • 创建,查看,删除索引库
        • 文档插入,删除,修改
      • 4.RestClient操作索引库
      • 5.DSL查询
      • 6.ES搜索结果处理
      • 7.RestClient操作文档查询
    • ES高级用法
  • Gateway

  • Xxl-job

  • Feign

  • Eureka

  • 中间件
  • Elasticsearch
phan
2023-05-15
目录

Elasticsearch使用

# Elasticsearch使用

# 1.倒排索引

倒排索引:每条数据每条记录就是一个文档,json格式存储,文档按照语义划分为词语。在倒排索引中,每行记录格式为词条:文档id,每个词条都是唯一的。

image-20230302195531882

因此查找“华为手机”这条记录时,首先先进行词条划分,然后在倒排索引中查找“华为”和“手机”两个词条所对应的所有文档id作为搜索的结果集。

MySql表中,行<—>Es索引,文档

# 2.安装

Kibana是用于可视化以及管理Es的一个界面应用程序。

ik分词器用于扩展中文分词

分词器扩展(文件/var/lib/docker/volumes/es-plugins/_data/ik/config/IKAnalyzer.cfg.xml中的ext_dict下编辑)和停用词(ext_stopwords)

# 3.DSL索引库操作

# mappings

  • tyoe数据类型
    • 字符串:text(可分词文本),keyword(精确值,品牌,国家)
    • 数值类型:long,double...注意es中没有数组这一概念,但是允许一个字段有多个值
    • 布尔类型
    • 对象类型object
  • index:是否创建索引,默认所有的字段都为true,如果是无意义字段不参与搜索则需要设置为false
  • analyzer:使用分词器(和text类型使用)
  • properties:该字段的子字段

# 创建,查看,删除索引库

建表语句:

PUT /索引库名称
{
  "mappings": {
    "properties": {
      "字段名":{
        "type": "text",
        "analyzer": "ik_smart"
      },
      "字段名2":{
        "type": "keyword",
        "index": "false"
      },
      "字段名3":{
        "properties": {
          "子字段": {
            "type": "keyword"
          }
        }
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

查看索引库

GET /索引库名
1

删除索引库

DELETE /索引库名
1

修改索引库,只能添加新字段,原有的字段已经建立了倒排索引不允许修改

PUT /索引库名/_mapping
{
  "properties": {
    "新字段名":{
      "type": "integer"
    }
  }
}
1
2
3
4
5
6
7
8

# 文档插入,删除,修改

文档插入,相当于向表中插入一条数据

POST /索引库名/_doc/文档id
{
    "字段1": "值1",
    "字段2": "值2",
    "字段3": {
        "子属性1": "值3",
        "子属性2": "值4"
    },
    // ...
}
1
2
3
4
5
6
7
8
9
10

查询文档

GET /索引库名称/_doc/id
1

修改文档(①全量修改:相当于覆盖原来文档。②增量修改:修改文档的部分字段)

全量修改

PUT /{索引库名}/_doc/文档id
{
    "字段1": "值1",
    "字段2": "值2",
    // ... 略
}
1
2
3
4
5
6

增量修改

POST /{索引库名}/_update/文档id
{
    "doc": {
         "字段名": "新的值",
    }
}
1
2
3
4
5
6

经纬度地理坐标类型type使用geo_point

copy_to:将当前字段值拷贝到指定字段,比如查询一个酒店的address字段,就可以从all指定字段同时获取city字段,而不需要再去搜索依次city字段。

# 4.RestClient操作索引库

导入依赖,并保证es版本要和docker的es服务版本一致。

<properties>
    <elasticsearch.version>7.12.1</elasticsearch.version>
</properties>

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
1
2
3
4
5
6
7
8

所有操作流程:初始化RestHighLevelClient->创建xxxRequest->准备参数source->调用xxx方法

创建索引库,指定索引库名称、索引库语句的资源文件。client.indices()包含所有索引库操作。

private RestHighLevelClient client=new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.200.200:9200")));

void testCteateHotelIndex() throws IOException {
    CreateIndexRequest request = new CreateIndexRequest("hotel");
    request.source(MAPPING_TEMPLATE, XContentType.JSON);
    client.indices().create(request, RequestOptions.DEFAULT);
}
1
2
3
4
5
6
7

插入文档数据,根据MP的HotelService(@Autowired)来获取行数据,然后封装成索引库文档的格式类型,source导入资源前还需要使用fastjson把对象转换成json对象。

查询文档数据,创建response对象并通过getSourceAsString()获取到json字符串,然后使用JSON.parseObject解析成java对象。

更新文档数据,更新的数据以key-value格式逗号隔开。

@Test
void testCteateHotelIndex1() throws IOException {
    Hotel hotel = hotelService.getById(61083L);
    HotelDoc hotelDoc = new HotelDoc(hotel);
    IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());
    request.source(JSON.toJSONString(hotelDoc), XContentType.JSON);
    client.index(request, RequestOptions.DEFAULT);
    //查询
    GetRequest request = new GetRequest("hotel", "61083");
    GetResponse response = client.get(request, RequestOptions.DEFAULT);
    String json = response.getSourceAsString();
    HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
    System.out.println(hotelDoc.toString());
    //更新
    UpdateRequest updateRequest = new UpdateRequest("hotel", "61083");
    updateRequest.doc(
            "price","952",
            "starName","四钻"
    );
    client.update(updateRequest, RequestOptions.DEFAULT);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

es批量导入一个表,使用BulkRequest类,发送一个请求实现批处理。

# 5.DSL查询

查询类型:

  • match:全文检索,针对text类型
  • multi_match:允许根据多字段查询
  • term:根据词条keyword,id进行精确查询(搜索内容必须和词条完全一致)
  • range:根据值范围查询
  • geo_distance:根据经纬度进行地理查询,"distance指示圆形范围的半径距离。
  • funtion_score:复合查询,每条文档会根据结果和搜索词条的关联度打分,返回结果按照分值降序排序。可以自定义函数来对专门文档加分过滤,指定酸粉函数和权重。
  • bool:must表示必须匹配每个子查询,should表示选择性匹配,must_not必须不匹配(不算分),filter表示必须满足的过滤条件(不算分)
GET /索引库名/_search
{
	"query":{
		"查询类型":{
			"查询字段":"查询值"
		}
	}
}
1
2
3
4
5
6
7
8

# 6.ES搜索结果处理

  • 排序

搜索得到的结果默认按照打分进行排序,可以使用sort字段指定按照哪个字段(Asc还是desc)重新进行排序。

如果sort指定geo_distance,则表示按照到指定位置的距离大小进行升序降序

  • 分页

通过from指定分页开始的位置,size指定期望获取的文档总数。

倒排索引不适合分页,底层是查找出所有数据然后截取所要分页的部分。(如果是分布式存取,则需要对所有服务器都取出前N条,再重新筛选),因此ES底层from+size限制不能超过一万。

解决:after search搜索时必须排序,记住上一次查询的最后一个值,只能向后翻页。scroll向内存复制一个快照。

  • 高亮

服务端提前给搜索结果关键字用标签标记出来,高亮显示

GET /索引库名/_search
{
	"query":{
		"match":{
			"查询字段":"查询值"
		}
	},
	"from":990,/分页开始的位置,默认为0
	"size":10,//期望获取的文档总数
	"sort": [
		{ "price": "asc"}
	],
	"highlisht":{
		"高亮字段(与上面搜索字段一致)":{
			"require_field_match":"false"
		}
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 7.RestClient操作文档查询

具体流程:准备Request->准备DSL查询语句->发送请求->解析响应回来的json数据。

除了DSL语句其他部分都可以进行封装,核心是修改searchRequest.source().query()的query方法内部参数。所有查询条件类对象都是用QueryBuilders工厂来获得。当出现多个查询条件(全文查询,精确查询,范围查询...)需要从QueryBuilders中获取BoolQueryBuilder拼起来所有的条件,最后通过request.source().query(boolQuery)整合搜索条件。如果需要编写函数查询,还需要把boolQuery作为它的原始查询。

request下还有如下四个操作:

  • ①查询
单字段查询
QueryBuilders.matchQuery("all","如家")
词条查询  
QueryBuilders.termQuery("city","杭州")
组合查询
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.termQuery("city", "杭州"));
boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(250));
1
2
3
4
5
6
7
8
  • ②分页
  • ③排序
  • ④高亮

分页,高亮(注意高亮结果不在"source"字段,在"highlight"字段获取,在原字段值的基础上加了标签,因此转化为java对象属性保存时也会带有标签,输入到前端值就会渲染)

//分页
searchRequest.source().from(0).size(5);
//排序
searchRequest.source().sort("price", SortOrder.ASC)
//高亮
 String s = hit.getSourceAsString();
Map<String, HighlightField> fields = hit.getHighlightFields();
HighlightField highlightField = fields.get("name");
String string = highlightField.getFragments()[0].string();
HotelDoc hotelDoc = JSON.parseObject(s, HotelDoc.class);
hotelDoc.setName(string);
1
2
3
4
5
6
7
8
9
10
11
编辑 (opens new window)
#中间件
上次更新: 2023/12/15, 15:49:57
Nginx配置问题
ES高级用法

← Nginx配置问题 ES高级用法→

Theme by Vdoing | Copyright © 2023-2024 blageCoder
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式