数据库-ElasticSearch入门(索引、文档、查询)

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 数据库-ElasticSearch入门(索引、文档、查询)



前面文章,安装了ES,请再安装chrome插件elasticsearch-head。由于需要发送http的请求,可以安装postman,当然,你用其他命令行工具也可以,另外,如果不了解HTTP协议、RestFul,Json格式可以自行补充一下。

ES启动与可视化

双击elasticsearch.bat即可,之后会检查环境,加载模块,打开端口等

启动图

注意安装好jdk(自带jdk,自己装的话推荐1.8+),9300是内部组件通信端口,9200是访问端口。

可视化

打开浏览器插件可以看到信息,跟着博主下面操作的话可以时常看看可视化插件,我就不再截图了。

索引

类似关系型数据库中的“数据库”这一概念

倒排索引

正排(正向)索引:根据id去寻找内容,例如Mysql

正排索引示例

id words
1 hi, l am lady killer 9
2 hello, i like young lady

我们易于根据id去查询内容,但当查询lady是否存在时,却抛弃了索引,全表查询,即正排索引不利于全文检索,尤其是模糊查询时(Lady,LADY这种非完全匹配)。

倒排索引就是来解决这个问题的,通过分词,权重等来快速检索

倒排索引

words id
lady 1,2
killer 1

后序就不再画了,通过这种方式更加快速全文搜索。

创建

http://ip:9200/index_name,注意使用幂等PUT,POST会显示错误如下。

使用POST

使用PUT

使用PUT创建索引

创建后结果如下:

结果

查询

单个索引

http://ip:9200/index_name,使用GET方法

获取索引

所有索引

http://ip:9200/_cat/indices?v,使用GET方法,其中,参数v是为了显示更详细

创建索引killer后,可以看到如下结果

所有索引

删除

和创建时的url一致,只需要使用DELETE方法删除即可。

删除索引killer

文档

类似关系型数据库中的表数据

创建

http://ip:9200/index_name/_doc/[_id],使用方法POST需要有请求体,JSON格式。

创建文档

可以看到,生成了一个随机的_id,即同样的请求,返回不一致,由于PUT是幂等的,所以也就只能用POST。当指定_id时,可以使用POST。

指定_id创建文档

查询

主键查询

和创建时的地址一致,需要指定_id,方法改为GET即可

查询单个数据

搜索所有文档

http://ip:9200/index_name/_search,方法仍然使用GET

获取索引的所有文档

条件查询

http://ip:9200/index_name/_search?q=key:value,方法使用GET

单条件查询

请求体方式:不在url中使用参数,而是请求体,这种方式更常见,更安全。

请求体查询

分页查询

在上面的基础上,添加from和size,代表从哪条数据开始查询和每页显示的条数

from=(pagenum-1)*size,查询第一页的数据,就是(1-1)*2,即从第0条数据开始查,显示2条

查询之前,我添加了两条数据

{
    "name":"leilei",
    "type":"friend",
    "age":20
}
{
    "name":"jiajia",
    "type":"friend",
    "age":20
}

条件是"type":"friend",结果如下

结果如下

排序

在查询的基础上,添加sort字段,里面再添加要排序的字段,选择升序还是降序可以再嵌套order

排序

多条件查询

稍微复杂一些,bool里面嵌套must或should,类似and或or,,must not 类似not,看下面的请求体

{
    "query":{
        "bool":{
            "must":[
                {
                    "match":{
                        "age":18
                    }
                },
                {
                    "match":{
                        "type":"girlfriend"
                    }
                }
            ]
        }
    }
}

这样两个match必须全部匹配到即可。类似京东选择游戏笔记本,又选择处理器是i7。

多条件查询must

使用should匹配girlfriend和20时,就能找到多个。

多条件查询should

范围查询

使用filter,gt表示大于,lt表示小于。放到bool里面,和must/must not/should并列。

"filter":{
                "range":{
                    "age":{
                        "lt":19
                    }
                }
            }

age>19的结果

完全匹配

前面使用的match是全文匹配,也就是进行了分词,不完全一致时也会匹配到

自带的分词器对于拼音的分词不太好,加了两条中文的

查询小贝结果如下:

小贝查询到宝贝、贝贝

这就类似于你在京东查询一个商品,可能没有一样的,但是并不是显示没有,而是显示类似的

使用match_phrase可以进行完全匹配查询

完全匹配小贝没有结果

高亮查询

添加highlight

高亮部分添加了em标签

聚合查询

使用aggs,表示聚合操作,嵌套分组terms,添加分组字段

聚合查询

可以看到19 20 18岁的doc数量

映射

将字段映射为关键字或文本类型,关键字不可拆分,设置index为false时不可拆分。

添加索引killer,给killer添加映射,http:///ip:9200/index_name/_mapping,方法使用PUT

{
    "properties":{
        "name":{
            "type":"keyword",
            "index":true
        },
        "hobby":{
            "type":"text",
            "index":true
        }
    }
}

添加映射

名字是关键字,不可拆分,爱好是文本,可以拆分。

添加两个文档

{
    "name":"弗兰克",
    "hobby":"枪杀"
}
{
    "name":"弗兰克林",
    "hobby":"捧杀"
}

按名字查询

按爱好查询

可以看到名字作为关键字,必须一样才能查到,爱好却能查到类似的

修改

全量修改

http://ip:9200/index_name/_doc/_id,使用PUT方法,添加请求体。

全量修改

可以看到上面数据没有全部改动,大部分情况下还是部分修改的。

局部修改

http://ip:9200/index_name/_update/_id,方法为POST,请求体使用doc字段嵌套修改内容,见下图。

部分修改

删除

http://ip:9200/index_name/_doc/_id,方法使用DELETE

删除文档

Python API

又支持异步的版本和不支持异步的,这里就使用简单的不支持异步的

安装与导入

pip install elasticsearch==7.10
from elasticsearch import Elasticsearch

包内容

项目结构

使用单元测试对API进行简单测试。后续仅展示esclient里面的函数即test_函数

初始化

def __init__(self, host="127.0.0.1", port: int = 9200):
        self._client = Elasticsearch(host=host, port=port)

参数

host: es的ip

port: es的端口

测试代码

es = Elasticsearch()

索引

创建

def index_create(self, index_name: str, map=None):
        if map is None:
            map = {}
        res = self._client.index(index=index_name, body=map)
        return res

参数

index:索引名

body:请求体

测试代码

def test_index_create(self):
        res = es.index_create("lady1")
        print(res)
        res = es.index_create("heros", map={
            "mapping": {
                "doc": {
                    "properties": {
                        "name": {
                            "type": "text",
                            "index": True
                        },
                        "age": {
                            "type": "keyword",
                            "index": True
                        },
                        "role": {
                            "type": "keyword",
                            "index": True
                        }
                    }
                }
            }
        })
        print(res)

结果

使用wireshark抓包

可以看到是一个POST包,使用的是json格式,body是空的

这个是有body的,但是映射貌似也不对,没有向_mapping发送,后面我们自己发送一个PUT数据包

创建映射

测试代码

def test_mapping(self):
        import requests
        import json
        url_put = "http://127.0.0.1:9200/heros/_mapping"
        headers_put = {
            'Content-Type': "application/json"
        }
        param ={
            "properties": {
                "name": {
                    "type": "text",
                    "index": True
                },
                "role": {
                    "type": "keyword",
                    "index": True
                }
            }
        }
        payload = json.dumps(param)
        response_put = requests.put(url_put, data=payload, headers=headers_put)
        print(response_put.text)

测试结果

之后就不再展示Wireshark抓包结果了

删除索引

def index_delete(self, index_name: str):
        res = self._client.indices.delete(index=index_name)
        return res

参数

index_name:索引的名字

测试代码

def test_index_delete(self):
        res = es.index_delete(index_name="lady1")
        print(res)

结果

查询

单个索引

def index_get(self, index_name: str):
        res = self._client.indices.get(index=index_name)
        return res

参数

index_name:索引的名字

测试代码

def test_index_get(self):
        res = es.index_get("heros")
        print(res)

结果

文档

创建

def doc_create(self, index_name, body, id_):
        res = self._client.create(index=index_name, body=body, id=id_)
        return res

参数

index_name:索引的名字

body:请求体

id_:文档的id

测试代码

def test_doc_create(self):
        zhaoyun = {
            "name": "赵云",
            "age": 25,
            "role": "打野"
        }
        yunzhongjun = {
            "name": "云中君",
            "age": 25,
            "role": "打野"
        }
        yao = {
            "name": "瑶",
            "age": 16,
            "role": "辅助"
        }
        sunshangxiang = {
            "name": "孙尚香",
            "age": 18,
            "role": "射手"
        }
        liubei = {
            "name": "刘备",
            "age": 30,
            "role": "打野"
        }
        heros = [zhaoyun, yunzhongjun, yao, sunshangxiang, liubei]
        init_id = 1000
        for h in heros:
            res = es.doc_create("heros", h, str(init_id))
            init_id += 1
            print(res)

结果

删除

def doc_delete(self, index_name, doc_id):
        res = self._client.delete(index=index_name, id=doc_id)
        return res

参数

index_name:索引的名字

doc_id:文档的id

一共就这几个数据,我就不删除了

修改

def doc_update(self, index_name, doc_id, doc):
        res = self._client.update(index=index_name, id=doc_id, body=doc)
        return res

参数

index_name:索引的名字

doc_id:文档的id

doc:文档

测试代码

def test_doc_update(self):
        sun = {
            "doc": {
                "age": 21
            }
        }
        res = es.doc_update("heros", "1002", sun)
        print(res["result"])

结果

查询

查询所有

def doc_get__all(self, index_name):
        res = self._client.search(index=index_name)
        return res['hits']['hits']

参数

index_name:索引的名字

这里仅返回hit到的json对象列表

测试代码

def test_doc_get_all(self):
        res = es.doc_get__all("heros")
        for hit in res:
            print(hit["_source"])

结果

根据id查询

def doc_get_id(self, index_name, id_):
        res = self._client.get(index=index_name, id=id_)
        return res["_source"]

参数

index_name:索引的名字

id_:文档的id

测试代码

def test_doc_get_id(self):
        res = es.doc_get_id("heros", "1002")
        print(res)

结果

根据条件查询

def doc_get_condition(self, index_name, con):
        res = self._client.search(index=index_name, body=con)
        return res['hits']['hits']

参数

index_name:索引的名字

con:查询的请求体,即条件

单个条件

测试代码

def test_doc_get_con_1(self):
        name = {
            "name": "小云"
        }
        con = {
            "query": {
            }
        }
        con["query"]["match"] = name
        res = es.doc_get_condition("heros", con)
        for hit in res:
            print(hit["_source"])

结果

因为name在前面设置映射时,设置为了text,所以即使不完全匹配也会有类似的结果。

分页查询

测试代码

def test_doc_get_page(self):
        page_num = 2
        size = 3
        con = {
            "from": (page_num - 1) * size,
            "size": size
        }
        res = es.doc_get_condition("heros", con)
        for hit in res:
            print(hit["_source"])

结果

对结果排序

测试代码

def test_doc_get_sort(self):
        page_num = 1
        size = 3
        field = "age"
        order = "desc"
        con = {
            "from": (page_num - 1) * size,
            "size": size,
            "sort": {
                field: {
                    "order": order
                }
            }
        }
        res = es.doc_get_condition("heros", con)
        for hit in res:
            print(hit["_source"])

结果

多个条件查询

测试代码

def test_doc_get_con_more(self):
        eighteen_match = {
            "match": {
                "age": "18"
            }
        }
        daye_match = {
            "match": {
                "role": "打野"
            }
        }
        con = {
            "query": {
                "bool": {
                    "must_not": []
                }
            }
        }
        con["query"]["bool"]["must_not"].append(eighteen_match)
        con["query"]["bool"]["must_not"].append(daye_match)
        res = es.doc_get_condition("heros", con)
        for hit in res:
            print(hit["_source"])

结果

范围查询

测试代码

def test_doc_get_scope(self):
        filter = {
            "range": {
                "age": {
                    "gt": 19
                }
            }
        }
        con = {
            "query": {
                "bool": {
                    "filter": filter
                }
            }
        }
        res = es.doc_get_condition("heros", con)
        for hit in res:
            print(hit["_source"])

结果

完全匹配

测试代码

def test_doc_get_phrase(self):
        name = {
            "name": "赵云"
        }
        con = {
            "query": {
            }
        }
        con["query"]["match_phrase"] = name
        res = es.doc_get_condition("heros", con)
        for hit in res:
            print(hit["_source"])

结果

高亮查询

测试代码

def test_doc_get_highlight(self):
        name = {
            "name": "云"
        }
        con = {
            "query": {
            },
            "highlight": {
                "fields": {
                    "name": {}
                }
            }
        }
        con["query"]["match"] = name
        res = es.doc_get_condition("heros", con)
        for hit in res:
            print(hit["highlight"])

结果

聚合查询

def doc_get__agg(self, index_name, con):
        res = self._client.search(index=index_name, body=con)
        return res['aggregations']

参数

index: 索引的名字

body:请求体,即聚合的字段

测试代码

def test_doc_get_aggs(self):
        con = {
            "aggs": {
                "role_groups": {
                    "terms": {
                        "field": "role"
                    }
                }
            },
        }
        res = es.doc_get__agg("heros", con)
        for cnt in res["role_groups"]["buckets"]:
            print(cnt["key"], " ", cnt["doc_count"])

结果

参考

Postman

网络-http协议学习笔记(消息结构、请求方法、状态码等)_lady_killer9的博客-CSDN博客

Quick start | Elasticsearch Guide [7.15] | Elastic

Elasticsearch Python Client [7.16] | Elastic

Python Elasticsearch Client — Elasticsearch 8.0.0 documentation

Elasticsearch: 权威指南 | Elastic


更多ELK相关内容:数据库-ElasticSearch学习笔记_lady_killer9的博客-CSDN博客

喜欢本文的请动动小手点个赞,收藏一下,有问题请下方评论,转载请注明出处,并附有原文链接,谢谢!

如有侵权,请及时联系。如果您感觉有所收获,自愿打赏,可选择支付宝18833895206(小于),您的支持是我不断更新的动力。

 

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
14天前
|
存储 缓存 固态存储
怎么让数据库查询更快
【10月更文挑战第28天】
24 2
|
15天前
|
存储 缓存 关系型数据库
怎么让数据库查询更快
【10月更文挑战第25天】通过以上综合的方法,可以有效地提高数据库查询的速度,提升应用程序的性能和响应速度。但在优化过程中,需要根据具体的数据库系统、应用场景和数据特点进行合理的调整和测试,以找到最适合的优化方案。
|
15天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
77 1
|
17天前
|
存储 关系型数据库 MySQL
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
191 2
|
16天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第26天】数据库作为现代应用系统的核心组件,其性能优化至关重要。本文主要探讨MySQL的索引策略与查询性能调优。通过合理创建索引(如B-Tree、复合索引)和优化查询语句(如使用EXPLAIN、优化分页查询),可以显著提升数据库的响应速度和稳定性。实践中还需定期审查慢查询日志,持续优化性能。
47 0
|
7天前
|
存储 安全 数据管理
如何在 Rocky Linux 8 上安装和配置 Elasticsearch
本文详细介绍了在 Rocky Linux 8 上安装和配置 Elasticsearch 的步骤,包括添加仓库、安装 Elasticsearch、配置文件修改、设置内存和文件描述符、启动和验证 Elasticsearch,以及常见问题的解决方法。通过这些步骤,你可以快速搭建起这个强大的分布式搜索和分析引擎。
20 5
|
1月前
|
存储 JSON Java
elasticsearch学习一:了解 ES,版本之间的对应。安装elasticsearch,kibana,head插件、elasticsearch-ik分词器。
这篇文章是关于Elasticsearch的学习指南,包括了解Elasticsearch、版本对应、安装运行Elasticsearch和Kibana、安装head插件和elasticsearch-ik分词器的步骤。
109 0
elasticsearch学习一:了解 ES,版本之间的对应。安装elasticsearch,kibana,head插件、elasticsearch-ik分词器。
|
2月前
|
NoSQL 关系型数据库 Redis
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
mall在linux环境下的部署(基于Docker容器),docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongodb、minio详细教程,拉取镜像、运行容器
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
|
3月前
|
数据可视化 Docker 容器
一文教会你如何通过Docker安装elasticsearch和kibana 【详细过程+图解】
这篇文章提供了通过Docker安装Elasticsearch和Kibana的详细过程和图解,包括下载镜像、创建和启动容器、处理可能遇到的启动失败情况(如权限不足和配置文件错误)、测试Elasticsearch和Kibana的连接,以及解决空间不足的问题。文章还特别指出了配置文件中空格的重要性以及环境变量中字母大小写的问题。
一文教会你如何通过Docker安装elasticsearch和kibana 【详细过程+图解】
|
3月前
|
JSON 自然语言处理 数据库
Elasticsearch从入门到项目部署 安装 分词器 索引库操作
这篇文章详细介绍了Elasticsearch的基本概念、倒排索引原理、安装部署、IK分词器的使用,以及如何在Elasticsearch中进行索引库的CRUD操作,旨在帮助读者从入门到项目部署全面掌握Elasticsearch的使用。