简介:ElasticSearch基础知识详解
上一篇文章我们已经介绍了ElasticSearch的安装及基础配置相关的知识,今天我们再来聊聊ES数据库的基础使用。在使用ES数据库之前我们先来了解以下ES中的索引(Index)和文档(document):
1 索引(Index)
索引中存储具有相同结果的文档,每个索引中都有自己的mapping定义,mapping用于定义字段名称和类型。听上去,索引类似与MySQL中的表的定义,而mapping就像是表中的字段。
注意了,虽然听起来很想MySQL中表的定义,但是索引实际上是类似一本书的目录,目录中记录了文档内容、单词及文档id的关联关系及具体位置等信息
索引也分正排索引和倒排索引
正排索引:文档id到文档内容、单词的关联关系。例如,下面的通过id查询文档内容时,就是通过正排索引实现的
倒排索引:与正排索引相反,是单词到文档id的关联关系。例如,下面的通过关键词搜索内容时,就是通过倒排索引实现的
和MySQL数据库一样,索引也需要定义结构及索引中的字段名及类型等。这个结构就叫做mapping,而mapping中的字段的类型有如下几种:
类型 | 值 |
文本 | text、 keyword 其中text具有分词功能,keyword没有 |
数值 | long、integer、short、byte、double、float、half_float、scaled_float |
布尔 | boolean |
日期 | date |
范围 | integer_range、float_range、long_range、double_range、date_range |
对象 | object |
数组 | array |
二进制 | binary |
2 文档(document)
在ES中文档就是一个JSON Object,有字段(Field)组成,数据类型就是上面mapping中字段的类型。类似MySQL中的每一行的数据。但是ES中的每一行数据是一个JSON对象的形式。
3 操作ES中的资源
现在我们已经了解了ElasticSearch中的索引及文档相关知识,那我们怎么去操作这些资源呢?ES数据库提供了标准的REST API,格式大致如下所示:
http://localhost:9200/索引名称/文档id或某种操作
从资源的角度来看,API大致分为四类:创建、修改、删除、获取
对于上面这四类ES并没有区分API,而是以请求方式来判断,大致分为一些几种:
以上三种就是主要的请求方式,接下来我们针对资源的四种操作分别来看看具体体现形式
3.1 创建索引
创建索引的方式很简单,直接一个请求即可,没有任何参数,只需要url中定义索引名称即可
# 创建索引
curl -XPUT 'http://localhost:9200/待创建的索引名称'
3.2 自定义mapping
上面创建索引时没有自定义【mapping】,我们可以创建索引后再自定义【mapping】,当然创建索引时也可以自定义【mapping】信息。请求方式如下:
# 自定义某个索引的Mapping
curl -XPUT 'http://localhost:9200/索引名称'
{
"mappings":{
"dynamic":true,
"properties":{
"字段名1":{"type":"文本类型:text"},
"json格式的字段":{
"dynamic":false,
"properties":{
"字段名1":{"type":"整型:integer"}
}
}
}
}
}
注意:这是【PUT】请求,自定义的mapping内容在http的body中
dynamic(默认为true):为true时,如果插入的数据中有 没有定义 的字段,ES自动新增字段,他还可以针对mapping的某个json字段进行限制,比如:上面的json格式的字段中dynamic为false,表示当前json格式的字段中不会插入mapping中没有定义的字段
上述两个步骤其实也可以略,直接添加文档数据,例如下方API请求:
curl -XPOST 'http://localhost:9200/test_index/_doc'
{
"username":"测试",
"age":1
}
注意:这是一个 POST 请求
test_index:索引名称
_doc:这个时固定的,表示该请求添加数据到索引中。在ES6之前的版本中这个是可以文档类型,但是现在已经固定死了
我们在没有创建索引【test_index】的情况下,添加是文档数据到【test_index】索引中时,ES自动识别并创建索引及索引相关的【mapping】信息
3.3 查看索引相关信息
添加文档数据时自动识别的【mapping】信息可能不符合我们的预期效果,我们可以通过下方API查看索引信息及【mapping】信息:
# 获取某个索引信息
curl -XGET 'http://localhost:9200/索引名称'
# 获取某个索引的mapping信息
curl -XGET 'http://localhost:9200/索引名称/_mapping'
3.4 插入或修改 文档数据
首先我们来了解一下文档 ID ,在MySQL中我们经常会设置一个id字段并设置成主键,主要目的是让每一条数据都有一个唯一标识。在MySQL中这个标识不是必须的,但是ES中ID是必须存在的,如果我们没有自定义ID,ES数据库会自动帮我们生成一个唯一 ID 值
上面插入文档数据时,我们没有就指定id,但是 ES 自动帮我们生成了一个唯一ID值,当然我们也可以自己指定ID。
例如我们可以在URL中指定自定义 ID 值:
curl -XPOST 'http://localhost:9200/索引名/_doc/a111'
{
"username":"测试",
"age":1
}
注意:url最后面的【a111】就是我们自定义的 ID 值
修改时也是当前API,body参数为新的数据
3.5 批量添加、修改、删除数据
如果需要同时插入多条数据时,我们可以通过body传参,ID也在body中,具体格式如下:
curl -XPOST 'http://localhost:9200/索引名/_bulk'
{"index":{"_id":1}}
{"id":1,"name":"PHP面向对象","author":"星歌","cat_id":1,"recommend":1,"image":"https://www.motui8.cn/upload/img/f8/f7a0dee9f65c90a0b112a0e2170521.jpg","intro":"public公有的类成员,可以在任何地方被访问。protected受保护的类成员,可以被其自身以及其子类访问。private私有的类成员,只能被自身访问","status":1,"browse_num":11,"create_time":"2023-06-29 12:56:59"}
{"index":{"_id":2}}
{"id":1,"name":"MySQL数据类型","author":"星歌","cat_id":3,"recommend":0,"image":"https://www.motui8.cn/upload/img/ed/6ffbf5ed60a36e2d60d6c9254fe2d6.png","intro":"ZEROFILL :当数值长度小于指定长度用0 填补,添加ZEROFILL字段属性会自动添加UNSIGNED,DECIMAL[M[,D]] [UNSIGNED无符号位|ZEROFILL],一般涉及金额问题都会用DECIMAL,避免精度丢失问题","status":1,"browse_num":11,"create_time":"2023-06-29 12:56:59"}
{
"id":8,"name":"解析url获取相关信息","author":"星歌","cat_id":1,"recommend":1,
"image":"https://www.motui8.cn/upload/img/15/47de0fe1ac4b4ad0897f935c1af6ba.png",
"intro":"解析url获取相关信息","status":1,"browse_num":11,
"create_time":"2023-06-29 12:56:59",
"detail":{
"content":"今天开发sass管理后台时,遇到这样一个需求:商户在平台设置自己平台的url,平台需要针对当前url拼接平台给定的参数。\n以前也经常遇到这类需要,但是总是忘记具体代码,今天我就总结一下吧!\n\nPHP解析URL\n在我的记忆中,PHP解析url时经常使用【pathinfo】函数,但是经常会遇到各种奇葩问题,所以今天我们使用【parse_url】来解析url。\n最开始我想着参数不多就自己直接在用户设置的url后拼接参数,代码如下:"
}
}
注意:批量添加数据时,自定义的id格式固定【{"index":{"_id":"自定义的id值"}}】
ES自定义的id与实际数据中的id不是同一个意思哦,只要ES自定义的ID不同,即使内容完全一样,也会从新添加到索引中。如果自定义的ID已存在时会变成修改操作
上述API为添加和修改操作,如需删除可以使用下面的方式:
curl -XPOST 'http://localhost:9200/索引名/_bulk'
{"delete":{"_id":2}}
{"delete":{"_id":3}}
注意:批量删除依然是 POST 请求哦,参数格式固定【{"delete":{"_id":‘ES的id’}}】
3.6 查询数据
通过ES的文档id查询数据,这种方式一般比较少用:
curl -XGET 'http://localhost:9200/索引名称/_doc/文档id'
通过搜索获取文档列表,这种方式主要应用搜索,使用频率最多的就是这个:
curl -XGET 'http://localhost:9200/索引名称/_search'
{
"_source":["name"]
"query":{
"term":{
"name":"PHP"
}
}
}
注意:json数据在http的body中。如果不指定json数据时,查询的是所有数据
_source:这个字段表明返回的文档的字段。如果是false则不返回文档数据,如果需要指定返回的字段,可以以数组的形式设置,例如:{"_source":["字段1","字段2".....]}。此外不设置该字段时,返回所有字段的数据
其中query类型分为两种,一种是全文匹配,还有一种是单词匹配。
单词匹配:
不会对查询语句做分词处理,直接去匹配字段的倒排索引。例如:term、terms、range 等 query 类型。就如同上面的例子一样,如果需要查询多个字段的值等于某个值时,格式和下方的全文匹配的示例一样。
全文匹配:
就是针对 text 类型的字段进行全文检索,会对查询语句进行分词处理,例如:match,match_phrase 等 query 类型。例如,我们需要查询多个字段进行全文匹配:
curl -XGET 'http://localhost:9200/索引名称/_search'
{
"query":{
"query_string":{
"fields":["username","intro"],
"query":"phpOR redis"
}
}
}
注意:query_string->fields 是我们需要查询的字段
query_string->query 是匹配的值。其中 OR 等同于逻辑运算符【或】,可以使用【AND】及【NOT】
如果需要查询某个json对象下的某个字段时,可以使用【field.field】方式指定字段,具体格式如下:
curl -XGET 'http://localhost:9200/索引名称/_search'
{
"query":{
"query_string":{
"fields":["username","intro","detail.content"],
"query":"php"
}
}
}
复杂查询
复杂查询常用的有两类,一个是constant_score查询,还有 bool 查询。
constant_score 查询格式:
curl -XGET 'http://localhost:9200/索引名称/_search'
{
"query":{
"constant_score":{
"filter":{
"match":{
"username":"admin"
}
}
}
}
}
bool查询格式:
curl -XGET 'http://localhost:9200/索引名称/_search'
{
"query":{
"bool":{
"filter":{
"match":{
"name":"admin"
},
"term":{
"name":"admin"
}
}
}
}
}
注意:filter 查询只会过滤符合条件的文档,不会进行相关性算分。此外,ES 针对 filter会有缓存。因此filter相比于match及term的性能要高很多
统计相关
统计相关其实就是聚合查询,例如查询符合条件的文档数:
curl -XGET 'http://localhost:9200/索引名称/_count'
{
"query":{
"constant_score":{
"filter":{
"match":{
"username":"admin"
}
}
}
}
}
基础知识和基本操作就这么多了,后期有时间会继续更新 elasticsearch 的其他相关知识和操作经验