ElasticSearch for Python
分词器安装–ik
ik下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v7.6.2
ik分词器需要安装到elasticsearch-7.6.2目录下的plugins下
elasticseacrh安装目录中间不可以有空格,如果出现空格,会出现elasticsearch无法启动,请注意!!!
ik分词器的由来
IK Analyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。从2006年12月推出1.0版开始, IK Analyzer已经推出了4个大版本。最初,它是以开源项目Luence为应用主体的,结合词典分词和文法分析算法的中文分词组件。从3.0版本开始,IK发展为面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。在2012版本中,IK实现了简单的分词歧义排除算法,标志着IK分词器从单纯的词典分词向模拟语义分词衍化。
IK Analyzer 2012特性:
- 采用了特有的
正向迭代最细粒度切分算法
,支持细粒度和智能分词两种切分模式。在系统环境:Core2 i7 3.4G双核,4G内存,window 7 64位, Sun JDK 1.6_29 64位 普通pc环境测试,IK2012具有160万字/秒(3000KB/S)的高速处理能力。 - 2012版本的智能分词模式支持简单的分词排歧义处理和数量词合并输出。
- 采用了多子处理器分析模式,支持:英文字母、数字、中文词汇等分词处理,兼容韩文、日文字符
- 优化的词典存储,更小的内存占用。支持用户词典扩展定义。特别的,在2012版本,词典支持中文,英文,数字混合词语。
后来,被一个叫medcl(曾勇 elastic开发工程师与布道师,elasticsearch开源社区负责人,2015年加入elastic)的人集成到了elasticsearch中, 并支持自定义字典…
测试
安装成功以后,重启elasticsearch和kibanan
GET _analyze
{
"analyzer": "ik_max_word",
"text": "学习使我快乐"
}
测试结果:
{
"tokens" : [
{
"token" : "学习",
"start_offset" : 0,
"end_offset" : 2,
"type" : "CN_WORD",
"position" : 0
},
{
"token" : "使",
"start_offset" : 2,
"end_offset" : 3,
"type" : "CN_CHAR",
"position" : 1
},
{
"token" : "我",
"start_offset" : 3,
"end_offset" : 4,
"type" : "CN_CHAR",
"position" : 2
},
{
"token" : "快乐",
"start_offset" : 4,
"end_offset" : 6,
"type" : "CN_WORD",
"position" : 3
}
]
}
ik-max-word:将文档做最细粒度的拆分,以穷尽尽可能的组合
GET _analyze
{
"analyzer": "ik_smart",
"text": "今天天气不错"
}
测试结果
{
"tokens" : [
{
"token" : "今天天气",
"start_offset" : 0,
"end_offset" : 4,
"type" : "CN_WORD",
"position" : 0
},
{
"token" : "不错",
"start_offset" : 4,
"end_offset" : 6,
"type" : "CN_WORD",
"position" : 1
}
]
}
ik_smart:最粗粒度的拆分文档
python连接elasticsearch
下载依赖包:
pip install elasticsearch
连接elasticsearch
from elasticsearch import Elasticsearch
# 默认连接本地的elasticsearch
es = Elasticsearch()
# 指定IP和端口连接
es = Elasticsearch(['127.0.0.1:9200'])
测试是否连接成功:
from elasticsearch import Elasticsearch
es = Elasticsearch() # 默认连接本地elasticsearch
print(es.ping()) # 返回为True,代表连接成功
python操作elasticsearch
第一个简单示例
from elasticsearch import Elasticsearch
es = Elasticsearch()
print(es.index(index='index01', doc_type='doc', id=1, body={'name': "zhangsan", "age": 20}))
返回结果
{'_index': 'index01', '_type': 'doc', '_id': '1', '_version': 1, 'result': 'created', '_shards': {'total': 2, 'successful': 1, 'failed': 0}, '_seq_no': 0, '_primary_term': 1}
获取数据
from elasticsearch import Elasticsearch
es = Elasticsearch()
print(es.get(index='index01', doc_type='doc', id=1))
返回结果
{'_index': 'index01', '_type': 'doc', '_id': '1', '_version': 1, '_seq_no': 0, '_primary_term': 1, 'found': True, '_source': {'name': 'zhangsan', 'age': 20}}
Python中关于elasticsearch的操作,主要集中一下几个方面:
- 结果过滤,对于返回结果做过滤,主要是优化返回内容。
- Elasticsearch(简称es),直接操作elasticsearch对象,处理一些简单的索引信息。一下几个方面都是建立在es对象的基础上。
- Indices,关于索引的细节操作,比如创建自定义的
mappings
。 - Cluster,关于集群的相关操作。
- Nodes,关于节点的相关操作。
- Cat API,换一种查询方式,一般的返回都是json类型的,cat提供了简洁的返回结果。
- Snapshot,快照相关,快照是从正在运行的Elasticsearch集群中获取的备份。我们可以拍摄单个索引或整个群集的快照,并将其存储在共享文件系统的存储库中,并且有一些插件支持S3,HDFS,Azure,Google云存储等上的远程存储库。
- Task Management API,任务管理API是新的,仍应被视为测试版功能。API可能以不向后兼容的方式更改。
结果过滤
from elasticsearch import Elasticsearch
es = Elasticsearch()
print(es.search(index='index01', filter_path=['hits.total', 'hits.hits._source']))
返回结果
{'hits': {'total': {'value': 1, 'relation': 'eq'}, 'hits': [{'_source': {'name': 'zhangsan', 'age': 20}}]}}
filter_path
参数用于减少elasticsearch返回的响应,比如仅返回hits.total
和hits.hits._source
内容。
除此之外,filter_path
参数还支持*
通配符以匹配字段名称、任何字段或者字段部分:
from elasticsearch import Elasticsearch
es = Elasticsearch()
print(es.search(index='index01', filter_path=['hits.hits._*']))
# print(es.search(index='index01', filter_path=['hits.to*'])) # 仅返回响应数据的total
返回结果:
{'hits': {'hits': [{'_index': 'index01', '_type': 'doc', '_id': '1', '_score': 1.0, '_source': {'name': 'zhangsan', 'age': 20}}]}}
指定类型的结果过滤
from elasticsearch import Elasticsearch
es = Elasticsearch()
print(es.search(index='index01', doc_type='doc'))
返回结果
{'took': 4, 'timed_out': False, '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0}, 'hits': {'total': {'value': 1, 'relation': 'eq'}, 'max_score': 1.0, 'hits': [{'_index': 'index01', '_type': 'doc', '_id': '1', '_score': 1.0, '_source': {'name': 'zhangsan', 'age': 20}}]}}
elasticsearch对象
index: 向指定索引添加或更新文档,如果索引不存在,首先会创建该索引,然后再执行添加或者更新操作。
from elasticsearch import Elasticsearch
es = Elasticsearch()
print(es.index(index='index02', doc_type='doc', id='1', body={"name": "lisi", "age": 22}))
# 如果不指定doc_type会报错,TypeError: index() missing 1 required positional argument: 'doc_type'
# print(es.index(index='index02', id='2', body={"name": "wangwu", "age": 23}))
# 可以不指定id,默认生成一个id
# print(es.index(index='index02', doc_type='doc', body={"name": "zhaoliu", "age": 20}))
返回结果:
{'_index': 'index02', '_type': 'doc', '_id': '1', '_version': 1, 'result': 'created', '_shards': {'total': 2, 'successful': 1, 'failed': 0}, '_seq_no': 0, '_primary_term': 1}
get:查询索引中指定文档
from elasticsearch import Elasticsearch
es = Elasticsearch()
print(es.get(index='index02', doc_type='doc', id=1))
# 如果不指定id,会报TypeError: get() missing 1 required positional argument: 'id'
# print(es.get(index='index02', doc_type='doc'))
# 如果不指定doc_type,会报TypeError: get() missing 1 required positional argument: 'doc_type'
# print(es.get(index='index', id=1))
返回结果
{'_index': 'index02', '_type': 'doc', '_id': '1', '_version': 1, '_seq_no': 0, '_primary_term': 1, 'found': True, '_source': {'name': 'lisi', 'age': 22}}
search,执行搜索查询并获取与查询匹配的搜索匹配。这个用的最多,可以跟复杂的查询条件。
-
index
要搜索的以逗号分隔的索引名称列表; 使用_all 或空字符串对所有索引执行操作。 -
doc_type
要搜索的以逗号分隔的文档类型列表; 留空以对所有类型执行操作。 -
body
使用Query DSL(QueryDomain Specific Language查询表达式)的搜索定义。 -
_source
返回_source
字段的true或false,或返回的字段列表,返回指定字段。 -
_source_exclude
要从返回的_source
字段中排除的字段列表,返回的所有字段中,排除哪些字段。 -
_source_include
从_source
字段中提取和返回的字段列表,跟_source
差不多。
from elasticsearch import Elasticsearch
es = Elasticsearch()
print(es.search(index='index01', doc_type='doc', body={"query": {"match":{"age": 20}}}))
# 结果字段过滤
# print(es.search(index='index02', doc_type='doc', body={"query": {"match":{"age": 19}}},_source=['name', 'age']))
# 结果字段过滤,排除年龄字段
# print(es.search(index='index01', doc_type='doc', body={"query": {"match":{"age": 19}}},_source_exclude =[ 'age']))
#
print(es.search(index='index02', doc_type='doc', body={"query": {"match":{"age": 19}}},_source_include =[ 'age']))
返回结果
{'took': 2, 'timed_out': False, '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0}, 'hits': {'total': {'value': 1, 'relation': 'eq'}, 'max_score': 1.0, 'hits': [{'_index': 'index01', '_type': 'doc', '_id': '1', '_score': 1.0, '_source': {'name': 'zhangsan', 'age': 20}}]}}
get_source,通过索引、类型和ID获取文档的来源,其实,直接返回想要的字典。
from elasticsearch import Elasticsearch
es = Elasticsearch()
print(es.get_source(index='index01', doc_type='doc', id='1'))
返回结果
{'name': 'zhangsan', 'age': 20}
count,执行查询并获取该查询的匹配数。比如查询年龄是20的文档。
from elasticsearch import Elasticsearch
es = Elasticsearch()
body = {
"query": {
"match": {
"age": 20
}
}
}
print(es.count(index='index01', doc_type='doc', body=body))
# count其它用法
print(es.count(index='index01', doc_type='doc', body=body)['count']) # 返回 1
print(es.count(index='index01')) # 返回{'count': 1, '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0}}
print(es.count(index='index01', doc_type='doc')) # 返回{'count': 1, '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0}}
返回结果
{'count': 1, '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0}}
create,创建索引(索引不存在的话)并新增一条数据,索引存在仅新增(只能新增,重复执行会报错)。
from elasticsearch import Elasticsearch
es = Elasticsearch()
print(es.create(index='index03', doc_type='doc', id='1', body={"name": 'laozhang', "age": 20}))
返回结果
{'_index': 'index03', '_type': 'doc', '_id': '1', '_version': 1, 'result': 'created', '_shards': {'total': 2, 'successful': 1, 'failed': 0}, '_seq_no': 0, '_primary_term': 1}
delete,删除指定的文档。比如删除文章id为4
的文档,但不能删除索引,如果想要删除索引,还需要es.indices.delete来处理
from elasticsearch import Elasticsearch
es = Elasticsearch()
print(es.delete(index='index03', doc_type='doc', id='1'))
返回结果
{'_index': 'index03', '_type': 'doc', '_id': '1', '_version': 2, 'result': 'deleted', '_shards': {'total': 2, 'successful': 1, 'failed': 0}, '_seq_no': 1, '_primary_term': 1}
delete_by_query,删除与查询匹配的所有文档。
-
index
要搜索的以逗号分隔的索引名称列表; 使用_all 或空字符串对所有索引执行操作。 -
doc_type
要搜索的以逗号分隔的文档类型列表; 留空以对所有类型执行操作。 -
body
使用Query DSL的搜索定义。
exists,查询elasticsearch中是否存在指定的文档,返回一个布尔值。
print(es.exists(index='index04', doc_type='doc', id='1'))
返回结果
False
info,获取当前集群的基本信息。
print(es.info())
返回结果
{'name': 'MING', 'cluster_name': 'elasticsearch', 'cluster_uuid': 'ggy3MupOSIqmnigmXroxHQ', 'version': {'number': '7.6.2', 'build_flavor': 'default', 'build_type': 'zip', 'build_hash': 'ef48eb35cf30adf4db14086e8aabd07ef6fb113f', 'build_date': '2020-03-26T06:34:37.794943Z', 'build_snapshot': False, 'lucene_version': '8.4.0', 'minimum_wire_compatibility_version': '6.8.0', 'minimum_index_compatibility_version': '6.0.0-beta1'}, 'tagline': 'You Know, for Search'}
ping,如果群集已启动,则返回True,否则返回False。
print(es.ping())
返回结果
True
indices.analyze,返回分词结果。
from elasticsearch import Elasticsearch
es = Elasticsearch()
print(es.indices.analyze(body={'analyzer': "ik_max_word", "text": "今天天气不错,风和日丽的。"}))
返回结果
{'tokens': [{'token': '今天天气', 'start_offset': 0, 'end_offset': 4, 'type': 'CN_WORD', 'position': 0}, {'token': '今天', 'start_offset': 0, 'end_offset': 2, 'type': 'CN_WORD', 'position': 1}, {'token': '天天', 'start_offset': 1, 'end_offset': 3, 'type': 'CN_WORD', 'position': 2}, {'token': '天气', 'start_offset': 2, 'end_offset': 4, 'type': 'CN_WORD', 'position': 3}, {'token': '不错', 'start_offset': 4, 'end_offset': 6, 'type': 'CN_WORD', 'position': 4}, {'token': '风和日丽', 'start_offset': 7, 'end_offset': 11, 'type': 'CN_WORD', 'position': 5}, {'token': '风和', 'start_offset': 7, 'end_offset': 9, 'type': 'CN_WORD', 'position': 6}, {'token': '日', 'start_offset': 9, 'end_offset': 10, 'type': 'CN_CHAR', 'position': 7}, {'token': '丽', 'start_offset': 10, 'end_offset': 11, 'type': 'CN_CHAR', 'position': 8}, {'token': '的', 'start_offset': 11, 'end_offset': 12, 'type': 'CN_CHAR', 'position': 9}]}
indices.delete,在Elasticsearch中删除索引。
print(es.indices.delete(index='index03'))
返回结果
{'acknowledged': True}