ElasticSearch基础知识

简介: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,而是以请求方式来判断,大致分为一些几种:

  • GET:获取资源
  • PUT/POST:创建或修改资源
  • DELETE:删除资源

以上三种就是主要的请求方式,接下来我们针对资源的四种操作分别来看看具体体现形式

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格式的字段中dynamicfalse,表示当前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类型分为两种,一种是全文匹配,还有一种是单词匹配。

单词匹配:

不会对查询语句做分词处理,直接去匹配字段的倒排索引。例如:termtermsrange 等 query 类型。就如同上面的例子一样,如果需要查询多个字段的值等于某个值时,格式和下方的全文匹配的示例一样。

全文匹配:

就是针对 text 类型的字段进行全文检索,会对查询语句进行分词处理,例如:matchmatch_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 的其他相关知识和操作经验

编程经验共享公众号二维码

编程经验共享公众号二维码
更多内容关注公众号
Copyright © 2021 编程经验共享 赣ICP备2021010401号-1