零基础学习Elasticsearch系列【二】

通过上一篇我们已经了解了es的介绍和es文档的操作,本文将介绍es的映射管理和各种高级查询,通过对es的各种查询能够更加了解es的操作

一、映射管理

映射类似于数据库中的表结构

  • 创建映射

    创建映射之前,应当先创建索引

    PUT请求,http://127.0.0.1:9200/student

    然后向 ES 服务器发 PUT 请求 :http://127.0.0.1:9200/student/_mapping

    请求体为:

    json 复制代码
    {
        "properties": {
            "name": {
                "type": "text",
                "index": true
            },
            "sex": {
                "type": "text",
                "index": false
            },
            "age": {
                "type": "long",
                "index": false
            }
        }
    }

    返回结果为:

    json 复制代码
    {
        "acknowledged": true
    }

    注意:

    json 复制代码
    "sex": {
        "type": "text",
        "index": false
    }

    index = false 会导致无法查询

    映射数据说明:

  • 字段名:任意填写,下面指定许多属性,例如:title、subtitle、images、price

  • type:类型,Elasticsearch 中支持的数据类型非常丰富,说几个关键的:

    • String 类型,又分两种:

      • text:可分词
      • keyword:不可分词,数据会作为完整字段进行匹配
    • Numerical:数值类型,分两类

      • 基本数据类型:long、integer、short、byte、double、float、half_float
      • 浮点数的高精度类型:scaled_float
    • Date:日期类型

    • Array:数组类型

    • Object:对象

  • index:是否索引,默认为 true,也就是说你不进行任何配置,所有字段都会被索引。 true:字段会被索引,则可以用来进行搜索 false:字段不会被索引,不能用来搜索

  • store:是否将数据进行独立存储,默认为 false 原始的文本会存储在source 里面,默认情况下其他提取出来的字段都不是独立存储 的,是从source 里面提取出来的。当然你也可以独立的存储某个字段,只要设置 "store": true 即可,获取独立存储的字段要比从_source 中解析快得多,但是也会占用 更多的空间,所以要根据实际业务需求来设置。

  • analyzer:分词器,这里的 ik_max_word 即使用 ik 分词器

  • 查看映射

    向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_mapping

    响应结果如下:

    json 复制代码
    {
        "student": {
            "aliases": {},
            "mappings": {
                "properties": {
                    "age": {
                        "type": "long"
                    },
                    "name": {
                        "type": "text"
                    },
                    "sex": {
                        "type": "text",
                        "index": false
                    }
                }
            },
            "settings": {
                "index": {
                    "creation_date": "1693989843117",
                    "number_of_shards": "1",
                    "number_of_replicas": "1",
                    "uuid": "17zS0l19SdmRqWLi-j_6bQ",
                    "version": {
                        "created": "7080099"
                    },
                    "provided_name": "student"
                }
            }
        }
    }
  • 索引映射关联

    意思就是在创建索引的同时,指定映射

    向 ES 服务器发 PUT 请求 :http://127.0.0.1:9200/student1

    请求体:

    json 复制代码
    {
        "settings": {},
        "mappings": {
            "properties": {
                "name": {
                    "type": "text",
                    "index": true
    ​
                },
                "sex": {
                    "type": "text",
                    "index": true
                },
                "age": {
                    "type": "long",
                    "index": true
                }
            }
        }
    }

    响应结果:

    json 复制代码
    {
        "acknowledged": true,
        "shards_acknowledged": true,
        "index": "student1"
    }
  • 映射的删除

    在删除索引的同时,映射也会被删除

二、高级查询

Elasticsearch 提供了基于 JSON 提供完整的查询 DSL 来定义查询

定义数据 :

bash 复制代码
# POST /student/_doc/1001
{
"name":"zhangsan",
"nickname":"zhangsan",
 "sex":"男",
 "age":30
}
# POST /student/_doc/1002
{
"name":"lisi",
"nickname":"lisi",
 "sex":"男",
 "age":20
}
# POST /student/_doc/1003
{
"name":"wangwu",
 "nickname":"wangwu",
 "sex":"女",
 "age":40
}
# POST /student/_doc/1004
{
"name":"zhangsan1",
"nickname":"zhangsan1",
 "sex":"女",
 "age":50
}
# POST /student/_doc/1005
{
"name":"zhangsan2",
"nickname":"zhangsan2",
 "sex":"女",
 "age":30
}

1. 查询所有文档

向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

无请求体也会返回所有数据,默认十条

或者使用请求体,但结果是一样的:

json 复制代码
{
    "query": {
        "match_all": {}
    }
}
​

2. 匹配查询

发 GET 请求 :http://127.0.0.1:9200/student/_search

多个词条之间是or的关系

json 复制代码
{
    "query": {
        "match": {
            "name":"zhangsan,lisi"
        }
    }
}

响应内容:

json 复制代码
{
    "took": 47,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 2,
            "relation": "eq"
        },
        "max_score": 1.3862942,
        "hits": [
            {
                "_index": "student",
                "_type": "_doc",
                "_id": "1001",
                "_score": 1.3862942,
                "_source": {
                    "name": "zhangsan",
                    "nickname": "zhangsan",
                    "sex": "男",
                    "age": 30
                }
            },
            {
                "_index": "student",
                "_type": "_doc",
                "_id": "1002",
                "_score": 1.3862942,
                "_source": {
                    "name": "lisi",
                    "nickname": "lisi",
                    "sex": "男",
                    "age": 20
                }
            }
        ]
    }
}

3. 字段匹配查询

multi_match 与 match 类似,不同的是它可以在多个字段中查询。

在 Postman 中,向 ES 服务器发 GET 请求 :http://127.0.0.1:9200/student/_search

json 复制代码
{
    "query": {
        "multi_match": {
            "query": "zhangsan",
            "fields": ["name", "nickname"]
        }
    }
}

响应结果为:

json 复制代码
{
    "took": 47,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 1,
            "relation": "eq"
        },
        "max_score": 1.3862942,
        "hits": [
            {
                "_index": "student",
                "_type": "_doc",
                "_id": "1001",
                "_score": 1.3862942,
                "_source": {
                    "name": "zhangsan",
                    "nickname": "zhangsan",
                    "sex": "男",
                    "age": 30
                }
            }
        ]
    }
}

4. 关键字匹配查询

json 复制代码
{
    "query": {
        "term": {
            "name": {
                "value": "zhangsan"
            }
        }
    }
}

5. 多关键字精确查询

json 复制代码
{
    "query": {
        "terms": {
            "name": ["zhangsan", "lisi"]
        }
    }
}

6. 指定查询字段

json 复制代码
{
    "_source": ["name", "nickname"],
    "query": {
        "terms": {
            "nickname": ["zhangsan"]
        }
    }
}

响应结果:

json 复制代码
{
    "took": 35,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 1,
            "relation": "eq"
        },
        "max_score": 1.0,
        "hits": [
            {
                "_index": "student",
                "_type": "_doc",
                "_id": "1001",
                "_score": 1.0,
                "_source": {
                    "name": "zhangsan",
                    "nickname": "zhangsan"
                }
            }
        ]
    }
}

7. 过滤字段

includes:来指定想要显示的字段

excludes:来指定不想要显示的字段

包含请求体:

json 复制代码
{
    "_source": {
        "includes": ["name", "nickname"]
    },
    "query": {
        "terms": {
            "nickname": ["zhangsan"]
        }
    }
}
​

不包含请求体:

json 复制代码
{
    "_source": {
        "excludes": ["name", "nickname"]
    },
    "query": {
        "terms": {
            "nickname": ["zhangsan"]
        }
    }
}

8. 组合查询

查询名字是 zhangsan,并且年龄不是40的

json 复制代码
{
    "query": {
        "bool": {
            "must": [{
                "match": {
                    "name": "zhangsan"
                }
            }],
            "must_not": [{
                "match": {
                    "age": "40"
                }
            }]
        }
    }
}

9. 范围查询

操作符 说明
gt >
gte >=
lt <
lte <=

例子:查询大于等于30并且小于等于50的

json 复制代码
{
    "query": {
        "range": {
            "age": {
                "gte": 30,
                "lte": 35
            }
        }
    }
}

返回结果:

json 复制代码
{
    "took": 1017,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 2,
            "relation": "eq"
        },
        "max_score": 1.0,
        "hits": [
            {
                "_index": "student",
                "_type": "_doc",
                "_id": "1001",
                "_score": 1.0,
                "_source": {
                    "name": "zhangsan",
                    "nickname": "zhangsan",
                    "sex": "男",
                    "age": 30
                }
            },
            {
                "_index": "student",
                "_type": "_doc",
                "_id": "1005",
                "_score": 1.0,
                "_source": {
                    "name": "zhangsan2",
                    "nickname": "zhangsan2",
                    "sex": "女",
                    "age": 30
                }
            }
        ]
    }
}

10. 模糊查询

fuzzy,fuzzy的查询不分词

有个偏移量,用户输入错误的内容,也可以查询到正确的结果

比如:用户想查询name等于zhangsan的数据,但手误打成了 zhangsn

json 复制代码
{
    "query": {
        "fuzzy": {
            "name": {
                "value": "zhangsn"
            }
        }
    }
}

返回结果

json 复制代码
{
    "took": 106,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 3,
            "relation": "eq"
        },
        "max_score": 1.1882522,
        "hits": [
            {
                "_index": "student",
                "_type": "_doc",
                "_id": "1001",
                "_score": 1.1882522,
                "_source": {
                    "name": "zhangsan",
                    "nickname": "zhangsan",
                    "sex": "男",
                    "age": 30
                }
            },
            {
                "_index": "student",
                "_type": "_doc",
                "_id": "1004",
                "_score": 0.9902103,
                "_source": {
                    "name": "zhangsan1",
                    "nickname": "zhangsan1",
                    "sex": "女",
                    "age": 50
                }
            },
            {
                "_index": "student",
                "_type": "_doc",
                "_id": "1005",
                "_score": 0.9902103,
                "_source": {
                    "name": "zhangsan2",
                    "nickname": "zhangsan2",
                    "sex": "女",
                    "age": 30
                }
            }
        ]
    }
}

11. 单字段排序

sort 可以让我们按照不同的字段进行排序,并且通过 order 指定排序的方式。desc 降序,asc 升序

例子:

css 复制代码
{
    "query": {
        "match": {
            "name": "zhangsan"
        }
    },
    "sort": [{
        "age": {
            "order": "desc"
        }
    }]
}

12. 多字段排序

使用 age 和 _score 进行查询,并且匹配的结果首先按照年龄排序,然后 按照相关性得分排序

css 复制代码
{
    "query": {
        "match_all": {}
    },
    "sort": [{
            "age": {
                "order": "desc"
            }
        },
        {
            "_score": {
                "order": "desc"
            }
        }
    ]
}

13. 高亮查询

Elasticsearch 可以对查询内容中的关键字部分,进行标签和样式(高亮)的设置。

在使用 match 查询的同时,加上一个 highlight 属性:

  • pre_tags:前置标签
  • post_tags:后置标签
  • fields:需要高亮的字段
  • title:这里声明 title 字段需要高亮,后面可以为这个字段设置特有配置,也可以空
json 复制代码
{
    "query": {
        "match": {
            "name": "zhangsan"
        }
    },
    "highlight": {
        "pre_tags": "<font color='red'>",
        "post_tags": "</font>",
        "fields": {
            "name": {}
        }
    }
}

响应结果:

json 复制代码
{
    "took": 184,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 1,
            "relation": "eq"
        },
        "max_score": 1.3862942,
        "hits": [
            {
                "_index": "student",
                "_type": "_doc",
                "_id": "1001",
                "_score": 1.3862942,
                "_source": {
                    "name": "zhangsan",
                    "nickname": "zhangsan",
                    "sex": "男",
                    "age": 30
                },
                "highlight": {
                    "name": [
                        "<font color='red'>zhangsan</font>"
                    ]
                }
            }
        ]
    }
}

14. 分页查询

css 复制代码
{
    "query": {
        "match_all": {}
    },
    "sort": [{
        "age": {
            "order": "desc"
        }
    }],
    "from": 0,
    "size": 2
}

15. 聚合查询

可以通过聚合查询平均值,最大、最小值

比如,查询最大的年龄

json 复制代码
{
    "aggs": {
        "max_age": {
            "max": {
                "field": "age"
            }
        }
    },
    "size": 0
}

注意这里的 size为0,因为我们不需要查询的数据,只需要聚合的数据就可以

结果如下:

json 复制代码
{
    "took": 196,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 5,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    },
    "aggregations": {
        "max_age": {
            "value": 50.0
        }
    }
}

可以看到最大的年龄为50

16. 桶聚合查询

相当于分组统计,group by

例如:分组统计每个年龄的数量

json 复制代码
{
    "aggs": {
        "age_groupby": {
            "terms": {
                "field": "age"
            }
        }
    },
    "size": 0
}

响应结果:

json 复制代码
{
    "took": 67,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 5,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    },
    "aggregations": {
        "age_groupby": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
                {
                    "key": 30,
                    "doc_count": 2
                },
                {
                    "key": 20,
                    "doc_count": 1
                },
                {
                    "key": 40,
                    "doc_count": 1
                },
                {
                    "key": 50,
                    "doc_count": 1
                }
            ]
        }
    }
}

三、总结

本文学习了对es映射的增删改查,还有对es的各种查询,已经基本满足使用需求。但更为复杂的查询还得查询官方文档或者技术博客。

这里放上官方文档链接,更为全面的查询,官方文档

ps:更多的时候,我们是不用自己去写查询条件的,有个插件叫 essql,开源地址为:传送门,我们可以下载对应的版本,然后去写普通的sql就可以了,他可以帮我们转成 es的查询语句,方便快捷,简单易食用

相关推荐
婪苏3 分钟前
Python 元类:类的创造者
后端
陈随易8 分钟前
Kimi k2发布,效果比肩Sonnet4,价格与DeepSeek一致
前端·后端·程序员
到账一个亿17 分钟前
代码的隐形守护者:Spring AOP 是如何做到的?
后端
SparkX开源AI知识库18 分钟前
SparkX开源AI知识库系统V1.0.0发布
后端
知其然亦知其所以然25 分钟前
Java 面试高频题:GC 到底回收了什么、怎么回收、啥时候回收?
java·后端·面试
Z_W_H_26 分钟前
【SpringBoot】 整合MyBatis+Postgresql
java·spring boot·后端
lihainuo37 分钟前
Next.js + AI-SDK 实战:模型注册表从类型设计到工具调用全解析
后端·node.js
考虑考虑1 小时前
Redis8新增特性
redis·后端·程序员
labixiong1 小时前
全方位理解跨源资源共享-CORS
前端·后端
AntBlack1 小时前
闲谈 :AI编程效率反而降低了 ,大家AI 编程的正确姿势到底是什么?
前端·后端·ai编程