如果您对Elasticsearch计算不同的嵌套值感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于Elasticsearch计算不同的嵌套值的详细内容,我们还将为您解答ela
如果您对Elasticsearch 计算不同的嵌套值感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于Elasticsearch 计算不同的嵌套值的详细内容,我们还将为您解答elasticsearch嵌套查询的相关问题,并且为您提供关于docker 部署 elasticsearch + elasticsearch-head + elasticsearch-head 跨域问题 + IK 分词器、ElasticSearch (一) ElasticSearch 的应用场景及为什么要选择 ElasticSearch?、Elasticsearch CentOS6.5下安装ElasticSearch6.2.4+elasticsearch-head+Kibana、Elasticsearch python操作实践(elasticsearch 、Elasticsearch DSL)的有价值信息。
本文目录一览:- Elasticsearch 计算不同的嵌套值(elasticsearch嵌套查询)
- docker 部署 elasticsearch + elasticsearch-head + elasticsearch-head 跨域问题 + IK 分词器
- ElasticSearch (一) ElasticSearch 的应用场景及为什么要选择 ElasticSearch?
- Elasticsearch CentOS6.5下安装ElasticSearch6.2.4+elasticsearch-head+Kibana
- Elasticsearch python操作实践(elasticsearch 、Elasticsearch DSL)
Elasticsearch 计算不同的嵌套值(elasticsearch嵌套查询)
如何解决Elasticsearch 计算不同的嵌套值?
我的文档结构如下
{
"_source": {
"nested_obj": [
{
"data_id": "123"
}
]
}
}
现在我想计算 data_id
的所有不同出现次数,但我不确定这样的查询是否准确?
GET /_search
{
"aggs": {
"nested_properties": {
"nested": {
"path": "nested_obj"
},"aggs": {
"count": {
"value_count": {
"field": "nested_obj.data_id"
}
}
}
}
}
}
解决方法
value_count
指标聚合不计算不同的值,而是计算所有值。您需要的是 cardinality
aggregation,但您需要知道 counts will be approximate 取决于 data_id
字段是否为高基数。
不过,您可以控制 precision threshold。
docker 部署 elasticsearch + elasticsearch-head + elasticsearch-head 跨域问题 + IK 分词器
0. docker pull 拉取 elasticsearch + elasticsearch-head 镜像
1. 启动 elasticsearch Docker 镜像
docker run -di --name tensquare_elasticsearch -p 9200:9200 -p 9300:9300 elasticsearch
对应 IP:9200 ---- 反馈下边 json 数据,表示启动成功
2. 启动 elasticsearch-head 镜像
docker run -d -p 9100:9100 elasticsearch-head
对应 IP:9100 ---- 得到下边页面,即启动成功
3. 解决跨域问题
进入 elasticsearch-head 页面,出现灰色未连接状态 , 即出现跨域问题
1. 根据 docker ps 得到 elasticsearch 的 CONTAINER ID
2. docker exec -it elasticsearch 的 CONTAINER ID /bin/bash 进入容器内
3. cd ./config
4. 修改 elasticsearch.yml 文件
echo "
http.cors.enabled: true
http.cors.allow-origin: ''*''" >> elasticsearch.yml
4. 重启 elasticsearch
docker restart elasticsearch的CONTAINER ID
重新进入 IP:9100 进入 elasticsearch-head, 出现绿色标注,配置成功 !
5. ik 分词器的安装
将在 ik 所在的文件夹下,拷贝到 /usr/share/elasticsearch/plugins --- 注意: elasticsearch 的版本号必须与 ik 分词器的版本号一致
docker cp ik elasticsearch的CONTAINER ID:/usr/share/elasticsearch/plugins
重启elasticsearch
docker restart elasticsearch
未添加ik分词器:http://IP:9200/_analyze?analyzer=chinese&pretty=true&text=我爱中国
添加ik分词器后:http://IP:9200/_analyze?analyzer=ik_smart&pretty=true&text=我爱中国
ElasticSearch (一) ElasticSearch 的应用场景及为什么要选择 ElasticSearch?
先了解一下数据的分类
结构化数据
又可以称之为行数据,存储在数据库里,可以用二维表结构来逻辑表达实现的数据。其实就是可以能够用数据或者统一的结构加以表示的数据。比如在数据表存储商品的库存,可以用整型表示,存储价格可以用浮点型表示,再比如给用户存储性别,可以用枚举表示,这都是结构化数据。
非结构化数据
无法用数字或者统一的结构表示的数据,称之为飞结构化数据。如:文本、图像、声音、网页。
其实结构化数据又数据非结构化数据。商品标题、描述、文章描述都是文本,其实文本就是非结构化数据。那么就可以说非结构化数据即为全文数据。
什么是全文检索?
一种将文件或者数据库中所有文本与检索项相匹配的文字资料检索方法,称之为全文检索。
全文检索的两种方法
顺序扫描法:将数据表的所有数据逐个扫描,再对文字描述扫描,符合条件的筛选出来,非常慢!
索引扫描法:全文检索的基本思路,也就是将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对快的目的。
全文检索的过程:
先索引的创建,然后索引搜索
为什么要选择用 ElasticSearch?
全文搜索属于最常见的需求,开源的 Elasticsearch (以下简称 Elastic)是目前全文搜索引擎的首选。
Elastic 的底层是开源库 Lucene。但是,你没法直接用 Lucene,必须自己写代码去调用它的接口。Elastic 是 Lucene 的封装,提供了 REST API 的操作接口,开箱即用。
分布式的实时文件存储,每个字段都被索引可被搜索。
分布式的实时分析搜索引擎。
可以扩展到上百台服务器,处理 PB 级别结构化或者非结构化数据。
所有功能集成在一个服务器里,可以通过 RESTful API、各种语言的客户端甚至命令与之交互。
上手容易,提供了很多合理的缺省值,开箱即用,学习成本低。
可以免费下载、使用和修改。
配置灵活,比 Sphinx 灵活的多。
Elasticsearch CentOS6.5下安装ElasticSearch6.2.4+elasticsearch-head+Kibana
CentOS6.5下安装ElasticSearch6.2.4
(1)配置JDK环境
配置环境变量
export JAVA_HOME="/opt/jdk1.8.0_144"
export PATH="$JAVA_HOME/bin:$PATH"
export CLASSPATH=".:$JAVA_HOME/lib"
(2)安装ElasticSearch6.2.4
下载地址:https://www.elastic.co/cn/downloads/past-releases/elasticsearch-6-2-4
启动报错:
解决方式:
bin/elasticsearch -Des.insecure.allow.root=true
或者修改bin/elasticsearch,加上ES_JAVA_OPTS属性:
ES_JAVA_OPTS="-Des.insecure.allow.root=true"
再次启动:
这是出于系统安全考虑设置的条件。由于ElasticSearch可以接收用户输入的脚本并且执行,为了系统安全考 虑,建议创建一个单独的用户用来运行ElasticSearch。
如果没有普通用户就要创建一个普通用户组和普通用户,下面介绍一下怎么创建用户组和普通用户
创建用户组和用户:
groupadd esgroup
useradd esuser -g esgroup -p espassword
更改elasticsearch文件夹及内部文件的所属用户及组:
cd /opt
chown -R esuser:esgroup elasticsearch-6.2.4
切换用户并运行:
su esuser
./bin/elasticsearch
再次启动显示已杀死:
需要调整JVM的内存大小:
vi bin/elasticsearch
ES_JAVA_OPTS="-Xms512m -Xmx512m"
再次启动:启动成功
如果显示如下类似信息:
[INFO ][o.e.c.r.a.DiskThresholdMonitor] [ZAds5FP] low disk watermark [85%] exceeded on [ZAds5FPeTY-ZUKjXd7HJKA][ZAds5FP][/opt/elasticsearch-6.2.4/data/nodes/0] free: 1.2gb[14.2%], replicas will not be assigned to this node
需要清理磁盘空间。
后台运行:./bin/elasticsearch -d
测试连接:curl 127.0.0.1:9200
会看到一下JSON数据:
[root@localhost ~]# curl 127.0.0.1:9200
{
"name" : "rBrMTNx",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "-noR5DxFRsyvAFvAzxl07g",
"version" : {
"number" : "5.1.1",
"build_hash" : "5395e21",
"build_date" : "2016-12-06T12:36:15.409Z",
"build_snapshot" : false,
"lucene_version" : "6.3.0"
},
"tagline" : "You Know, for Search"
}
实现远程访问:
需要对config/elasticsearch.yml进行 配置:
network.host: hadoop-001
再次启动报错:Failed to load settings from [elasticsearch.yml]
这个错就是参数的冒号前后没有加空格,加了之后就好,我找了好久这个问题;
后来在一个外国网站找到了这句话.
Exception in thread "main" SettingsException[Failed to load settings from [elasticsearch.yml]]; nested: ElasticsearchParseException[malformed, expected end of settings but encountered additional content starting at line number: [3], column number: [1]]; nested: ParserException[expected ''<document start>'', but found BlockMappingStart
in ''reader'', line 3, column 1:
node.rack : r1
^
];
Likely root cause: expected ''<document start>'', but found BlockMappingStart
in ''reader'', line 3, column 1:
node.rack : r1
这个是行的开头没有加空格,fuck!
Exception in thread "main" SettingsException[Failed to load settings from [elasticsearch.yml]]; nested: ScannerException[while scanning a simple key
in ''reader'', line 11, column 2:
discovery.zen.ping.unicast.hosts ...
^
参数冒号后加空格,或者是数组中间加空格
例如:
# discovery.zen.minimum_master_nodes: 3
再次启动
还是报错
max file descriptors [4096] for elasticsearch process is too low
处理第一个错误:
vim /etc/security/limits.conf //文件最后加入
esuser soft nofile 65536
esuser hard nofile 65536
esuser soft nproc 4096
esuser hard nproc 4096
处理第二个错误:
进入limits.d目录下修改配置文件。
vim /etc/security/limits.d/20-nproc.conf
修改为 esuser soft nproc 4096
注意重新登录生效!!!!!!!!
处理第三个错误:
vim /etc/sysctl.conf
vm.max_map_count=655360
执行以下命令生效:
sysctl -p
关闭防火墙:systemctl stop firewalld.service
启动又又又报错
system call filters failed to install; check the logs and fix your configuration or disable sys
直接在
config/elasticsearch.yml 末尾加上一句
bootstrap.system_call_filter: false
再次启动成功!
安装Head插件
Head是elasticsearch的集群管理工具,可以用于数据的浏览和查询
(1)elasticsearch-head是一款开源软件,被托管在github上面,所以如果我们要使用它,必须先安装git,通过git获取elasticsearch-head
(2)运行elasticsearch-head会用到grunt,而grunt需要npm包管理器,所以nodejs是必须要安装的
nodejs和npm安装:
http://blog.java1234.com/blog/articles/354.html
git安装
yum install -y git
(3)elasticsearch5.0之后,elasticsearch-head不做为插件放在其plugins目录下了。
使用git拷贝elasticsearch-head到本地
cd ~
git clone git://github.com/mobz/elasticsearch-head.git
(4)安装elasticsearch-head依赖包
[root@localhost local]# npm install -g grunt-cli
[root@localhost _site]# cd /usr/local/elasticsearch-head/
[root@localhost elasticsearch-head]# cnpm install
(5)修改Gruntfile.js
[root@localhost _site]# cd /usr/local/elasticsearch-head/
[root@localhost elasticsearch-head]# vi Gruntfile.js
在connect-->server-->options下面添加:hostname:’*’,允许所有IP可以访问
(6)修改elasticsearch-head默认连接地址
[root@localhost elasticsearch-head]# cd /usr/local/elasticsearch-head/_site/
[root@localhost _site]# vi app.js
将this.base_uri = this.config.base_uri || this.prefs.get("app-base_uri") || "http://localhost:9200";中的localhost修改成你es的服务器地址
(7)配置elasticsearch允许跨域访问
打开elasticsearch的配置文件elasticsearch.yml,在文件末尾追加下面两行代码即可:
http.cors.enabled: true
http.cors.allow-origin: "*"
(8)打开9100端口
[root@localhost elasticsearch-head]# firewall-cmd --zone=public --add-port=9100/tcp --permanent
重启防火墙
[root@localhost elasticsearch-head]# firewall-cmd --reload
(9)启动elasticsearch
(10)启动elasticsearch-head
[root@localhost _site]# cd ~/elasticsearch-head/
[root@localhost elasticsearch-head]# node_modules/grunt/bin/grunt server 或者 npm run start
(11)访问elasticsearch-head
关闭防火墙:systemctl stop firewalld.service
浏览器输入网址:hadoop-001:9100/
安装Kibana
Kibana是一个针对Elasticsearch的开源分析及可视化平台,使用Kibana可以查询、查看并与存储在ES索引的数据进行交互操作,使用Kibana能执行高级的数据分析,并能以图表、表格和地图的形式查看数据
(1)下载Kibana
https://www.elastic.co/downloads/kibana
(2)把下载好的压缩包拷贝到/soft目录下
(3)解压缩,并把解压后的目录移动到/user/local/kibana
(4)编辑kibana配置文件
[root@localhost /]# vi /usr/local/kibana/config/kibana.yml
将server.host,elasticsearch.url修改成所在服务器的ip地址
server.port: 5601 //监听端口
server.host: "hadoo-001" //监听IP地址,建议内网ip
elasticsearch.url: "http:/hadoo-001" //elasticsearch连接kibana的URL,也可以填写192.168.137.188,因为它们是一个集群
(5)开启5601端口
Kibana的默认端口是5601
开启防火墙:systemctl start firewalld.service
开启5601端口:firewall-cmd --permanent --zone=public --add-port=5601/tcp
重启防火墙:firewall-cmd –reload
(6)启动Kibana
[root@localhost /]# /usr/local/kibana/bin/kibana
浏览器访问:http://192.168.137.188:5601
安装中文分词器
一.离线安装
(1)下载中文分词器
https://github.com/medcl/elasticsearch-analysis-ik
下载elasticsearch-analysis-ik-master.zip
(2)解压elasticsearch-analysis-ik-master.zip
unzip elasticsearch-analysis-ik-master.zip
(3)进入elasticsearch-analysis-ik-master,编译源码
mvn clean install -Dmaven.test.skip=true
(4)在es的plugins文件夹下创建目录ik
(5)将编译后生成的elasticsearch-analysis-ik-版本.zip移动到ik下,并解压
(6)解压后的内容移动到ik目录下
二.在线安装
./elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.2.4/elasticsearch-analysis-ik-6.2.4.zip
Elasticsearch python操作实践(elasticsearch 、Elasticsearch DSL)
Elasticsearch python操作实践(elasticsearch 、Elasticsearch DSL)
关于Elasticsearch
安装方式
文档
中文文档
Elasticsearch
Elasticsearch DSL操作文档
本文通过python模块对elasticsearch进行简单的增删改查。
本文测试脚本仓库地址:https://github.com/YangJunJ/studyElasticsearch.git
环境
- Python 3.6.2
- elasticsearch 7.13.1
- elasticsearch-dsl 7.3.0
- elasticsearch 7.13.1
安装下面两个python模块
sudo pip3 install elasticsearch
sudo pip3 install elasticsearch_dsl
建立连接
创建文件elasticsearch_obj.py
from elasticsearch import Elasticsearch
from elasticsearch_dsl import Search, UpdateByQuery
class ElasticSearchObj(object):
def __init__(self):
self.user_key = "user_index"
self.friend_key = "friend_index"
self.test_count_key = "count_test_key"
# 初始化一个Elasticsearch实例对象
self.client = Elasticsearch(hosts=[{'host': "127.0.0.1", "port": 9200}])
def search(self, index):
# 返回索引对象结果级
return Search(using=self.client, index=index)
def update(self, index):
# ubq = UpdateByQuery(index=index).using(self.client)
# or
ubq = UpdateByQuery(index=index, using=self.client)
return ubq
创建或者更新文档
Elasticsearch 使用 JSON作为文档的序列化格式,用起来有点项nosql,文档的字段数量也可以像mongodb文档一样,不一致不相同的形式存储
index插入
create插入
创建文件study_insert.py
import random
from elasticsearch_obj import ElasticSearchObj
class CreateNewRecord(ElasticSearchObj):
def index(self, index, doc_id=None, doc_type="_doc", **kwargs):
"""
如果索引不存在,则会创建索引并写入文档
self.client.index(index, body, doc_type=None, id=None, params=None, headers=None)
http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html
:param index: 文档索引名
:param doc_id: 当doc_id=None时,通过该方法会向文档中插入一条记录,doc_id!=None时,如果doc_id已经存在则会更新,不存在则插入
:param doc_type: 文档类型,默认为_doc,相同index下的记录值必须一致,如果不相等,则会触发异常
:param kwargs: 文档内容
:return:
"""
return self.client.index(index=index, body=kwargs, doc_type=doc_type, id=doc_id)
def create(self, index, doc_id=None, doc_type="_doc", **kwargs):
"""
http://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html
用法同index,不同的是create必须传递文档Id,否则会触发异常错误
:param index:
:param doc_id:
:param doc_type:
:param kwargs:
:return:
"""
return self.client.create(index=index, id=doc_id, doc_type=doc_type, body=kwargs)
def test_insert(self):
"""
插入一些记录,方便等会查询时使用
:return:
"""
hobby = ["唱", "跳", "rap", "唱跳rap", "游泳", "打球", "其他"]
for i in range(100):
response = self.index(
index=self.user_key,
id=i,
name="".join(random.sample('zyxwvutsrqponmlkjihgfedcba', random.randint(3, 8))),
age=random.randint(18, 30),
hobby=random.choice(hobby),
height=random.randint(155, 185),
sex=random.choice(["男", "女", "不详"])
)
print(f"{self.user_key}插入{i}条数据, 返回:{response}")
for i in range(100):
response = self.index(
index=self.friend_key,
user_id=i,
friend_id=random.randint(0, 99),
word=random.sample(["拧螺丝", "撸代码", "CRUD", "划水", "偷偷写下bug"], random.randint(1, 3)),
other={"work_place": random.choice(["第一排", "第二排"]), "performance": random.choice(["好", "不好"])}
)
print(f"{self.friend_key}插入{i}条数据, 返回:{response}")
for i in range(20000):
response = self.index(
index=self.test_count_key,
user_id=i,
friend_id=random.randint(0, 99),
weight=random.randint(0, 10000)
)
print(f"{self.test_count_key}插入{i}条数据, 返回:{response}")
if __name__ == "__main__":
test = CreateNewRecord()
test.test_insert()
查询
页查询子句
- 模糊查询:match, 返回与提供的文本、数字、日期或布尔值匹配的文档,包括用于模糊匹配
- 精确查询:term, 该术语必须与字段值完全匹配,包括空格和大写
- 范围查询:range, 返回包含提供范围内的术语的文档
- gt: 大于(可选)
- gte: 大于或等于(可选)
- lt: 小于(可选)
- lte:小于或等于(可选)
- format:用于转换date查询中值的日期格式(可选,字符串)
查询上下文query & 过滤上下文filter 差别
用法可以查看下面脚本
创建文件study_search.py
from elasticsearch_obj import ElasticSearchObj
class Search(ElasticSearchObj):
"""
示例 elasticsearch_dsl.Search 基本操作
查询的字段值中如果包含中文、下划线等其他特殊字符, 字段需要需要加上 __keyword,否则无法匹配, 用法详见示例
介绍两个查询中需要使用到的方法:
elasticsearch_dsl.Search.scan(): 将搜索条件扫描索引,返回所有与条件匹配文档生成器
elasticsearch_dsl.Search.to_dict(): 将hit对象系列化成python字典记录
"""
def get_all_record(self):
"""
示例获取self.key下的所有文档
:return:
"""
# all_record 是 elasticsearch_dsl.search.Search对象,可以通过scan() 方法遍历self.key索引内的所有文档
all_record = self.search(self.user_key)
for record in all_record.scan():
# record 是 elasticsearch_dsl.response.hit.Hit 对象
# 可以通过.属性获取字段值, 比如: record.name
# 如果字段名不存在,则会触发'Hit' object has no attribute 错误
print(f"record.id:{record.id}, record.name:{record.name}")
# 上面的是其中一种方法,它也可以通过to_dict()方法,将记录通过python字典的形式返回
print(record.to_dict())
def print_all_record(self, explain, all_record, max_count=3):
i = 1
for record in all_record.scan():
print(explain, record.to_dict())
if i >= max_count:
print(explain, f"查询数量大于{i},后面的记录不打印了")
break
i += 1
self.cross_line()
@staticmethod
def cross_line():
print('=================================================')
def get_record_by_query(self):
"""
示例query的常用用法
:return:
"""
all_record = self.search(self.user_key)
# 例如要找到爱好中包含rap的用户信息
match_rap = all_record.query("match", hobby="rap")
self.print_all_record("查看所有包含爱好rap的用户:", match_rap)
# 查找爱好中含有rap,并且性别为女的用户信息
match_rap_female = all_record.query("match", hobby="rap").query("term", sex__keyword="女")
# match_rap_female = match_rap.query("term", sex__keyword="女")
self.print_all_record("查看爱好含有rap的所有女用户:", match_rap_female)
# 查找身高大于175的男用户,并且爱好只有唱的用户
man_sing_gt_175 = all_record.query("range", height={"gt": 175}).query(
"term", sex__keyword="男").query(
"term", hobby__keyword="唱")
self.print_all_record("查找身高大于175的男用户,并且爱好只有唱的用户", man_sing_gt_175)
def get_record_by_filter(self):
"""
示例filter的用法
filter 与 query用法一样,这里只举一个简单例子
:return:
"""
all_record = self.search(self.user_key)
# 查找年龄大于等于25的男用户,并且爱好是唱跳rap
all_record = all_record.filter("range", age={"gte": 25}).filter(
"term", sex__keyword="男").filter(
"term", hobby__keyword="唱跳rap")
self.print_all_record("查找年龄大于等于25的男用户,并且爱好是唱跳rap:", all_record)
def get_record_by_query_and_filter(self):
"""
query、filter可以混用
举一个例子
:return:
"""
all_record = self.search(self.user_key)
# 查找年龄在20-25的男性用户
all_record = all_record.query("range", age={"gte": 20, "lte": 25}).filter("term", sex__keyword="男")
self.print_all_record("查找年龄在20-25的男性用户:", all_record)
def get_record_by_exclude(self):
"""
非查询
:return:
"""
all_record = self.search(self.user_key)
# 查找性别不是男生,并且爱好不是唱的用户
records = all_record.exclude("term", sex__keyword="男").exclude("term", hobby__keyword="唱")
self.print_all_record("查找性别不是男生,并且爱好不是唱的用户:", records, 6)
# 查找男性用户中,爱好不是唱且身高大于175的用户
records = all_record.filter("term", sex__keyword="男").exclude(
"term", hobby__keyword="唱").query(
"range", height={"gt": 175})
self.print_all_record("查找男性用户中,爱好不是唱且身高大于175的用户:", records, 6)
def other_search(self):
"""
其他查询:
获取文档数量:.count()
查询结果排序:sort(field)
:return:
"""
all_record = self.search(self.user_key)
# 获取id>=90的文档数量
gte_90 = all_record.filter("range", id={"gte": 90})
print(f"id>=90的文档 存在,数量为:{gte_90.count()}") # id>=90的文档 存在,数量为:10
# 获取id>=300的文档数量
gte_300 = all_record.filter("range", id={"gte": 300})
print(f"id>=300的文档 存在,数量为:{gte_300.count()}") # id>=300的文档 存在,数量为:0
# 排序 获取排序结果后,不能使用san(), 比如:self.search(self.key).sort("-height").scan()
# 使用scan()不会以任何预先确定的顺序返回结果, 详见:
# https://elasticsearch-py.readthedocs.io/en/master/helpers.html#elasticsearch.helpers.scan
# 不使用san() 获取记录会有数量10000条的限制,如果查询文档数量大于10000,不使用san()方法便会出现异常
# 下面查询会触发异常:
# all_record = self.search(self.test_count_key)
# for record in all_record[0: 15000]:
# print(record.to_dict())
# 因为test_count_key下数量已经达到20000条,当取15000条数据时会触发:elasticsearch.exceptions.RequestError异常
# 查询id>90, 且按玩家身高排序从大到小排序
gte_90_sort = all_record.sort("-height")
# self.print_all_record("查询id>90, 且按玩家身高排序从大到小排序:", gte_90_sort, 10)
for record in gte_90_sort:
print(record.to_dict())
self.cross_line()
# 查询id>90, 且按玩家身高排序从小到大排序, 如果身高相同,则按id降序排序
gte_90_sort = all_record.filter("range", id={"gte": 90}).sort("height", "-id")
for record in gte_90_sort:
print(record.to_dict())
self.cross_line()
# 分页
# 查询用户用户数据,跳过前五十条后20条
skip_50_search_20 = all_record[50: 70]
i = 1
for record in skip_50_search_20:
print(f"第{i}条数据, 用户id:{record.to_dict()['id']}")
i += 1
if __name__ == "__main__":
search = Search()
# search.get_all_record()
# search.get_record_by_query()
# search.get_record_by_filter()
# search.get_record_by_query_and_filter()
# search.get_record_by_exclude()
search.other_search()
更新
按查询更新文档
编写执行脚本
刷新索引
创建文件study_search.py
详见示例:update_example
import time
from elasticsearch_obj import ElasticSearchObj
class Update(ElasticSearchObj):
def refresh(self, index):
self.client.indices.refresh(index=index)
@staticmethod
def cross_line():
print('=================================================')
def print_all_record(self, explain, all_record):
for record in all_record.scan():
print(explain, record.to_dict())
self.cross_line()
def update_example(self):
# 将user_key id为90记录,name改为”我是来测试的“, height增加50
# 查找user_key id为90更新前的记录
update_before = self.search(self.user_key).filter("term", id=90)
self.print_all_record("查找user_key id为90更新前的记录:", update_before)
update_obj = self.update(self.user_key).filter(
"term", id=90).script(
source="ctx._source.name=params.name;ctx._source.height+=params.height;",
params={
"name": "我是来测试的",
"height": 50
})
update_response = update_obj.execute() # 请求执行并返回执行结果
print("user_key id为90记录,name改为”我是来测试的“, height增加50 更新返回结果:", update_response)
update_after = self.search(self.user_key).filter("term", id=90)
self.print_all_record("查找user_key id为90更新后的记录1:", update_after)
time.sleep(1)
update_after = self.search(self.user_key).filter("term", id=90)
self.print_all_record("查找user_key id为90更新后的记录2:", update_after)
# 执行结果就不沾出来了,但有执行的可以看出
# 更新后记录1:是更新前的结果; 而更新后记录2:是更新后的结果
# 造成这一现象是因为上一个请求更新在内部并未完全完成,所以在sleep 一秒后便能获取更新后的记录
print(end="\n\n\n")
# 如果需要在更新后立即获取最新文档,又不知道多久能够完成更新, 可以在执行更新后刷新文档
# 看下面示例
# 将user_key 下id为70的文档,name改为”试试刷新index能否更新后获取最新数据“,height增加一百
print("user_key 下id为70的文档,name改为”试试刷新index能否更新后获取最新数据“,height增加一百")
update_before = self.search(self.user_key).filter("term", id=70)
self.print_all_record("查找user_key id为80更新前的记录:", update_before)
update_obj = self.update(self.user_key).filter(
"term", id=70).script(
source="ctx._source.name=params.name;ctx._source.height+=params.height;",
params={
"name": "试试刷新index能否更新后获取最新数据",
"height": 100
})
update_response = update_obj.execute() # 请求执行并返回执行结果
print("user_key id为70记录,name改为”试试刷新index能否更新后获取最新数据“, height增加100 更新返回结果:", update_response)
self.refresh(self.user_key) # 刷新
update_after = self.search(self.user_key).filter("term", id=70)
self.print_all_record("查找user_key id为70更新后的记录1:", update_after)
# 默认情况下,Elasticsearch 每秒都会定期刷新索引, 如果并不需要获取更新后的文档,尽量就不要手动刷新了
# 可以通过更新响应的total跟updated数量是否一致判断记录是否更新成功
# 查询更新会更新所有匹配的文档,查询条件跟上面介绍的查询用法一致
# 例如:将user_key所有age增加一岁
response = self.update(self.user_key).script(source="ctx._source.age+=1;").execute()
print("将user_key所有age增加一岁:", response["total"], response["updated"], "response=", response)
# 此处增加刷新,是因为上一个执行是更新整个user_key,如果还未自动刷新,执行下面示例,或造成并发异常,
# 导致elasticsearch.exceptions.ConflictError异常
self.refresh(self.user_key)
print(end="\n\n\n")
# 特别注意的是,如果script定义的字段,查询的文档存在则会更新,不存在则会在文档中插入字段
print("将user_key下id为1的文档增加一个字段test_field,值为:[1,2,3]")
update_before = self.search(self.user_key).filter("term", id=1)
self.print_all_record("查找user_key id为1更新前的记录:", update_before)
update_obj = self.update(self.user_key).filter(
"term", id=1).script(
source='ctx._source.test_field=params.test_field',
params={
"test_field": [1, 2, 3],
})
response = update_obj.execute()
print("将user_key下id为1的文档增加一个字段test_field:", response)
self.refresh(self.user_key) # 刷新
update_after = self.search(self.user_key).filter("term", id=1)
self.print_all_record("查找user_key 将user_key下id为1的文档增加一个字段test_field,更新后的记录:", update_after)
# 删除字段
print("将user_key下id为1的文档增加的test_field字段移除")
update_before = self.search(self.user_key).filter("term", id=1)
self.print_all_record("查找user_key id为1更新前的记录:", update_before)
response = self.update(self.user_key).filter(
"term", id=1).script(
source='ctx._source.remove("test_field")').execute()
print("将user_key下id为1的文档增加的test_field字段移除:", response)
self.refresh(self.user_key) # 刷新
update_after = self.search(self.user_key).filter("term", id=1)
self.print_all_record("将user_key下id为1的文档增加的test_field字段移除,更新后的记录:", update_after)
if __name__ == "__main__":
update = Update()
update.update_example()
删除
删除索引
根据查询条件删除文档
创建文件study_delete.py
from elasticsearch_obj import ElasticSearchObj
class StudyDelete(ElasticSearchObj):
def delete_index(self, index):
"""
https://www.elastic.co/guide/en/elasticsearch/reference/7.9/indices-delete-index.html
删除整个索引
:param index:
:return:
"""
try:
self.client.indices.delete(index=index)
except Exception:
print(f"需要删除的索引:{index}不存在")
def delete_by_query(self):
"""
示例根据查询条件删除文档
:return:
"""
# 将user_key下id大于90的玩家删除
all_record = self.search(self.user_key)
print("查看删除前文档的数量:", all_record.count())
all_record.filter("range", id={"gt": 90}).delete()
self.client.indices.refresh(index=self.user_key)
all_record = self.search(self.user_key)
print(f"查看删除后文档的数量:{all_record.count()}")
if __name__ == "__main__":
study_delete = StudyDelete()
study_delete.delete_index(study_delete.friend_key) # 删除索引friend_key
study_delete.delete_by_query()
关于Elasticsearch 计算不同的嵌套值和elasticsearch嵌套查询的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于docker 部署 elasticsearch + elasticsearch-head + elasticsearch-head 跨域问题 + IK 分词器、ElasticSearch (一) ElasticSearch 的应用场景及为什么要选择 ElasticSearch?、Elasticsearch CentOS6.5下安装ElasticSearch6.2.4+elasticsearch-head+Kibana、Elasticsearch python操作实践(elasticsearch 、Elasticsearch DSL)的相关信息,请在本站寻找。
本文标签: