使用ElasticSearch的各种姿势(#^.^#)

ElasticSearch

索引库

1. mapping 介绍

1.1 数据类型 (Data Types)

  • text: 用于全文搜索的文本字段,会被分词。
  • keyword: 用于不需要分词的关键字字段,比如标签、关键词等。
  • date: 日期类型字段。
  • object: 对象类型字段,可以包含其他字段。

1.2 分词器 (Analyzers)

  • analyzer: 指定字段的分词器,用于将文本分割成词项。
  • search_analyzer: 指定搜索时使用的分词器,可以与 analyzer 不同,用于搜索时的分词处理。

1.3 索引选项 (Index Options)

  • index: 控制字段是否被索引,可以设置为 "true" 或 "false"。

1.4 存储属性 (Store)

  • store : 控制是否将字段的原始值存储在 _source 字段中。

  • 存储属性控制是否将字段的原始值存储在 _source 字段中。默认情况下,Elasticsearch 会将文档的原始 JSON 内容存储在 _source 字段中,但有时候我们可能不需要存储所有字段的原始值,特别是对于大量文本内容的字段,可以选择不存储原始值以节省存储空间。

    示例 : 假设我们有一个文档包含一个名为 "content" 的字段,我们希望对这个字段进行全文搜索,但不需要在搜索结果中返回原始的 "content" 值。我们可以将 "content" 字段的存储属性设置为 false,这样原始的 "content" 值就不会被存储在 _source 字段中。

    json 复制代码
    {
      "mappings": {
        "properties": {
          "content": {
            "type": "text",
            "store": false
          }
        }
      }
    }

1.5 多字段 (Multi-fields)

  • fields: 允许为同一字段定义多个不同的属性,比如使用不同的分词器或数据类型。

1.6 动态映射 (Dynamic Mapping)

  • dynamic : 控制字段的动态映射行为,包括 "true"、"false" 和 "strict"。
    • dynamic: true:

      当设置为 true 时,Elasticsearch 将尝试自动检测文档中的新字段,并动态地将其添加到映射中。这意味着当索引新文档时,Elasticsearch 会自动创建新字段的映射。

      示例:假设我们有一个索引,并且在索引文档时出现了之前未见过的字段,比如 "author",Elasticsearch 将自动创建 "author" 字段的映射。

    • dynamic: false:

      当设置为 false 时,Elasticsearch 不会自动检测文档中的新字段,新字段将被忽略,不会被添加到映射中。

      示例:如果我们将动态映射设置为 false,那么当索引新文档时,如果文档中包含之前未见过的字段,比如 "author",Elasticsearch 将不会创建 "author" 字段的映射。

    • dynamic: strict:

      当设置为 strict 时,如果文档包含之前未见过的字段,索引操作将会失败,Elasticsearch 会拒绝索引包含未知字段的文档。

      示例:如果我们将动态映射设置为 strict,那么当索引新文档时,如果文档中包含之前未见过的字段,比如 "author",索引操作将会失败。

json 复制代码
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "standard",
        "fields": {
          "keyword": {
            "type": "keyword"
          }
        },
        "store": true
      },
      "content": {
        "type": "text",
        "analyzer": "english",
        "index": false
      },
      "publish_date": {
        "type": "date"
      },
      "author": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword"
          }
        },
        "store": false
      }
    },
    "dynamic": "strict"
  }
}

2. 索引库操作

2.1 创建

json 复制代码
PUT /索引库名称
{
  "mappings": {
    "properties": {
      "字段名":{
        "type": "text",
        "analyzer": "ik_smart"
      },
      "字段名2":{
        "type": "keyword",
        "index": "false"
      },
      "字段名3":{
        "properties": {
          "子字段": {
            "type": "keyword"
          }
        }
      },
      // ...略
    }
  }
}

2.2 删除

DELETE /索引库名

2.3 修改

索引库和mapping一旦创建无法修改,但是可以添加新的字段,

json 复制代码
PUT /索引库名/_mapping
{
  "properties": {
    "新字段名":{
      "type": "integer"
    }
  }
}

3. 文档操作

3.1 新增

json 复制代码
POST /索引库名/_doc/文档id
{
    "字段1": "值1",
    "字段2": "值2",
    "字段3": {
        "子属性1": "值3",
        "子属性2": "值4"
    },
    // ...
}

3.2 删除

DELETE /索引库名/_doc/文档id

3.3 修改

3.3.1 全量修改

json 复制代码
PUT /索引库名/_doc/文档id
{
    "字段1": "值1",
    "字段2": "值2",
    // ... 略
}

3.3.2 增量修改

json 复制代码
POST /索引库名/_update/文档id
{
    "doc": {
         "字段名": "新的值",
    }
}

4. 文档查询

前缀 : GET /索引库/_search

  • 查询所有:查询出所有数据,一般测试用。例如:match_all

  • 全文检索(full text)查询:利用分词器对用户输入内容分词,然后去倒排索引库中匹配。例如:

    • match_query

    • multi_match_query

    • ...

  • 精确查询:根据精确词条值查找数据,一般是查找keyword、数值、日期、boolean等类型字段。例如:

    • ids

    • range

    • term

    • ...

  • 地理(geo)查询:根据经纬度查询。例如:

    • geo_distance

    • geo_bounding_box

    • ...

  • 复合(compound)查询:复合查询可以将上述各种查询条件组合起来,合并查询条件。例如:

    • bool
    • function_score
    • ...

全文检索

4.1 match_all

查询所有

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

4.2 match

执行全文搜索,匹配查询中的一个或多个词项

json 复制代码
{
  "query": {
    "match": {
      "title": "Elasticsearch"
    }
  }
}

4.3 multi_match

允许同时查询多个字段

json 复制代码
{
  "query": {
    "multi_match": {
      "query": "Elasticsearch",
      "fields": ["title", "content"]
    }
  }
}
// fields 中填写多个字段

4.4 match_phrase

Match Phrase查询用于匹配包含指定短语的文档,而不是单个词项的匹配

查询会对查询字符串进行分词,然后尝试匹配包含整个短语的文档。它会将查询字符串视为一个短语,并尝试在文档中找到包含该短语的内容,而不是简单地匹配单个词项。

json 复制代码
{
  "query": {
    "match_phrase": {
      "content": "data analysis"
    }
  }
}

4.5 query_string

Query String查询允许使用查询字符串进行全文搜索,支持通配符、布尔操作符等高级搜索语法

查询会根据查询字符串中的语法进行分词和处理。它支持使用通配符、布尔操作符等高级搜索语法,但不会对查询字符串进行分词。这意味着查询字符串中的术语将按照输入的方式进行匹配,而不会被分词处理。

json 复制代码
{
  "query": {
    "query_string": {
      "query": "Elasticsearch AND (data OR analysis)"
    }
  }
}

精确匹配

4.5 ids

Ids查询用于精确匹配指定文档ID的文档。它允许在给定的类型中查找与提供的ID列表匹配的文档。

json 复制代码
{
  "query": {
    "ids": {
      "values": ["1", "2", "3"]
    }
  }
}

4.6 exists

Exists查询用于匹配包含指定字段的文档。它可以用于查找包含某个字段的文档,而不考虑字段的实际值。

json 复制代码
{
  "query": {
    "exists": {
      "field": "price"
    }
  }
}

4.7 prefix

Prefix查询用于匹配指定字段以指定前缀开头的文档。它可以用于查找以指定前缀开头的词项或短语。

json 复制代码
{
  "query": {
    "prefix": {
      "user": "ki"
    }
  }
}

4.8 wildcard

Wildcard查询用于匹配指定字段符合通配符模式的文档。它支持通配符(*和?)来进行模糊匹配。

Wildcard查询用于匹配指定字段符合通配符模式的文档。通配符*代表零个或多个字符,?代表一个字符。

json 复制代码
{
  "query": {
    "wildcard": {
      "user": "ki*"
    }
  }
}

4.9 regexp

Regexp查询用于匹配指定字段符合正则表达式模式的文档。它支持使用正则表达式来进行匹配。

json 复制代码
{
  "query": {
    "regexp": {
      "user": "k.*y"
    }
  }
}

4.10 range

Range查询用于匹配指定范围内的值。它可以用于数值型字段或日期型字段,以精确匹配指定范围内的值。

json 复制代码
{
  "query": {
    "range": {
      "price": {
        "gte": 20,
        "lte": 100
      }
    }
  }
}
// gte       >=
// gt         >

4.11 term

Term查询用于精确匹配指定字段中包含指定词项的文档。它不会对查询词项进行分词处理,而是直接进行精确匹配。

json 复制代码
{
  "query": {
    "term": {
      "status.keyword": "published"
    }
  }
}

4.12 terms

Terms查询用于匹配字段中包含指定词项列表中任意一个词项的文档。类似于SQL中的IN操作符。

json 复制代码
{
  "query": {
    "terms": {
      "tags.keyword": ["elasticsearch", "search", "database"]
    }
  }
}

地理查询

"lat"代表纬度(latitude),"lon"代表经度(longitude)

4.13 geo_distance

地理距离查询用于查找与指定地理位置距离在一定范围内的文档。这种查询通常用于查找附近的地点或者地理位置相关的数据。

json 复制代码
// 假设我们要查找距离某个特定地理坐标(例如纬度40.7128,经度-74.0060)50公里范围内的所有文档:
{
  "query": {
    "geo_distance": {
      "distance": "50km",
      "location": {
        "lat": 40.7128,
        "lon": -74.0060
      }
    }
  }
}

4.14 geo_bounding_box

地理边界框查询用于查找落在指定矩形区域内的地理位置点。这种查询对于在地图上指定一个矩形区域并查找其中的地点非常有用。

json 复制代码
// 假设我们要查找落在一个矩形区域内的所有文档,该矩形区域由左下角坐标(40.7128,-74.0060)和右上角坐标(40.748817,-73.985428)定义:
{
  "query": {
    "geo_distance": {
      "distance": "50km",
      "location": {
        "lat": 40.7128,
        "lon": -74.0060
      }
    }
  }
}

4.15 geo_bounding_box

地理多边形查询用于查找落在指定多边形区域内的地理位置点。这种查询对于在地图上指定一个多边形区域并查找其中的地点非常有用。

json 复制代码
// 假设我们要查找落在一个多边形区域内的所有文档,该多边形由一系列顶点坐标定义:
{
  "query": {
    "geo_polygon": {
      "location": {
        "points": [
          {"lat": 40.7128, "lon": -74.0060},
          {"lat": 40.735657, "lon": -73.991046},
          {"lat": 40.748817, "lon": -73.985428}
        ]
      }
    }
  }
}

复合查询

TF-IDF(词项频率-逆文档频率)

TF-IDF是一种用于信息检索和文本挖掘的常见算法。它基于两个核心概念:

  • 词项频率(Term Frequency,TF):衡量一个词在文档中出现的频率。通常情况下,出现次数越多,词项频率越高。
  • 逆文档频率(Inverse Document Frequency,IDF):衡量一个词对于整个文档集合的重要性。如果一个词在很多文档中出现,它的逆文档频率会降低。

TF-IDF算法将这两个概念结合起来,通过词项频率和逆文档频率来计算文档中每个词的权重,从而确定文档与查询的相关性。

BM25(Best Matching 25)

BM25是一种改进的信息检索算法,它在TF-IDF的基础上引入了文档长度的考量,并对词项频率进行了调整。BM25算法考虑了查询词在文档中的频率、文档长度以及查询词的逆文档频率,从而更准确地评估文档与查询的匹配程度。

Elasticsearch使用TF-IDF和BM25的结合来计算文档的相关性得分。这些算法考虑了词项频率、逆文档频率、文档长度等因素,以确定文档与查询的匹配程度,并根据匹配程度为文档赋予相关性得分。

这些相关性算法的目标是确保搜索结果能够按照与查询的匹配程度排序,从而提供最相关的文档作为搜索结果。如果您对相关性算法或Elasticsearch中的其他搜索相关主题有更多疑问,欢迎随时向我提问。

4.16 Bool Query(布尔查询)

Bool查询允许您组合多个查询条件,包括must(必须匹配)、should(应该匹配)、must_not(必须不匹配)和filter(过滤)

示例: 假设我们要查找标题中包含"Elasticsearch"关键词,并且内容中包含"复合查询"或者"复合条件"的文档:

json 复制代码
{
  "query": {
    "bool": {
      "must": [
        { "match": { "title": "Elasticsearch" } }
      ],
      "should": [
        { "match": { "content": "复合查询" } },
        { "match": { "content": "复合条件" } }
      ]
    }
  }
}

4.17 Function Score Query

  1. query
    • 这是Function Score Query中的主查询部分,用于指定要进行相关性评分的原始查询。可以是任何类型的查询,例如match、term、bool等。
  2. functions
    • 这是一个数组,包含一个或多个自定义函数,用于修改文档的相关性得分。每个函数都可以基于不同的条件来修改得分。
  3. score_mode
    • 用于指定如何组合原始查询得分和自定义函数得分。常见的取值包括:
      • "multiply":将原始查询得分与自定义函数得分相乘。
      • "sum":将原始查询得分与自定义函数得分相加。
      • "avg":将原始查询得分与自定义函数得分求平均。
  4. boost_mode
    • 用于指定如何将原始查询得分和自定义函数得分相结合以生成最终的文档得分。常见的取值包括:
      • "multiply":将原始查询得分和自定义函数得分相乘。
      • "sum":将原始查询得分和自定义函数得分相加。
      • "replace":用自定义函数得分替换原始查询得分。
  5. min_score
    • 可选属性,用于指定最低得分阈值。只有得分高于此阈值的文档才会被返回。
  6. boost
    • 可选属性,用于为整个Function Score Query设置一个静态的boost值,以增加或减少所有文档的得分。

4.18 Constant Score Query(常量分数查询)

Constant Score查询允许您对一个查询条件赋予一个常量分数,以便在查询时不考虑相关性得分。

示例: 假设我们要对所有包含"Elasticsearch"关键词的文档赋予一个常量分数2.0:

json 复制代码
{
  "query": {
    "constant_score": {
      "filter": {
        "term": { "content": "Elasticsearch" }
      },
      "boost": 2.0
    }
  }
}

4.19Dis Max Query(离散最大化查询)

Dis Max查询用于在多个查询条件中返回与任一条件匹配的文档,并将相关性得分最高的条件作为整体查询的得分。

示例: 假设我们要查找标题或内容中包含"Elasticsearch"或者"Kibana"的文档,并返回相关性得分最高的条件:

json 复制代码
{
  "query": {
    "dis_max": {
      "queries": [
        { "match": { "title": "Elasticsearch" } },
        { "match": { "content": "Elasticsearch" } }
      ]
    },
    "tie_breaker": 0.7
  }
}

参考文档

在Elasticsearch中,离散最大化查询(Dis Max Query)中的tie_breaker参数是用来调整多个匹配子查询的得分影响的参数。当一个文档匹配多个子查询时,每个子查询都会产生一个得分,最终的得分会受到tie_breaker参数的影响。

具体来说,tie_breaker参数的取值范围是0到1之间的浮点数。当tie_breaker设置为0时,只有最高得分的子查询的得分会被考虑 ,其他子查询的得分不会影响最终的得分。当tie_breaker设置为1时,所有子查询的得分都会被考虑,最终得分是所有子查询得分的加和

通常情况下,tie_breaker的取值会介于0和1之间,这样可以让其他子查询的得分对最终得分产生一定的影响,但不会完全取代最高得分的影响。

举个例子,如果tie_breaker设置为0.7,那么即使有其他子查询的得分较低,它们仍然会对最终得分产生一定的影响,但最高得分的子查询的影响会更大。

4.20 排序(Sorting)

在Elasticsearch中,排序可以基于文档中的一个或多个字段进行。除了基本的按字段值排序外,Elasticsearch还支持地理位置的排序。这对于需要根据地理位置信息(如经纬度)来排序搜索结果的场景非常有用。以下是一个示例:

json 复制代码
{
  "query": {
    "match_all": {}
  },
  "sort": [
    { "price": "asc" },
    {
      "_geo_distance": {
        "location": {
          "lat": 40,
          "lon": -70
        },
        "order": "asc",
        "unit": "km"
      }
    }
  ]
}

在这个示例中,搜索结果首先按照价格升序排序,然后按照与给定地理位置(纬度 40,经度 -70)的距离升序排序。

以下再做一个举例( 可以根据以下延伸出很多排序 ):

json 复制代码
{
  "query": {
    "bool": {
      "filter": {
        "geo_bounding_box": {
          "location": {
            "top_left": {
              "lat": 40.73,
              "lon": -74.1
            },
            "bottom_right": {
              "lat": 40.01,
              "lon": -71.12
            }
          }
        }
      }
    }
  },
  "sort": [
    {
      "_geo_distance": {
        "location": {
          "lat": 40.715, 
          "lon": -74.011
        },
        "order": "asc",
        "unit": "km",
        "mode": "min",
        "distance_type": "arc"
      }
    },
    {
      "price": {
        "order": "asc"
      }
    }
  ]
}

4.21 分页(Pagination)

分页操作允许您从搜索结果中获取特定范围内的文档。除了常规的 from 和 size 参数外,Elasticsearch还提供了 search_after 参数,它允许您在分页时使用上一页的最后一个文档作为游标来获取下一页的结果。以下是一个示例:

json 复制代码
{
  "query": {
    "match_all": {}
  },
  "from": 10,
  "size": 10
}

4.22 高亮(Highlighting)

默认 match 字段和 fields是对应的,如果你的 description 是一个新字段,比如多个字段 copyto 到一个字段,这时候需要取消强绑定。

高亮可以帮助用户快速识别搜索关键词在文档中的位置。除了基本的高亮操作外,Elasticsearch还支持自定义高亮标签、多字段高亮等功能。以下是一个示例:

json 复制代码
{
  "query": {
    "match": {
      "description": "智能手机"
    },
    "highlight": {
      "fields": {
        "description": {
          "pre_tags": ["<em>"],
          "post_tags": ["</em>"]
        }
      }
    }
  }
}

4.23 聚合(Aggregations)

桶聚合

项(Terms)聚合举例:
  • 项(Terms)聚合:假设您有一个包含产品类别的字段,您可以使用项聚合按照产品类别对销售数据进行分组,以便了解每个产品类别的销售数量或平均销售额。

    假设我们有一个包含销售数据的索引,每个文档代表一次销售记录,包括产品类别、销售金额和销售日期等字段。我们可以使用项(Terms)聚合来按照产品类别对销售数据进行分组,并计算每个产品类别的销售总额。

    json 复制代码

{ "aggs": { "sales_by_category": { "terms": { "field": "product_category.keyword" }, "aggs": { "total_sales": { "sum": { "field": "sales_amount" } } } } } }

sql 复制代码
在这个例子中,我们使用项聚合按照产品类别对销售数据进行分组,并在每个分组内使用求和指标聚合来计算销售总额。

##### 范围(Range)聚合举例:

- 范围(Range)聚合:假设您有一个包含销售数据的索引,您可以使用范围聚合来按照销售额的不同范围进行分组,以便了解不同销售额范围内的订单数量或利润总额。

假设我们有一个包含用户年龄的索引,每个文档代表一个用户的个人信息,包括姓名、年龄等字段。我们可以使用范围(Range)聚合来按照不同年龄段对用户进行分组,并计算每个年龄段内的用户数量。

{ "aggs": { "age_ranges": { "range": { "field": "age", "ranges": [ { "to": 18 }, { "from": 19, "to": 30 }, { "from": 31, "to": 40 }, { "from": 41 } ] } } } }

sql 复制代码
在这个例子中,我们使用范围聚合按照不同年龄段对用户进行分组,并计算每个年龄段内的用户数量。

##### 日期直方图(Date Histogram)聚合

- 日期直方图(Date Histogram)聚合:如果您的数据包含时间戳,您可以使用日期直方图聚合按照不同的时间间隔(如每天、每周、每月)对销售数据进行分组,以便了解销售趋势随时间的变化。

假设我们有一个包含用户登录记录的索引,每个文档代表一个用户的登录信息,包括用户ID、登录时间等字段。我们可以使用日期直方图(Date Histogram)聚合来按照每天的时间间隔对用户登录记录进行分组,并计算每天的登录次数。

```json
{
  "aggs": {
    "logins_per_day": {
      "date_histogram": {
        "field": "login_time",
        "calendar_interval": "1d"
      }
    }
  }
}

在这个例子中,我们使用日期直方图聚合按照每天的时间间隔对用户登录记录进行分组,并计算每天的登录次数。

度量聚合

聚合允许您对搜索结果进行统计分析,比如计算平均值、求和、最大/最小值、统计(Stats)聚合等。您可以根据不同的条件对搜索结果进行分组,并对每个分组进行聚合操作。以下是一个示例,假设我们有一个文档类型为 "sales",包含了销售数据,我们可以对销售额进行聚合:

json 复制代码
{
  "aggs": {
    "total_sales": {
      "sum": {
        "field": "amount"
      }
    }
  }
}

在这个示例中,我们对 "amount" 字段进行了求和操作,得到了销售额的总和。

管道聚合

  • 桶脚本(Bucket Script)聚合:对其他聚合结果进行数学运算,例如求和、平均值等。
  • 桶选择器(Bucket Selector)聚合:根据条件过滤桶中的文档。
  • 衍生指标(Derivative)聚合:计算时间序列数据的导数。

4.24 过滤(Filtering)

除了查询条件外,您还可以使用过滤器来进一步限制搜索结果 。过滤器可以用于排除特定条件下的文档,比如范围过滤、布尔过滤、嵌套文档过滤等。以下是一个示例,假设我们要过滤出销售额大于1000的文档:

json 复制代码
{
  "query": {
    "match_all": {}
  },
  "filter": {
    "range": {
      "amount": {
        "gt": 1000
      }
    }
  }
}

4.25 深度分页(Deep Pagination)

对于大型数据集,传统的分页方式可能会导致性能下降。Elasticsearch提供了基于游标的深度分页功能,允许您有效地处理大量数据的分页操作。以下是一个示例,使用 search_after 参数进行深度分页:

json 复制代码
{
  "query": {
    "match_all": {}
  },
  "size": 10,
  "search_after": [last_sort_value]
}

在这个示例中,last_sort_value 是上一页结果中最后一个文档的排序值,用于获取下一页的结果。

4.26 搜索建议(Search Suggest)

Elasticsearch支持搜索建议功能,可以根据用户的输入提供自动补全和相关搜索建议,从而改善搜索体验。以下是一个示例,使用搜索建议功能来提供自动补全:

json 复制代码
{
  "suggest": {
    "text": "es",
    "my-suggestion": {
      "term": {
        "field": "title"
      }
    }
  }
}

在这个示例中,当用户输入 "es" 时,系统将提供与标题字段匹配的自动补全建议。

后续还会补充....

如果文章有错误希望大家指出(^▽^)

大家觉得更新太慢可以查看官网学习

相关推荐
sg_knight11 小时前
Spring Cloud与RabbitMQ深度集成:从入门到生产级实战
java·spring boot·spring·spring cloud·消息队列·rabbitmq·stream
INFINI Labs11 小时前
Elasticsearch 备份:方案篇
大数据·elasticsearch·搜索引擎·gateway·snapshot·backup·ccr
NickBi13 小时前
龙芯 LoongArch64编译es7.17.20
后端·elasticsearch
安逸sgr14 小时前
SpringMVC启动流程
java·jvm·spring·spring cloud·eclipse·tomcat·maven
Vio72514 小时前
Ribbon负载均衡
spring cloud·ribbon·负载均衡
会飞的小蛮猪19 小时前
Prometheus运维之路(ES监控接入)
elasticsearch·监控·自动化运维
贝多芬也爱敲代码1 天前
如何减小ES和mysql的同步时间差
大数据·mysql·elasticsearch
深思慎考1 天前
ElasticSearch与Kibana 入门指南(7.x版本)
大数据·elasticsearch·jenkins
problc2 天前
PostgreSQL + Redis + Elasticsearch 实时同步方案实践:从触发器到高性能搜索
redis·elasticsearch·postgresql