elasticsearch是经常用到的文档索引工具,使用方便快捷。
之前介绍了如何增删改索引结构
https://blog.csdn.net/liliang199/article/details/155574706
这里进一步示例在创建索引后,如何全文搜索索引结构。
所用索引数据初始化自上述内容,详细过程参考上述连接。
这里所用示例代码参考和修改自网络资料。
1 分词器分析
elasticsearch全文检索依赖分词器对输入文本进行分词,然后依据分词在文档库中进行匹配。
1.1 elasticsearch分词
elasticsearch常用的分词器罗列如下:
standard是默认分词器,对单个字符进行切分,查全率高,准确度较低。
IK 分词器 ik_max_word,查全率与准确度较高,性能高,业务中普遍采用的中文分词器。
IK 分词器 ik_smart,切分力度较大,准确度与查全率不高,但是查询性能较高。
Smart Chinese 分词器,查全率与准确率性能较高。
hanlp 中文分词器,切分力度较大,准确度与查全率不高,但是查询性能较高。
Pinyin 分词器,针对汉字拼音进行的分词器,与上面介绍的分词器稍有不同,在用拼音进行查询时查全率准确度较高。
如果要说你用standard之外的分词器,比如ik系列,需要自主下载和安装,参考链接如下所示
https://github.com/infinilabs/analysis-ik/blob/master/README.md
1.2 standard分词示例
这里应用standard分词器,示例elasticsearch的分词结果。
# 要分析的文本内容
text = "ElasticSearch的应用场景."
# 自定义分词器的名称
analyzer_name = "standard"
response = es_client.indices.analyze(
index=index, # 替换为你的索引名
body={
# "analyzer": analyzer_name,
"text": text
}
)
print(response)
# 提取分词结果
tokens = [token["token"] for token in response["tokens"]]
# 打印分词结果
print(tokens)
输出如下所示
{'tokens': [{'token': 'elasticsearch', 'start_offset': 0, 'end_offset': 13, 'type': '<ALPHANUM>', 'position': 0}, {'token': '的', 'start_offset': 13, 'end_offset': 14, 'type': '<IDEOGRAPHIC>', 'position': 1}, {'token': '应', 'start_offset': 14, 'end_offset': 15, 'type': '<IDEOGRAPHIC>', 'position': 2}, {'token': '用', 'start_offset': 15, 'end_offset': 16, 'type': '<IDEOGRAPHIC>', 'position': 3}, {'token': '场', 'start_offset': 16, 'end_offset': 17, 'type': '<IDEOGRAPHIC>', 'position': 4}, {'token': '景', 'start_offset': 17, 'end_offset': 18, 'type': '<IDEOGRAPHIC>', 'position': 5}]}
'elasticsearch', '的', '应', '用', '场', '景'
2 match查询
2.1 match查询
match匹配查询属于全文查询,elasticsearch在处理全文搜索时,分析查询字符串,根据分词结果构建查询,返回查询结果。
match查询有三种类型,分别是布尔、短语和短语前缀,默认match查询是布尔类型。
elasticsearch引擎对查询字符串进行分词的过程,参考第一节分词器分析。
2.2 match示例
上一篇文章中,将数据导入elasticsearch,导入过程参考
https://blog.csdn.net/liliang199/article/details/155574706
导入完成后,title字段将会包含如下数据。
Elasticsearch 完全指南:原理、优势与应用场景
20个必知的PyTorch概念简单解释,带你快速入门"
查询问题为"Elasticsearch应用场景"
针对title字段的match查询代码示例如下。
# 使用search查询数据
query = {
"query": {
"match": {
"title": "ElasticSearch的应用场景",
}
},
"from": 0,
"size": 3
}
res = es_client.search(index=index, body=query)
print(res)
虽然输入"ElasticSearch的应用场景"不能完全匹配elasticsearch title字段存储文本。
然而,依然搜到数据。这说明match匹配不是精确检索,而是全文分词检索。
{'took': 28, 'timed_out': False, '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0}, 'hits': {'total': {'value': 2198, 'relation': 'eq'}, 'max_score': 6.528569, 'hits': [{'_index': 'es_index_test', '_id': '1', '_score': 6.528569, '_source': {'document_id': 6, 'title': '20个必知的PyTorch概念简单解释,带你快速入门', 'content': 'PyTorch是当今最重要且最受欢迎的深度学习框架之一。它基于Meta的Lua语言Torch库构建,并于2017年开源。自发布以来,该库已被用于构建几乎所有重要的现代AI创新,从特斯拉的自动驾驶汽车到OpenAI的ChatGPT。本文将从基础出发,系统阐述20个最重要的概念,以深化对PyTorch的理解。'}}, {'_index': 'es_index_test', '_id': '2', '_score': 0.0034088849, '_source': {'document_id': '2', 'title': 'Elasticsearch 完全指南:原理、优势与应用场景', 'content': 'Elasticsearch 是一个基于 Apache Lucene 构建的开源、分布式、RESTful 搜索和分析引擎。它是 Elastic Stack(ELK Stack)的核心组件,由 Elastic 公司开发和维护。'}}, {'_index': 'es_index_test', '_id': '3', '_score': 0.0034088849, '_source': {'document_id': '3', 'title': 'Elasticsearch 完全指南:原理、优势与应用场景', 'content': 'Elasticsearch 是一个基于 Apache Lucene 构建的开源、分布式、RESTful 搜索和分析引擎。它是 Elastic Stack(ELK Stack)的核心组件,由 Elastic 公司开发和维护。'}}]}}
3 match_phrase 搜索
3.1 match_phrase查询
match_phrase要求所有的分词必须同时出现在文档中,同时位置必须紧邻一致。
match_phrase查询时,elasticsearch首先分析即分词查询字符串,从分词后的文本中构建短语查询,这意味着必须匹配短语中的所有分词,并且保证各个分词的相对位置不变。
这里用的是standard分词器,对单个字符进行切分,查全率高,准确度较低。
为确保找到内容,需要引入slop参数调整。
3.2 match_phrase示例
match_phrase短语匹配查询示例如下。
所用查询问题为"Elasticsearch应用场景",与2.2所用查询问题一致。
slop=8时,查询未命中。
示例如下
# 使用search查询数据
query = {
"query": {
"match_phrase": {
"title": {
"query": "Elasticsearch应用场景",
"slop": 8,
}
}
},
"from": 0,
"size": 3
}
res = es_client.search(index=index, body=query)
print(res)
输出如下所示,slop=8时显然未命中。
{'took': 23, 'timed_out': False, '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0}, 'hits': {'total': {'value': 0, 'relation': 'eq'}, 'max_score': None, 'hits': []}}
需要将slop设置为更大的数字,但有可能混入其他可能不太相关的文档。
slop=9命中
示例如下
# 使用search查询数据
query = {
"query": {
"match_phrase": {
"title": {
"query": "Elasticsearch应用场景",
"slop": 9,
}
}
},
"from": 0,
"size": 3
}
res = es_client.search(index=index, body=query)
print(res)
输出示例如下所示。
{'took': 40, 'timed_out': False, '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0}, 'hits': {'total': {'value': 2197, 'relation': 'eq'}, 'max_score': 0.00057690963, 'hits': [{'_index': 'es_index_test', '_id': '2', '_score': 0.00057690963, '_source': {'document_id': '2', 'title': 'Elasticsearch 完全指南:原理、优势与应用场景', 'content': 'Elasticsearch 是一个基于 Apache Lucene 构建的开源、分布式、RESTful 搜索和分析引擎。它是 Elastic Stack(ELK Stack)的核心组件,由 Elastic 公司开发和维护。'}}, {'_index': 'es_index_test', '_id': '3', '_score': 0.00057690963, '_source': {'document_id': '3', 'title': 'Elasticsearch 完全指南:原理、优势与应用场景', 'content': 'Elasticsearch 是一个基于 Apache Lucene 构建的开源、分布式、RESTful 搜索和分析引擎。它是 Elastic Stack(ELK Stack)的核心组件,由 Elastic 公司开发和维护。'}}, {'_index': 'es_index_test', '_id': '4', '_score': 0.00057690963, '_source': {'document_id': '4', 'title': 'Elasticsearch 完全指南:原理、优势与应用场景', 'content': 'Elasticsearch 是一个基于 Apache Lucene 构建的开源、分布式、RESTful 搜索和分析引擎。它是 Elastic Stack(ELK Stack)的核心组件,由 Elastic 公司开发和维护。'}}]}}
4 精确查询
如果要实现精确查询,需要将字段设为keyword类,然后使用term精确匹配对应字段。
这里首先同时创建keyword、text索引字段,导入数据,然后示例term精确匹配查询过程。
4.1 创建索引
为对比分析,这里同时创建keywor和text索引字段。
具体为字段document_id创建keyword索引,为title为text索引。
示例代码如下。
index = "es_index_key"
mapping = {
"properties": {
"document_id": {"type": "keyword", "store": True, "similarity": "boolean"},
"title": {
"type": "text"
},
}
}
print(es_client.indices.exists(index=index))
res = es_client.indices.create(
index=index,
mappings=mapping
)
print(res)
输出如下
False
{'acknowledged': True, 'shards_acknowledged': True, 'index': 'es_index_key'}
4.2 导入数据
然后为创建的索引,导入测试数据,示例代码如下。
obj1 = {
"document_id": "news_1",
"title": u"The Ten Best Science Books of 2025",
"content": u"In 2025, our science reporters followed the first confirmed glimpse of a colossal squid and a rare look at dinosaur blood vessels. We watched the odds of a future asteroid impact climb to higher-than-normal levels---then drop back down to zero. We parsed headlines on a blood test to detect cancer and a beloved pair of coyotes in New York City's Central Park. Throughout it all, many of us read extended works of science nonfiction, pulling back the curtain on tuberculosis, evolution and the Arctic....",
}
obj2 = {
"document_id": "news_2",
"title": u"The 7 Most Groundbreaking NASA Discoveries of 2025",
"content": u"In 2025, NASA faced unprecedented uncertainty as it grappled with sweeping layoffs, looming budget cuts, and leadership switch-ups. Despite all of that, the agency somehow still managed to do some seriously astonishing science.....",
}
_id1 = 1
es_client.index(index=index, body=obj1, id=_id1)
_id2 = 2
es_client.index(index=index, body=obj2, id=_id2)
输出如下所示
ObjectApiResponse({'_index': 'es_index_key', '_id': '2', '_version': 1, 'result': 'created', '_shards': {'total': 2, 'successful': 1, 'failed': 0}, '_seq_no': 1, '_primary_term': 1})
4.3 term精确匹配
这里分别对keyword、text字段进行精确、模糊查询示例。
keyword类型字段使用term精确匹配有效,text类型字段使用term精确匹配无效。
1)keyword精确查询
使用keyword字段document_id的精确查询示例如下所示。
测试问题为document_id="news_2"
query = {
"query": {
"term": {
"document_id": "news_2"
}
}
}
res = es_client.search(index=index, body=query)
print(res)
输出如下,找到了数据。
{'took': 33, 'timed_out': False, '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0}, 'hits': {'total': {'value': 1, 'relation': 'eq'}, 'max_score': 1.0, 'hits': [{'_index': 'es_index_key', '_id': '2', '_score': 1.0, '_source': {'document_id': 'news_2', 'title': 'The 7 Most Groundbreaking NASA Discoveries of 2025', 'content': 'In 2025, NASA faced unprecedented uncertainty as it grappled with sweeping layoffs, looming budget cuts, and leadership switch-ups. Despite all of that, the agency somehow still managed to do some seriously astonishing science.....'}}]}}
对测试问题做些微小修改,document_id="news_2x"
uery = {
"query": {
"term": {
"document_id": "news_2 x"
}
}
}
res = es_client.search(index=index, body=query)
print(res)
输出如下,显然这时没有找到
{'took': 16, 'timed_out': False, '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0}, 'hits': {'total': {'value': 0, 'relation': 'eq'}, 'max_score': None, 'hits': []}}
这说明document_id的term精确匹配生效了。
2)text精确查询
这里,title字段采用text类型,这里对text进行term精确匹配,
测试问题如下
title= u"The 7 Most Groundbreaking NASA Discoveries of 2025"
结合4.2数据导入过程,测试问题与elasticsearch库中的title完全一样。
测试代码如下所示
query = {
"query": {
"term": {
"title": u"The 7 Most Groundbreaking NASA Discoveries of 2025",
}
}
}
res = es_client.search(index=index, body=query)
print(res)
输出如下,显然在titile正确情况下,依然没有找到数据。
{'took': 19, 'timed_out': False, '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0}, 'hits': {'total': {'value': 0, 'relation': 'eq'}, 'max_score': None, 'hits': []}}
3)text模糊查询
在term精确匹配失效的情况下,尝试对title字段进行模糊匹配。
测试问题不变,title= u"The 7 Most Groundbreaking NASA Discoveries of 2025"
测试代码如下所示。
query = {
"query": {
"match": {
"title": u"The 7 Most Groundbreaking NASA Discoveries of 2025",
}
}
}
res = es_client.search(index=index, body=query)
print(res)
输出如下,转为模糊查询后,就找到数据了。
这说明text类型字段不支持term精确匹配。
{'took': 37, 'timed_out': False, '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0}, 'hits': {'total': {'value': 2, 'relation': 'eq'}, 'max_score': 3.906169, 'hits': [{'_index': 'es_index_key', '_id': '2', '_score': 3.906169, '_source': {'document_id': 'news_2', 'title': 'The 7 Most Groundbreaking NASA Discoveries of 2025', 'content': 'In 2025, NASA faced unprecedented uncertainty as it grappled with sweeping layoffs, looming budget cuts, and leadership switch-ups. Despite all of that, the agency somehow still managed to do some seriously astonishing science.....'}}, {'_index': 'es_index_key', '_id': '1', '_score': 0.5623002, '_ignored': ['content.keyword'], '_source': {'document_id': 'news_1', 'title': 'The Ten Best Science Books of 2025', 'content': 'In 2025, our science reporters followed the first confirmed glimpse of a colossal squid and a rare look at dinosaur blood vessels. We watched the odds of a future asteroid impact climb to higher-than-normal levels---then drop back down to zero. We parsed headlines on a blood test to detect cancer and a beloved pair of coyotes in New York City's Central Park. Throughout it all, many of us read extended works of science nonfiction, pulling back the curtain on tuberculosis, evolution and the Arctic....'}}]}}
reference
elasticsearch增删改查索引结构示例
https://blog.csdn.net/liliang199/article/details/155574706
ElasticSearch查询 第四篇:匹配查询(Match)
https://www.cnblogs.com/ljhdo/p/4577065.html
elasticsearch7.x 的 python sdk,如何指定自定义的分词器查看分词后的结果
https://segmentfault.com/a/1190000043863785
Elasticsearch 中文分词器
https://developer.aliyun.com/article/848626
Elasticsearch 精确查询
https://www.echo.cool/docs/database/elasticsearch/elasticsearch-query/elasticsearch-exact-query/
【ElasticSearch】精确匹配text字段 用match加.keyword 或 term
https://blog.csdn.net/u012161251/article/details/120559438
IK Analysis for Elasticsearch and OpenSearch
https://github.com/infinilabs/analysis-ik/blob/master/README.md