Elasticsearch 是一个基于Apache Lucene的开源分布式搜索和分析引擎,广泛应用于全文搜索、结构化搜索、分析等多种场景。
Easysearch 作为Elasticsearch 的国产化替代方案,不仅保持了与原生Elasticsearch 的高度兼容性,还在功能、性能、稳定性和扩展性方面进行了全面提升。以下是Easysearch的基本知识和语法:
基本概念
- 节点(Node):Elasticsearch集群中的单个服务器。
- 集群(Cluster):由一个或多个节点组成,拥有唯一的集群名。
- 索引(Index):类似于关系数据库中的数据库,一个索引包含了一系列的文档。
- 类型(Type):索引中的一个逻辑分类,在Elasticsearch 6.x以后已被弃用。
- 文档(Document):索引中的基本数据单位,类似于关系数据库中的行。
- 字段(Field):文档中的一个属性,类似于关系数据库中的列。
- 分片(Shard):索引可以被分成多个分片来分布存储。
- 副本(Replica):分片的副本,用于高可用性和故障恢复。
查看集群信息
在Elasticsearch中,可以通过多个API来查看集群的各种信息,包括集群的健康状况、节点信息和索引状态。以下是一些常用的查看集群信息的API和示例:
查看集群健康状况
_cluster/health
API可以查看集群的健康状态,包括集群是否处于正常状态、节点数量、分片状态等。
GET /_cluster/health
示例响应:
{"cluster_name": "my_cluster","status": "green","timed_out": false,"number_of_nodes": 3,"number_of_data_nodes": 3,"active_primary_shards": 5,"active_shards": 10,"relocating_shards": 0,"initializing_shards": 0,"unassigned_shards": 0,"delayed_unassigned_shards": 0,"number_of_pending_tasks": 0,"number_of_in_flight_fetch": 0,"task_max_waiting_in_queue_millis": 0,"active_shards_percent_as_number": 100.0
}
查看集群状态
_cluster/stats
API可以查看集群的详细状态,包括索引、节点、分片等信息。
GET /_cluster/stats
示例响应:
{"cluster_name": "my_cluster","status": "green","indices": {"count": 10,"shards": {"total": 20,"primaries": 10,"replication": 1.0,"index": {"shards": {"min": 1,"max": 5,"avg": 2.0}}}},"nodes": {"count": {"total": 3,"data": 3,"coordinating_only": 0,"master": 1,"ingest": 2},"os": {"available_processors": 12,"allocated_processors": 12},"process": {"cpu": {"percent": 10},"open_file_descriptors": {"min": 100,"max": 300,"avg": 200}}}
}
查看节点信息
_nodes
API可以查看集群中节点的详细信息,包括节点角色、IP地址、内存使用情况等。
GET /_nodes
示例响应:
{"cluster_name": "my_cluster","nodes": {"node_id_1": {"name": "node_1","transport_address": "192.168.1.1:9300","host": "192.168.1.1","ip": "192.168.1.1","roles": ["master", "data", "ingest"],"os": {"available_processors": 4,"allocated_processors": 4},"process": {"cpu": {"percent": 10},"open_file_descriptors": 200}},"node_id_2": {"name": "node_2","transport_address": "192.168.1.2:9300","host": "192.168.1.2","ip": "192.168.1.2","roles": ["data"],"os": {"available_processors": 4,"allocated_processors": 4},"process": {"cpu": {"percent": 15},"open_file_descriptors": 150}}}
}
查看索引状态
_cat/indices
API可以查看集群中所有索引的状态,包括文档数、存储大小、分片数等信息。
GET /_cat/indices?v
示例响应:
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open index_1 SxNUd84vRl6QH5P7g0T4Vg 1 1 0 0 230b 230b
green open index_2 NxEYib4yToCnA1PpQ8P4Xw 5 1 100 1 10mb 5mb
这些API可以帮助你全面了解Elasticsearch集群的状态和健康状况,从而更好地管理和维护集群。
增删改查
创建索引
PUT /my_index
{"settings": {"number_of_shards": 3,"number_of_replicas": 2}
}
删除索引
DELETE /my_index
添加文档
POST /my_index/_doc/1
{"name": "John Doe","age": 30,"occupation": "Engineer"
}
PUT /my_index/_doc/1
{"name": "John Doe","age": 30,"occupation": "Engineer"
}
新建文档
PUT /my_index/_create/1
{"a":1}
新建之后再执行报错:
{"error": {"root_cause": [{"type": "version_conflict_engine_exception","reason": "[23]: version conflict, document already exists (current version [1])","index_uuid": "1xWdHLTaTm6l6HbqACaIEA","shard": "0","index": "ss"}],"type": "version_conflict_engine_exception","reason": "[23]: version conflict, document already exists (current version [1])","index_uuid": "1xWdHLTaTm6l6HbqACaIEA","shard": "0","index": "ss"},"status": 409
}
获取文档
GET /my_index/_doc/1
更新文档
原来的字段会保留,更新age字段
POST /my_index/_update/1
{"doc": {"age": 31}
}
删除文档
DELETE /my_index/_doc/1
``#### 查询所有文档
```json
GET /my_index/_search
{"query": {"match_all": {}}
}
这个是《老杨玩搜索》里面的总结的图,可以当作“小抄”来记忆。
_bulk API用于在一次请求中执行多个索引、删除和更新操作。这对于批量处理大规模数据特别有用,可以显著提高性能和效率。以下是如何使用_bulk API的基本知识和示例:
POST /my_index/_bulk
{ "index": { "_id": "1" } }
{ "name": "John Doe", "age": 30, "occupation": "Engineer" }
{ "index": { "_id": "2" } }
{ "name": "Jane Doe", "age": 25, "occupation": "Designer" }
{ "update": { "_id": "1" } }
{ "doc": { "age": 31 } }
_bulk API的请求体由多个操作和文档组成。每个操作行包含一个动作描述行和一个可选的源文档行。动作描述行指明了操作的类型(例如,index、create、delete、update)以及操作的元数据。源文档行则包含了实际的数据。
每个操作之间需要用换行符分隔,并且请求体最后必须以换行符结尾。
POST _bulk
{ "index": {"_index":"a" ,"_id": "1" } }
{ "name": "John Doe", "age": 30, "occupation": "Engineer" }
{ "index": {"_index":"b" , "_id": "2" } }
{ "name": "Jane Doe", "age": 25, "occupation": "Designer" }
{ "update": {"_index":"a" , "_id": "1" } }
{ "doc": { "age": 31 } }
全文检索
分词器
在Easysearch中,分词器(Analyzer)用于将文本分解为词项(terms),是全文搜索和文本分析的基础。分词器通常由字符过滤器(Character Filters)、分词器(Tokenizer)和词项过滤器(Token Filters)组成。以下是关于ES分词器的详细介绍:
- 字符过滤器(Character Filters):在分词之前对文本进行预处理。例如,去除HTML标签,替换字符等。
- 分词器(Tokenizer):将文本分解为词项(tokens)。这是分词过程的核心。
- 词项过滤器(Token Filters):对词项进行处理,如小写化、去除停用词、词干提取等。
内置分词器
我们一起看下
POST /index/_mapping
{"properties": {"content": {"type": "text","analyzer": "ik_max_word","search_analyzer": "ik_smart"}}
}
-
POST /index/_mapping
- 这个部分表示要向名为
index
的索引添加或更新映射设置。
- 这个部分表示要向名为
-
“properties”:
properties
定义了索引中文档的字段结构。在这个例子中,定义了一个名为content
的字段。
-
“content”:
- 定义了名为
content
的字段。
- 定义了名为
-
“type”: “text”
type
字段指定content
字段的数据类型为text
。text
类型适用于需要分词和全文搜索的字段。
-
“analyzer”: “ik_max_word”
analyzer
字段指定索引时使用的分词器为ik_max_word
。ik_max_word
是IK分词器中的一种,它会尽可能多地将文本分解为更多的词项。
-
“search_analyzer”: “ik_smart”
search_analyzer
字段指定搜索时使用的分词器为ik_smart
。ik_smart
是IK分词器中的另一种,它会更智能地进行分词,以提高搜索的准确性。
当然,在设置这个mapping的时候可以使用同样的分词器,也可以使用不同的分词器。这里介绍下IK分词器:
- IK分词器是一种中文分词器,适用于中文文本的分词。IK分词器有两种分词模式:
ik_max_word
和ik_smart
。ik_max_word
:将文本尽可能多地切分成词项,适用于需要更高召回率的场景。ik_smart
:进行最智能的分词,适用于需要更高精度的搜索场景。
这个DSL的设置意味着,在向这个索引添加或更新文档时,content
字段的文本会使用ik_max_word
分词器进行分词处理,以确保文本被尽可能多地切分成词项。而在搜索时,content
字段的文本会使用ik_smart
分词器进行分词处理,以提高搜索的准确性和相关性。
以下是关于standard,ik_smart,ik_max_word这几个分词器的对比:
GET /_analyze
{"tokenizer": "standard","text": "我,机器人"
}GET /_analyze
{"tokenizer": "ik_smart","text": "我,机器人"
}GET /_analyze
{"tokenizer": "ik_max_word","text": "我,机器人"
}
结果如下:
# GET /_analyze (standard)
{"tokens": [{"token": "我","start_offset": 0,"end_offset": 1,"type": "<IDEOGRAPHIC>","position": 0},{"token": "机","start_offset": 2,"end_offset": 3,"type": "<IDEOGRAPHIC>","position": 1},{"token": "器","start_offset": 3,"end_offset": 4,"type": "<IDEOGRAPHIC>","position": 2},{"token": "人","start_offset": 4,"end_offset": 5,"type": "<IDEOGRAPHIC>","position": 3}]
}
# GET /_analyze(ik_smart)
{"tokens": [{"token": "我","start_offset": 0,"end_offset": 1,"type": "CN_CHAR","position": 0},{"token": "机器人","start_offset": 2,"end_offset": 5,"type": "CN_WORD","position": 1}]
}
# GET /_analyze (ik_max_word)
{"tokens": [{"token": "我","start_offset": 0,"end_offset": 1,"type": "CN_CHAR","position": 0},{"token": "机器人","start_offset": 2,"end_offset": 5,"type": "CN_WORD","position": 1},{"token": "机器","start_offset": 2,"end_offset": 4,"type": "CN_WORD","position": 2},{"token": "人","start_offset": 4,"end_offset": 5,"type": "CN_CHAR","position": 3}]
}
如果使用了不存在的分词器会出现这个错误。
{"error": {"root_cause": [{"type": "illegal_argument_exception","reason": "failed to find global tokenizer under [simple]"}],"type": "illegal_argument_exception","reason": "failed to find global tokenizer under [simple]"},"status": 400
}