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

在线体验各类最新模型,更有模型 免费Token 额度领取!
立即体验
简介: 数据库-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(小于),您的支持是我不断更新的动力。

 

相关实践学习
以电商场景为例搭建AI语义搜索应用
本实验旨在通过阿里云Elasticsearch结合阿里云搜索开发工作台AI模型服务,构建一个高效、精准的语义搜索系统,模拟电商场景,深入理解AI搜索技术原理并掌握其实现过程。
ElasticSearch 最新快速入门教程
本课程由千锋教育提供。全文搜索的需求非常大。而开源的解决办法Elasricsearch(Elastic)就是一个非常好的工具。目前是全文搜索引擎的首选。本系列教程由浅入深讲解了在CentOS7系统下如何搭建ElasticSearch,如何使用Kibana实现各种方式的搜索并详细分析了搜索的原理,最后讲解了在Java应用中如何集成ElasticSearch并实现搜索。  
相关文章
|
9月前
|
SQL 关系型数据库 数据库
Python SQLAlchemy模块:从入门到实战的数据库操作指南
免费提供Python+PyCharm编程环境,结合SQLAlchemy ORM框架详解数据库开发。涵盖连接配置、模型定义、CRUD操作、事务控制及Alembic迁移工具,以电商订单系统为例,深入讲解高并发场景下的性能优化与最佳实践,助你高效构建数据驱动应用。
996 7
|
人工智能 安全 机器人
无代码革命:10分钟打造企业专属数据库查询AI机器人
随着数字化转型加速,企业对高效智能交互解决方案的需求日益增长。阿里云AppFlow推出的AI助手产品,借助创新网页集成技术,助力企业打造专业数据库查询助手。本文详细介绍通过三步流程将AI助手转化为数据库交互工具的核心优势与操作指南,包括全场景适配、智能渲染引擎及零代码配置等三大技术突破。同时提供Web集成与企业微信集成方案,帮助企业实现便捷部署与安全管理,提升内外部用户体验。
1090 12
无代码革命:10分钟打造企业专属数据库查询AI机器人
|
12月前
|
存储 关系型数据库 MySQL
MySQL数据库索引的数据结构?
MySQL中默认使用B+tree索引,它是一种多路平衡搜索树,具有树高较低、检索速度快的特点。所有数据存储在叶子节点,非叶子节点仅作索引,且叶子节点形成双向链表,便于区间查询。
285 4
|
Cloud Native 关系型数据库 分布式数据库
|
并行计算 关系型数据库 MySQL
如何用 esProc 将数据库表转储提速查询
当数据库查询因数据量大或繁忙变慢时,可借助 esProc 将数据导出为文件进行计算,大幅提升性能。以 MySQL 的 3000 万行订单数据为例,两个典型查询分别耗时 17.69s 和 63.22s。使用 esProc 转储为二进制行存文件 (btx) 或列存文件 (ctx),结合游标过滤与并行计算,性能显著提升。例如,ctx 并行计算将原查询时间缩短至 0.566s,TopN 运算提速达 30 倍。esProc 的简洁语法和高效文件格式,特别适合历史数据的复杂分析场景。
|
SQL 关系型数据库 MySQL
如何优化SQL查询以提高数据库性能?
这篇文章以生动的比喻介绍了优化SQL查询的重要性及方法。它首先将未优化的SQL查询比作在自助餐厅贪多嚼不烂的行为,强调了只获取必要数据的必要性。接着,文章详细讲解了四种优化策略:**精简选择**(避免使用`SELECT *`)、**专业筛选**(利用`WHERE`缩小范围)、**高效联接**(索引和限制数据量)以及**使用索引**(加速搜索)。此外,还探讨了如何避免N+1查询问题、使用分页限制结果、理解执行计划以及定期维护数据库健康。通过这些技巧,可以显著提升数据库性能,让查询更高效流畅。
|
存储 算法 关系型数据库
数据库主键与索引详解
本文介绍了主键与索引的核心特性及其区别。主键具有唯一标识、数量限制、存储类型和自动排序等特点,用于确保数据完整性和提升查询效率;而索引通过特殊数据结构(如B+树、哈希)优化查询速度,适用于不同场景。文章分析了主键与索引的优劣、适用场景及工作原理,并对比两者在唯一性、数量限制、功能定位等方面的差异,为数据库设计提供指导。
|
安全 Java Linux
Linux安装Elasticsearch详细教程
Linux安装Elasticsearch详细教程
2344 64
|
JSON 安全 数据可视化
Elasticsearch(es)在Windows系统上的安装与部署(含Kibana)
Kibana 是 Elastic Stack(原 ELK Stack)中的核心数据可视化工具,主要与 Elasticsearch 配合使用,提供强大的数据探索、分析和展示功能。elasticsearch安装在windows上一般是zip文件,解压到对应目录。文件,elasticsearch8.x以上版本是自动开启安全认证的。kibana安装在windows上一般是zip文件,解压到对应目录。elasticsearch的默认端口是9200,访问。默认用户是elastic,密码需要重置。
6506 0

热门文章

最新文章