什么是Elastic Search?
它是一个开源的分布式搜索和分析引擎,用于处理海量数据。它支持近实时的全文搜索,结构化查询,数据分析等场景。它基于apache lucene构建,提供了简单易用的resful API。
架构
+-----------------+
| Client Apps |
+--------+--------+
|
+---------------v------------------+
| Coordinating Nodes (无数据) |
+---------------+------------------+
|
+---------------v------------------+
| Data Nodes (分片存储 + 计算) |
| * Shard 1 Primary |
| * Shard 1 Replica |
+---------------+------------------+
|
+---------------v------------------+
| Dedicated Master Nodes (3节点) |
| * 管理集群元数据 |
+---------------------------------+
应用场景
日志分析
监控系统/安全审计
电商搜索
实时数据分析
日志分析: 能够对海量日志进行索引和搜索,可以使用复杂的查询语句帮助运维人员快速查找和定位问题。
监控系统/安全审计: 高效储存和查询数据,支持按时间/指标类型等条件进行查询,从而快速定位性能问题/安全事件。
电商搜索: 通过强大的全文搜索能力,支持分词、模糊查询、同义词查询、多语言搜索等功能,解决传统数据库无法进行全文搜索的痛点,结合其他条件查询,提供更准确、更高效的搜索结果。同时支持高扩展性,可以轻松扩展到多个节点,处理海量数据,满足高并发的搜索请求。
实时数据分析: 能够实时处理和索引新数据,支持毫秒级的查询响应,确保用户能够获取最新的数据。
核心概念
索引相关
es中索引就是indices,相当于表或者说document
查看所有索引
GET /_cat/indices?v=true&pretty
查看特定索引:
GET /<index_name>?v=true&pretty
查看索引是否存在
HEAD /xdclass_shop
创建索引
PUT /<index_name>
{
"settings": {
"number_of_replicas": 0,
"number_of_shards": 2
}
}
修改索引设置
PUT /xdclass_shop/_settings
{
"number_of_replicas": 1
}
文档相关
文档就是索引里的一条条记录了,相当于entry
通过文档id查询文档: GET /<index_name>/_doc/<doc_id>
新增doc(指定id)
PUT /<index_name>/_doc/<doc_id>
{
"key":"value"
}
新增doc(不指定id)
POST /<index_name>/_doc/ #无id
{
"key":"value"
}
批量导入
POST /<index_name>/_bulk
{ "index": { "_index": "<index_name>" } }
{"key":"value"}
# json不能换行,每一个json对象必须在新的一行。最后一个json对象结束后必须换行
修改doc
POST /<index_name>/_doc/<doc_id>
{
"key":"value/new_value",
"new_key":"new_value"
}
PUT /<index_name>/_doc/<doc_id>
{
"key":"value/new_value",
"new_key":"new_value"
}
搜索所有文档
GET /<indice_name>/_search
按条件搜索文档
具体看query DSL
GET /<index_name>/_search
{
"query": {
"<condition, like match>": {
"key": "value"
}
}
}
删除文档
DELETE /<indice_name>/_doc/<doc_id>
数据类型
查看索引库字段类型
GET /<index_name>/_mapping
创建指定字段类型的索引库
// 没有index
PUT /<index_name>
{
"mappings": {
"properties": {
"<key>": {
"type":"<data_type:>"
}
}
}
}
//修改现有index
PUT /<index_name>/_mapping
{
"properties": {
"<key>": {
"type":"<data_type>"
}
}
}
倒排索引相关
倒排索引(Inverted Index)是一种数据库索引结构,它将文档中的内容映射到包含这些内容的文档。与传统的"正排索引"(文档→内容)相反,倒排索引是"内容→文档"的映射关系。它可以快速检索内容是否属于某个文档,所以需要分词器。
查看分词器分词效果
GET _analyze
{
"analyzer":"<tokenizer_name>",
"text":"<content>"
}
查看某个索引的分词器
POST /<index_name>/_analyze
{
"field":"<field_name>",
"text":"<content>"
}
Query DSL
Elasticsearch 的查询语法主要基于 JSON DSL(Domain-Specific Language),支持丰富的查询类型和聚合操作。
基础语法
所有查询都包裹在 query 或 aggs(聚合)中,基本格式如下:
GET /<index_name>/_search
{
"_source":[<field_name>] # 可选参数,用于指定需要返回的field,
"query": { // 查询条件
"<condition, like match>": {
"key": "value"
},
"aggs": { ... }, // 聚合分析
"sort": [ ... ], // 排序
"from": 0, // 分页起始位置
"size": 10 // 返回条数
}
}
全文搜索查询
match 分词搜索
全文搜索,会讲查询条件分词并且与指定字段中的⽂本进⾏匹配。默认词与词是or的关系
{
"query": {
"match": {
"field_name": "搜索词" // 自动分词后匹配
}
}
}
//示例
{ "match": { "title": "苹果手机" } }
match_phrase - 短语匹配(需完整顺序)
match_phrase查询分析文本并根据分析的文本创建一个短语查询。这里的短语是指一个完整的token。match_phrase 会将检索关键词分词。match_phrase的分词结果必须在被检索字段的分词中都包含,而且顺序必须相同,而且默认必须都是连续的。
{
"match_phrase": {
"field_name": "完整短语"
}
}
multi_match - 多字段匹配
{
"multi_match": {
"query": "关键词",
"fields": ["title", "description"] // 指定多个字段
}
}
match_all
查询所有文档。此时查询条件为{}。 即不传key value
{
"match_all": {
"query": {},
}
}
精确查询
term
用于精确匹配指定字段关键词,不进行分词
{
"term": {
"status": { // 字段名
"value": "published" // 精确值
}
}
}
terms - 多值匹配
{
"terms": {
"tags": ["科技", "手机"] // 匹配字段包含任意一个值
}
}
range - 范围查询
{
"range": {
"price": {
"gte": 1000, // 大于等于
"lte": 5000 // 小于等于
}
}
}
复合查询
bool - 组合逻辑查询
{
"query": {
"bool": {
"must": [ ... ], // AND 条件
"must_not": [ ... ], // NOT 条件
"should": [ ... ], // OR 条件
"filter": [ ... ] // 过滤(不计算评分)
}
}
}
// 示例:搜索价格在 1000-5000 元且包含“手机”的商品:
{
"bool": {
"must": [
{ "match": { "title": "手机" } } //title中必须包含关键词手机
],
"filter": [
{ "range": { "price": { "gte": 1000, "lte": 5000 } } } //价格是大于等于1000, 小于等于5000
]
}
}
must:必须匹配,贡献算分;
must_not:必须不匹配,不贡献算分;
should:如果满足这些语句中任意语句,将增加_score,否则无任何影响,它们主要用于修正每个文档的相关性得分;
filter:必须匹配,但它不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。
constant_score - 固定评分查询
Constant Score 查询是 Elasticsearch 中的一种查询方式,它可以将查询结果的评分设定为一个常量值,从而忽略相关性评分的计算。这种方式在需要执行过滤操作但不需要评分的场景中非常有用。
constant_score:本意(常量分数),可以将一个不变的常量应用到所有匹配的文档中。它常用于只需要执行一个filter而没有其他查询(例如评分查询)的情况下。term查询被放置在constant_score中,转换成不评分的filter。这种方式可以用来只有filter的bool查询中。
{
"constant_score": {
"filter": { ... }, // 过滤条件
"boost": 1.2 // 固定评分值
}
}
聚合查询(Aggregations)
指标聚合(Metrics)
{
"aggs": {
"avg_price": { "avg": { "field": "price" } }, // 计算均价
"max_price": { "max": { "field": "price" } } // 最高价
}
}
桶聚合(Buckets)
{
"aggs": {
"group_by_brand": {
"terms": { "field": "brand" } // 按品牌分组
}
}
}
嵌套聚合
{
"aggs": {
"group_by_brand": {
"terms": { "field": "brand" },
"aggs": {
"avg_price": { "avg": { "field": "price" } } // 每组计算均价
}
}
}
}
排序与分页
排序
{
"sort": [
{ "price": { "order": "desc" } }, // 按价格降序
"_score" // 再按相关性评分排序
]
}
分页
{
"from": 10, // 跳过前10条
"size": 5 // 返回5条
}
高亮显示
高亮显示(Highlighting)是一种功能,它用于在搜索结果中突出显示与用户查询匹配的文本片段。高亮显示可以帮助用户快速定位到搜索结果中与查询相关的部分,提升用户体验。例如,当用户搜索“苹果”时,高亮显示可以将文档中所有“苹果”这个词标红或加粗,让用户一眼就能看到匹配的内容。
{
"query": { ... },
"highlight": {
"fields": {
"title": {} // 高亮title字段匹配内容
}
}
}
//示例
GET /your_index/_search
{
"query": {
"match": {
"content": "苹果"
}
},
"highlight": {
"fields": {
"content": {}
}
}
}
//返回结果
//content字段中匹配的词会被加<em>标签
{
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "your_index",
"_type": "_doc",
"_id": "1",
"_score": 1.0,
"_source": {
"content": "这是一个关于苹果的文档。"
},
"highlight": {
"content": [
"这是一个关于<em>苹果</em>的文档。"
]
}
}
]
}
}
查询模板(Query Template)
使用 mustache 语法动态传参:
{
"query": {
"match": {
"{{field}}": "{{value}}" // 运行时替换变量
}
}
}
SQL 查询(需X-Pack插件)
GET /_sql?format=json
{
"query": "SELECT * FROM products WHERE price > 1000 LIMIT 10"
}
性能优化技巧
避免通配符查询:如 wildcard 性能较差。
使用 filter 替代 must:过滤条件不计算评分,可缓存。
限制返回字段:通过 _source: ["field1", "field2"] 减少数据传输。
完整示例
GET /products/_search
{
"query": {
"bool": {
"must": [
{ "match": { "title": "手机" } }
],
"filter": [
{ "range": { "price": { "gte": 1000 } } }
]
}
},
"aggs": {
"brand_stats": {
"terms": { "field": "brand" },
"aggs": {
"avg_price": { "avg": { "field": "price" } }
}
}
},
"highlight": {
"fields": { "title": {} }
},
"from": 0,
"size": 10
}