Elasticsearch简介
高性能分布式搜索引擎
基于lucene基础架构,使用Java语言开发的一个支持多集群,高亮,快速搜索的数据库
优势:
- 支持分布式,可水平扩展
- 提供Restful接口,可被任何语言调用
Elasticsearch倒排索引
基础概念
索引(index):相同类型的文档的集合--类似表
文档(document):每条数据就是一个文档--类似行
词条(term):文档按照语义分成的词语
字段(Field):JSON文档中的字段--类似列
映射(mapping):索引中文档的字段约束--类似表结构约束
DSL:JSON风格的请求语句,定义搜索条件--类似SQL
正向索引(MySQL)
基于文档id创建索引。根据id查询快,但是查询词条时必须先找到文档,而后判断是否包含词条
倒排索引
对文档内容分词,对词条创建索引,并记录词条所在文档的id。查询时先根据词条查询到文档id,而后根据文档id查询文档
IK分词器--中文分词器
允许我们配置拓展词典来增加自定义的词库,有ik_smart(粗粒度的切分模式)和ik_max_word(细粒度切分模式)。
作用:
- 创建倒排索引时,对文档分词
- 用户搜索时,对输入的内容分词
索引库与文档操作
索引库
- 创建索引库:PUT /索引库名
- 查询索引库:GET /索引库名
- 删除索引库:DELETE /索引库名
- 添加字段:PUT /索引库名/_mapping
mapping属性包括:
- type:字段数据类型,常见的简单类型有:
- 字符串:text(可分词的文本)、keyword(精确值,例如:品牌、国家、ip地址)
- 数值:long、integer、short、byte、double、float、
- 布尔:boolean
- 日期:date
- 对象:object
- index:是否创建索引,默认为true
- analyzer:使用哪种分词器
- properties:该字段的子字段
JavaRestClient客户端
- 创建XxxIndexRequest。XXX是Create、Get、Delete
- 准备请求参数( Create时需要)
- 发送请求。调用RestHighLevelClient#indices().xxx()方法,xxx是create、get(exists)、delete
文档
- 创建文档:POST /索引库名/_doc/文档id { json文档 }
- 查询文档:GET /索引库名/_doc/文档id
- 删除文档:DELETE /索引库名/_doc/文档id
- 修改文档:
- 全量修改:PUT /索引库名/_doc/文档id { json文档 }
- 增量修改:POST /索引库名/_update/文档id { "doc": {字段}}
JavaRestClient客户端
引入的依赖如下:
xml
代码解读
复制代码
`<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.4.3</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch-cli</artifactId>
<version>6.4.3</version>
<scope>compile</scope>
</dependency>`
- 初始化RestHighLevelClient
- 创建XxxRequest。XXX是Index、Get、Update、Delete
- 准备参数(Index和Update时需要)
- 发送请求。调用RestHighLevelClient#.xxx()方法,xxx是index、get、update、delete
- 解析结果(Get时需要)
DSL查询
分为两大类:
- 叶子查询(Leaf query clauses):一般是在特定的字段里查询特定值,属于简单查询,很少单独使用。
- 复合查询(Compound query clauses):以逻辑方式组合多个叶子查询或者更改叶子查询的行为方式。
在查询以后,还可以对查询的结果做处理,包括:
- 排序:按照1个或多个字段值做排序
- 分页:根据from和size做分页,类似MySQL
- 高亮:对搜索结果中的关键字添加特殊样式,使其更加醒目
- 聚合:对搜索结果做数据统计以形成报表
叶子查询
全文检索(full text)查询:利用分词器对用户输入内容分词,然后去词条列表中匹配。例如:
// match_query:根据一个字段查询
GET /indexName/_search
{
"query": {
"match": {
"FIELD": "TEXT"
}
}
}
// multi_match_query:根据多个字段查询,参与查询字段越多,查询性能越差
GET /indexName/_search
{
"query": {
"multi_match": {
"query": "TEXT",
"fields": ["FIELD1", " FIELD12"]
}
}
}
精确查询:词条级别的查询,不对用户输入内容分词,直接精确匹配,一般是查找keyword、数值、日期、布尔等类型。例如:
// term:根据词条精确匹配,一般搜索keyword类型、数值类型、布尔类型、日期类型字段
GET /indexName/_search
{
"query": {
"term": {
"FIELD": {
"value": "VALUE"
}
}
}
}
// range:根据数值范围查询,可以是数值、日期的范围
GET /indexName/_search
{
"query": {
"range": {
"FIELD": {
"gte": 10,
"lte": 20
}
}
}
}
复合查询
第一类:基于逻辑运算组合叶子查询,实现组合条件,例如: bool布尔查询是一个或多个查询子句的组合。子查询的组合方式有:
- must:必须匹配每个子查询,类似“与”
- should:选择性匹配子查询,类似“或”
- must_not:必须不匹配,不参与算分,类似“非”
- filter:必须匹配,不参与算分,用于筛选的
第二类:基于某种算法修改查询时的文档相关性算分,从而改变文档排名。(不常用,电商中的广告之类)
排序
Elasticsearch支持对搜索结果排序,默认是根据相关度算分(_score)来排序,也可以指定字段排序。可以排序字段类型有:keyword类型、数值类型、地理坐标类型、日期类型等
GET /indexName/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"FIELD": "desc" // 排序字段和排序方式ASC、DESC
}
]
}
分页
Elasticsearch 默认情况下只返回top10的数据。而如果要查询更多数据就需要修改分页参数了。通过修改from、size参数来控制要返回的分页结果:
GET /items/_search
{
"query": {
"match_all": {}
},
"from": 0, // 分页开始的位置,默认为0
"size": 10, // 期望获取的文档总数
"sort": [
{"price": "asc"}
]
}
针对深度分页,ES提供了两种解决方案,官方文档: search after:分页时需要排序,原理是从上一次的排序值开始,查询下一页数据。官方推荐使用的方式。 scroll:原理将排序数据形成快照,保存在内存。官方已经不推荐使用。
高亮显示
就是在搜索结果中把搜索关键字突出显示。
GET /items/_search
{
"query": {
"match": {
"name": "华为"
}
},
"from": 0, // 分页开始的位置
"size": 20, // 期望获取的文档总数
"sort": [
{ "price": "asc" }, // 普通排序
],
"highlight": {
"fields": { // 高亮字段
"name": {
"pre_tags": "<em>", // 高亮字段的前置标签
"post_tags": "</em>" // 高亮字段的后置标签
}
}
}
}
DSL聚合
统计所有商品中共有哪些商品分类,其实就是以分类(category)字段对数据分组。category值一样的放在同一组,属于Bucket聚合中的Term聚合。
默认情况下,Bucket聚合是对索引库的所有文档做聚合,我们可以限定要聚合的文档范围,只要添加query条件即可。
除了对数据分组(Bucket)以外,我们还可以对每个Bucket内的数据进一步做数据计算和统计。 例如:我想知道手机有哪些品牌,每个品牌的价格最小值、最大值、平均值。
GET /items/_search
{
"query": {"match_all": {}}, // 可以省略
"size": 0, // 设置size为0,结果中不包含文档,只包含聚合结果
"aggs": { // 定义聚合
"cateAgg": { //给聚合起个名字
"terms": { // 聚合的类型,按照品牌值聚合,所以选择term
"field": "category", // 参与聚合的字段
"size": 20 // 希望获取的聚合结果数量
}
}
}
}