前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Elasticsearch初检索及高级

Elasticsearch初检索及高级

作者头像
乐心湖
发布2021-01-18 15:01:45
1.1K0
发布2021-01-18 15:01:45
举报
文章被收录于专栏:MyTechnology

初级检索

_cat

API

简介

GET /_cat/nodes

查看所有节点

GET /_cat/health

查看 es 健康状况

GET /_cat/master

查看主节点

GET /_cat/indices

查看所有索引 show databases;

索引文档(CRUD)

保存文档

保存一个数据,保存在哪个索引的哪个类型下,指定用哪个唯一标识

PUT customer/external/1在 customer 索引下的 external 类型下保存 1号数据

代码语言:javascript
复制
{
    "name":"乐心湖"
}

PUT 和 POST 都可以; POST 可以新增可以修改。可以选择是否指定id,如果不指定id,会自动生成id。指定id就会修改这个数据,并新增版本号; PUT 可以新增可以修改。PUT必须指定id;由于PUT需要指定id,我们一般都用来做修改操作,不指定d会报错;

查询文档

GET custome/external/1在 customer 索引下的 external 类型下查询 1号数据

结果分析

代码语言:javascript
复制
{
    "_index": "customer",      // 索引
    "_type": "external",    // 类型
    "_id": "1",                // 记录id
    "_version": 2,            // 版本号
    "_seq_no": 1,            // 并发控制字段,每次更新就会+1,用来做乐观锁
    "_primary_term": 1,        // 同上,主分片重新分配,如重启,就会变化
    "found": true,
    "_source": {
        "name": "钟小湖"
    }
}

更新文档

有两种方式,效果一样。

POST custome/external/1当带有 _update 时,为局部更新文档,此时的内容格式需要调整,写在 "doc" 里面,例如:

http://192.168.152.129:9200/customer/external/1/_update

代码语言:javascript
复制
{
    "doc":{
        "name": "钟小湖5"
    }
}

PUT customer/external/1

删除文档

DELETE customer/external/1

DELETE customer

Elasticsearch 没有提供删除类型的API,其实你可以把Type下的所有Document删除掉,也相当于删除了Type

批量保存

POST customer/external/_bulk

这个需要在 Kibana 中使用,数据结构稍有不同

代码语言:javascript
复制
{"index":{"_id":"1"}}
{"name":"钟小湖"}
{"index":{"_id":"2"}}
{"name":"乐心湖"}

数据格式

代码语言:javascript
复制
{action:{metadata}}\n
{requeestBody}\n
{action:{metadata}}\n
{requesetbod }\n

导入样本测试数据,方便后续学习。

POST bank/account/_bulk

https://github.com/elastic/elasticsearch/edit/master/docs/src/test/resources/accounts.json

高级检索

SearchAPi

ES 支持两种基本方式检索:

  • 一个是通过使用 REST request URL,发送搜索参数,(uri + 检索参数)
  • 另一个是通过使用 REST request bod 来发送他们,(uri + 请求体)

发送请求

GET /bank/_search?q=*&sort=account_number:asc

响应结果

代码语言:javascript
复制
{
    "took" : 2,
    "timed_out" : false,
    "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
    },
    "hits" : {
        "total" : {
            "value" : 1000,
            "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [
            {
                "_index" : "bank",
                "_type" : "account",
                "_id" : "40",
                "_score" : null,
                "_source" : {
                    "account_number" : 40,
                    "balance" : 33882,
                    "firstname" : "Pace",
                    "lastname" : "Molina",
                    "age" : 40,
                    "gender" : "M",
                    "address" : "263 Ovington Court",
                    "employer" : "Cytrak",
                    "email" : "pacemolina@cytrak.com",
                    "city" : "Silkworth",
                    "state" : "OR"
                },
                "sort" : [
                    40,
                    40
                ]
            },
            ...
        ]

The response also provides the following information about the search request:

  • took – how long it took Elasticsearch to run the query, in milliseconds
  • timed_out – whether or not the search request timed out
  • _shards – how many shards were searched and a breakdown of how many shards succeeded, failed, or were skipped.
  • max_score – the score of the most relevant document found
  • hits.total.value - how many matching documents were found
  • hits.sort - the document’s sort position (when not sorting by relevance score)
  • hits._score - the document’s relevance score (not applicable when using match_all)

(1)只有6条数据,这是因为存在分页查询;

(2)详细的字段信息,参照: https://www.elastic.co/guide/en/elasticsearch/reference/current/getting-started-search.html

  • took - Elasticearch执行搜索的时间(毫秒)
  • time_ out - 告诉我们搜索是否超时
  • _shards - 告诉我们多少个分片被搜索了,以及统计了成功/失败的搜索分片
  • hit - 搜索结果
  • hits.total - 搜索结果
  • hits.hits - 实际的搜索结果数组(默认为前10的文档)
  • sort - 结果的排序key (键) (没有则按 score 排序)
  • score 和 max score - 相关性得分和最高得分(全文检索用)

HTTP 客户端工具(POSTMAN),get请求不能携带请求体,我们变为 post 也一样的 我们 POST 一个 JSON 风格的查询请求体到 _search API

一旦搜索结果被返回,ES 就完成了这次请求的搜索,并且不会维护任何服务端的资源或者结果的 cursor(游标)

当然你可以用 uri+请求体 进行检索在 Kibana 中使用,也就是第二种方法。

代码语言:javascript
复制
GET /bank/_search
{
  "query": { "match_all": {} },
  "sort": [
    { "age": "desc"},
    { "account_number": "asc" }
  ]
}

Query DSL

基本语法格式

Elasticsearch 提供了一个可以执行查询的Json风格的DSL。这个被称为Query DSL,该查询语言非常全面。

一个查询语句的典型结构

代码语言:javascript
复制
QUERY_NAME:{
   ARGUMENT:VALUE,
   ARGUMENT:VALUE,...
}

例子:

代码语言:javascript
复制
GET /bank/_search
{
  "query": { "match_all": {} },
  "sort": [
    { "age": "desc" },
    { "account_number": "asc" }
  ],
  "from": "1",
  "size": "2"
}

query定义如何查询

  • match_all 查询类型(代表查询所有的所有),es 中可以在 query 中组合非常多的查询类型完成复杂查询;
  • 除了 query 参数之外,我们也可以传递其他的参数以改变查询结果,如 sort,size;
  • from+size 限定,完成分页功能;
  • sort排序,多字段排序,会在前序字段相等时后续字段内部排序,否则以前序为准;

如果针对于某个字段

代码语言:javascript
复制
{
  QUERY_NAME:{
     FIELD_NAME:{
       ARGUMENT:VALUE,
       ARGUMENT:VALUE,...
      }   
   }
}

返回部分字段

增加 "_source"

代码语言:javascript
复制
GET /bank/_search
{
  "query": { "match_all": {} },
  "sort": [
    { "age": "desc" },
    { "account_number": "asc" }
  ],
  "from": "1",
  "size": "2",
  "_source": ["firstname","age"]
}

match匹配查询

增加 matchmatch 返回 age=24 的数据。

代码语言:javascript
复制
GET /bank/_search
{
  "query": { 
    "match": { "age": "24" }
  },
  "sort": [
    { "account_number": "asc" }
  ],
  "from": "1",
  "size": "2",
  "_source": ["firstname","age"]
}

属性为基本类型(非字符串)时,精确控制

属性为字符串时,全文检索(模糊查询)

代码语言:javascript
复制
GET /bank/_search
{
  "query": { 
    "match": { "address": "mill lane" }
  }
}

全文检索,最终会按照评分(score)进行排序,会对检索条件进行分词匹配。

match_phrase短句匹配

将需要匹配的值当成一整个单词(不分词)进行检索

查处address中包含mill_road的所有记录,并给出相关性得分

代码语言:javascript
复制
GET bank/_search
{
  "query": {
    "match_phrase": {
      "address": "mill road"
    }
  }
}

使用match的keyword

文本字段的匹配,使用keyword,匹配的条件就是要显示字段的全部值,要进行精确匹配的。

match_phrase是做短语匹配,只要文本中包含匹配条件,就能匹配到。

搜不到文档

代码语言:javascript
复制
GET bank/_search
{
  "query": {
    "match": {
      "address.keyword": "990 Mill"
    }
  }
}

一条文档

代码语言:javascript
复制
GET bank/_search
{
  "query": {
    "match": {
      "address.keyword": "990 Mill Road"
    }
  }
}

multi_math多字段匹配

state或者address中包含mill,并且在查询过程中,会对于查询条件进行分词。

代码语言:javascript
复制
GET bank/_search
{
  "query": {
    "multi_match": {
      "query": "mill",
      "fields": [
        "address",
        "state"
      ]
    }
  }
}

bool用来做复合查询

复合语句可以合并任何其他查询语句,包括符合语句。这也就意味着,复合语句之间可以互相嵌套,可以表达非常复杂的逻辑。

must:必须达到must 所列举的所有条件

should:应该达到 should 列举的条件,如果达到会增加相关文档的评分,并不会改变查询的结果,如果 query 中只有 should 且只有一种匹配规则,那么 should 的条件就会被作为默认匹配条件而区改变查询结果。

must_not:必须不是指定的情况

代码语言:javascript
复制
GET /bank/_search
{
    "query": {
        "bool": {
            "must": [
                {
                    "match": {
                        "gender": "M"
                    }
                },
                {
                    "match": {
                        "address": "mill"
                    }
                }
            ],
            "must_not": [
                {"match":{
                    "age":"38"
                }}
            ],
            "should": [
                {"match": {
                    "lastname": "Wallace"
                }}
            ]
        }
    }
}

Filter结果过滤

并不是所有的查询都需要产生分数,特别是哪些仅用于filtering过滤的文档。为了不计算分数,elasticsearch会自动检查场景并且优化查询的执行。

filter在使用过程中,并不会计算相关性得分。

代码语言:javascript
复制
GET /bank/_search
{
  "query": {
    "bool": {
      "filter": {
        "range": {
          "age": {
            "gte": 30,
            "lte": 40
          }
        }
      }
    }
  }
}

must 混用,在此基础上过滤出合适的结果。

代码语言:javascript
复制
GET /bank/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {
          "address": "mill"
        }}
      ],
      "filter": {
        "range": {
          "age": {
            "gte": 30,
            "lte": 40
          }
        }
      }
    }
  }
}

这里先是查询所有匹配 address=mill 的文档,然后再根据 30<=age<=40 进行过滤查询结果

在boolean查询中,must, shouldmust_not 元素都被称为查询子句 。 文档是否符合每个“must”或“should”子句中的标准,决定了文档的“相关性得分”。 得分越高,文档越符合您的搜索条件。 默认情况下,Elasticsearch返回根据这些相关性得分排序的文档。 must_not 子句中的条件被视为“过滤器”。它影响文档是否包含在结果中, 但不影响文档的评分方式。还可以显式地指定任意过滤器来包含或排除基于结构化数据的文档。

term

和match一样。匹配某个属性的值。全文检索字段用 match,其他非text字段匹配用 term

Avoid using the term query for text fields. 避免对文本字段使用“term”查询 By default, Elasticsearch changes the values of text fields as part of analysis. This can make finding exact matches for text field values difficult. 默认情况下,Elasticsearch作为analysis的一部分更改 “text”字段的值。这使得为“text”字段值寻找精确匹配变得困难。undefinedTo search text field values, use the match. 要搜索“text”字段值,请使用匹配。 https://www.elastic.co/guide/en/elasticsearch/reference/7.6/query-dsl-term-query.html

使用term匹配查询

代码语言:javascript
复制
GET bank/_search
{
  "query": {
    "term": {
      "address": "mill Road"
    }
  }
}

查询结果:

代码语言:javascript
复制
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}

一条也没有匹配到

而更换为match匹配时,能够匹配到32个文档

因此,全文检索字段用 match,其他非text字段匹配用 term

例如:address 用 mathch;age 用 term;

Aggregation(聚合)

聚合提供了从数据中分组和提取数据的能力。最简单的聚合方法大致等于SQL Group by和SQL聚合函数。在elasticsearch中,执行搜索返回hits(命中结果),并且同时返回聚合结果,把已响应中的所有hits(命中结果)分隔开。这是非常强大且有效的,你可以执行查询和多个聚合,并且在一次使用中得到各自的(任何一个的)返回结果。

基本语法

代码语言:javascript
复制
{
  "aggs": {
    "my-agg-name": {
      "terms": {
        "field": "my-field"
      }
    }
  }
}

搜索 address 中包含 mill 的所有人的年龄分布以及平均年龄,但不显示这些人的详情

代码语言:javascript
复制
GET /bank/_search
{
  "query": {
    "match": {
      "address": "Mill"
    }
  }, 
  "aggs": {
    "ageAgg": {
      "terms": {
        "field": "age"
      }
    },
    "ageAvg": {
      "avg": {
        "field": "age"
      }
    }
  },
  "size": 0
}

从结果可以看到,搜索的详细结果 htis 没有展示了,原因是我们加了 "size": 0


按照年龄聚合,并且求这些年龄段的这些人的平均薪资

相当于在聚合中再添一层聚合

代码语言:javascript
复制
GET /bank/_search
{
  "aggs": {
    "ageAgg": {
      "terms": {
        "field": "age"
      },
      "aggs": {
        "balanceAgg": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  },
  "size": 0
}

查出所有年龄分布,并且这些年龄段中性别M的平均薪资和F的平均薪资以及这个年龄段的总体平均薪资

代码语言:javascript
复制
GET /bank/_search
{
  "aggs": {
    "ageAgg": {
      "terms": {
        "field": "age"
      },
      "aggs": {
        "genderAgeAgg": {
          "terms": {
            "field": "gender.keyword"
          },
          "aggs": {
            "balanceGenderAgeAgg": {
              "avg": {
                "field": "balance"
              }
            }
          }
        },
        "balanceAgeAgg": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  },
  "size": 0
}

结果

代码语言:javascript
复制
{
    "key" : 31,
    "doc_count" : 61,
    "balanceAgeAgg" : {
        "value" : 28312.918032786885
    },
    "genderAgeAgg" : {
        "doc_count_error_upper_bound" : 0,
        "sum_other_doc_count" : 0,
        "buckets" : [
            {
                "key" : "M",
                "doc_count" : 35,
                "balanceGenderAgeAgg" : {
                    "value" : 29565.628571428573
                }
            },
            {
                "key" : "F",
                "doc_count" : 26,
                "balanceGenderAgeAgg" : {
                    "value" : 26626.576923076922
                }
            }
        ]
    }
},

Mapping

Maping 是用来定义一个文档(document),以及它所包含的属性(field)是如何存储和索引的。

使用maping来定义

  • 哪些字符串属性应该被看做全文本属性(full text fields);
  • 哪些属性包含数字,日期或地理位置;
  • 文档中的所有属性是否都嫩被索引(all 配置);
  • 日期的格式;
  • 自定义映射规则来执行动态添加属性;

查看mapping信息 GET bank/_mapping


创建索引并指定映射

代码语言:javascript
复制
PUT /my_index
{
  "mappings": {
    "properties": {
      "age": {
        "type": "integer"
      },
      "email": {
        "type": "keyword"
      },
      "name": {
        "type": "text"
      }
    }
  }
}
代码语言:javascript
复制
{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "my_index"
}

查看映射

GET /my_index/_mapping

代码语言:javascript
复制
{
  "my_index" : {
    "mappings" : {
      "properties" : {
        "age" : {
          "type" : "integer"
        },
        "email" : {
          "type" : "keyword"
        },
        "name" : {
          "type" : "text"
        }
      }
    }
  }
}

添加新的字段映射

代码语言:javascript
复制
PUT /my_index/_mapping
{
  "properties": {
    "employee-id": {
      "type": "keyword",
      "index": false
    }
  }
}

这里的 "index": false,表明新增的字段不能被检索,只是一个冗余字段。

更新映射

对于已经存在的字段映射,我们不能更新。更新必须创建新的索引,进行数据迁移。

数据迁移

例如我们想把索引 bank 中的 age 修改为 integer

就需要创建一个新的索引,指定号映射类型

代码语言:javascript
复制
PUT /newbank
{
  "mappings": {
    "properties": {
      "account_number": {
        "type": "long"
      },
      "address": {
        "type": "text"
      },
      "age": {
        "type": "integer"
      },
      "balance": {
        "type": "long"
      },
      "city": {
        "type": "keyword"
      },
      "email": {
        "type": "keyword"
      },
      "employer": {
        "type": "keyword"
      },
      "firstname": {
        "type": "text"
      },
      "gender": {
        "type": "keyword"
      },
      "lastname": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      },
      "state": {
        "type": "keyword"
      }
    }
  }
}

由于我们的数据是在 /bank/account 下,所有需要添加 "type": "account"

代码语言:javascript
复制
POST _reindex
{
  "source": {
    "index": "bank",
    "type": "account"
  },
  "dest": {
    "index": "newbank"
  }
}

查看新的索引信息

GET /newbank/_search


版权属于:乐心湖's Blog

本文链接:https://cloud.tencent.com/developer/article/1774967

声明:博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 初级检索
    • _cat
      • 索引文档(CRUD)
        • 保存文档
        • 查询文档
        • 更新文档
        • 删除文档
      • 批量保存
      • 高级检索
        • SearchAPi
          • Query DSL
            • 基本语法格式
            • 返回部分字段
            • match匹配查询
            • match_phrase短句匹配
            • multi_math多字段匹配
            • bool用来做复合查询
            • Filter结果过滤
            • term
            • Aggregation(聚合)
          • Mapping
            • 数据迁移
            相关产品与服务
            Elasticsearch Service
            腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档