Elasticsearch 的存储与查询

Elasticsearch 的存储与查询

在搜索系统领域,数据的存储与查询是两个最基础且至关重要的环节。Elasticsearch(ES) 在这两方面进行了深度优化,使其在关系型数据库或非关系型数据库中脱颖而出,成为搜索系统的首选。

映射 (Mapping)

  • 映射 (Mapping)
    • 映射是 ES 中的一种元数据,用于描述文档中的数据结构和类型。映射可以在创建索引时自动推断,也可以手动定义。映射包括字段名、字段类型、是否可搜索、是否可分析等属性。映射可以在文档级别和索引级别定义。
    • ES 中是实现了动态映射的,在索引中写入下面的一个文档。
{"name":"jack","age":18,"birthDate": "1991-10-05"
}
  • 在动态映射的作用下,name 会映射成 text 类型,age 会映射成 long 类型,birthDate 会被映射为 date 类型,自动判断的规则如下

    • JSON TypeField Type
      true, falseboolean
      123, 456, 876long
      123.43, 234.534double
      String, “2022-05-15”date
      String: “Hello Elasticsearch”string
      符合 IPv4 或 IPv6 地址格式ip
      字段的内容是 base64 编码的字符串binary
      字段的内容是一个数组,数组中的每个元素都将根据其内容被映射为相应的类型array
      字段的内容是一个 JSON 对象,那么它将被映射为 object 类型。对象中的每个属性都将根据其内容被映射为相应的类型object
      字段的内容是一个数组,且数组中的元素是对象,并且可以对内部对象进行精确查询nested
      字段的内容是经纬度对geo_point
      字段的内容是除点外的任意几何形状坐标geo_shape
  • Mapping 的字段类型

    • 字段类型是映射中的一种属性,用于描述文档中的字段数据类型。ES 支持多种字段类型,如文本、数值、日期、布尔值等。每种字段类型有其特点和限制,因此选择合适的字段类型对于优化查询性能和存储空间至关重要。
    • 一级分类二级分类具体类型
      核心类型字符串类型string,text,keyword
      整数类型integer,long,short,byte
      浮点类型double,float,half_float,scaled_float
      逻辑类型boolean
      日期类型date
      范围类型range(Integer_range,long_range,date_range…)
      二进制类型binary (BASE64 的二进制)
      复合类型数组类型array
      对象类型object
      嵌套类型nested
      地理类型地理坐标类型geo_point
      地理地图geo_shape
      特殊类型IP 类型ip
  • 字符串类型

    • text: ES 5x 后不再支持 string, 由 textkeyword 类型替代
      • 子类型
        • text: 类型适用于需要被全文检索的字段
        • match_only_text: 是 text 的空间优化变体,它禁用评分,它适合为日志消息建立索引
      • text 类型的 常用参数
        • analyzer: 指明该字段用于索引时和搜索时的分析字符串的分词器 (使用 search_analyzer 可覆盖它)。 默认为索引分析器或标准分词器
        • search_analyzer: 在搜索时,用于分析该字段的分析器,默认是 analyzer 参数的值
        • boost: 查询时字段匹配上时的权重级别,接受浮点数,默认为 1.0
        • fields: 它允许同一个字符串值以多种方式进行索引以满足不同的目的
        • index: 设置该字段是否可以用于搜索,默认为 true
        • eager_global_ordinals: 在刷新时急切地加载全局序数,对于经常用于 term 聚合的字段,启用此功能是个好主意 (但会影响写入速度)
        • fielddata: 指明该字段是否可以使用内存中的 fielddata 进行排序,聚合或脚本编写?该字段可能会消耗大量的内存,如果要用的话建议 keyword 类型的字段使用
        • similarity: 设置相关性排序公式,默认为 BM25
    • keyword
      • 子类型
        • keyword: 用于结构化过的内容,只能用于精准搜索,不会进行分词处理,常用户 ID、Email 等
        • constant_keyword: 某个字段为 constant_keyword 类型,则该索引中,所有文档的该字段的值必须一致,常用于版本号
        • wildcard: 这种类型主要用于非结构化的机器生成内容,对大数据量的字段做了优化,支持模糊匹配,常用于日志服务
      • keyword 类型的 常用参数
        • ignore_above: 当字段文本的长度大于指定值时,不会被索引,但是会存储
        • 其它参数: 同 text

## fields 字段示例
{"properties": {"title": {"type": "text","analyzer": "ik_max_word","search_analyzer": "ik_smart","similarity": "custom_similarity","doc_values": false,"fields": {"title_smart": {"type": "text","analyzer": "ik_smart","search_analyzer": "ik_smart","similarity": "custom_similarity","doc_values": false}}}}
}# 自定义排序算法
"similarity": {"custom_similarity": {"type": "BM25","b": 0.9,"k1": 1.2}
}
  • 数字类型

    • TypeDescription
      longA signed 64-bit integer with a minimum value of -263 and a maximum value of 263-1.
      integerA signed 32-bit integer with a minimum value of -231 and a maximum value of 231-1.
      shortA signed 16-bit integer with a minimum value of -32,768 and a maximum value of 32,767.
      byteA signed 8-bit integer with a minimum value of -128 and a maximum value of 127.
      doubleA double-precision 64-bit IEEE 754 floating point number, restricted to finite values.
      floatA single-precision 32-bit IEEE 754 floating point number, restricted to finite values.
      half_floatA half-precision 16-bit IEEE 754 floating point number, restricted to finite values.
      scaled_floatA floating point number that is backed by a long, scaled by a fixed double scaling factor.
      unsigned_longAn unsigned 64-bit integer with a minimum value of 0 and a maximum value of 264-1.
  • 范围类型

    • integer_rangeinteger 类型的区别在于,如果你的字段只包含一个整数值,你可以使用 integer 类型。如果你的字段包含一个整数范围,你可以使用 integer_range 类型
    • Range TypeDescription
      integer_rangeA range of signed 32-bit integers with a minimum value of -231 and maximum of 231-1.
      float_rangeA range of single-precision 32-bit IEEE 754 floating point values.
      long_rangeA range of signed 64-bit integers with a minimum value of -263 and maximum of 263-1.
      double_rangeA range of double-precision 64-bit IEEE 754 floating point values.
      date_rangeA range of date values. Date ranges support various date formats through the format mapping parameter. Regardless of the format used, date values are parsed into an unsigned 64-bit integer representing milliseconds since the Unix epoch in UTC. Values containing the now date math expression are not supported.
      ip_rangeA range of ip values supporting either IPv4 or IPv6 (or mixed) addresses.
# integer 存储例子
{"name": "John","age": 25
}# integer_range 存储例子
{"name": "John","age": {"gte": 20,"lte": 30}
}# 若用 keyword 类型定义 my_field, 则范围查询会变成"字符串比较"而非"数值比较"
GET /keyword_test/_search
{"query": {"range": {"my_field": {"gte": 21,"lt": 32}}}
}"hits" : [{"_index" : "keyword_test","_type" : "_doc","_id" : "1","_score" : 1.0,"_source" : {"my_field" : "3"}}
]
  • 对象类型
    • 对象类型即一个 JSON 对象,JSON 字符串允许嵌套对象,所以一个文档可以嵌套多个多层对象。但 Lucene 没有内部对象的概念,会将 JSON 文档扁平化
# 插入这个的一个文档
PUT my-index-000001/_doc/1
{"region": "US","manager": {"age":     30,"name": {"first": "John","last":  "Smith"}}
}# 实际上该文档会被存储成 key-value 对的形式
{"region":             "US","manager.age":        30,"manager.name.first": "John","manager.name.last":  "Smith"
}# 该文档会被动态的 mapping
{"mappings": {"properties": {"region": {"type": "keyword"},"manager": {"properties": {"age":  { "type": "integer" },"name": {"properties": {"first": { "type": "text" },"last":  { "type": "text" }}}}}}}
}# 在搜索时
{"query": {"bool": {"must": [{"match": {"manager.name.first": "John"}}]}}
}
  • 嵌套类型
    • nested 是一种特殊类型的 object 类型,它可以以数组对象的形式来进行索引,并且可以独立的查询其中的每一个对象

# ES 是没有内部对象的概念的,下述例子会动态的转化成一个"扁平化"的对象
{"group" : "fans","user" : [{"first" : "John","last" :  "Smith"},{"first" : "Alice","last" :  "White"}]
}# 类似下述的方式存储
{"group" :        "fans","user.first" : [ "alice", "john" ],"user.last" :  [ "smith", "white" ]
}# 执行下述 query 会得到不正确的结果,因为对象失去了层级结构
{"query": {"bool": {"must": [{ "match": { "user.first": "Alice" }},{ "match": { "user.last":  "Smith" }}]}}
}# 以嵌套类型来定义字段
{"mappings": {"properties": {"user": {"type": "nested"}}}
}# 插入相同的 doc
{"group" : "fans","user" : [{"first" : "John","last" :  "Smith"},{"first" : "Alice","last" :  "White"}]
}# 以 nested 的方式进行检索,无结果返回
{"query": {"nested": {"path": "user","query": {"bool": {"must": [{ "match": { "user.first": "Alice" }},{ "match": { "user.last":  "Smith" }}]}}}}
}# 在 ES 中,嵌套类型的字段会被转化成独立的文档,这些文档和主文档有相同的 id
  • 向量类型
    • 支持最大不超过 2048 维的向量,dense_vector 字段不支持查询、排序和聚合,只能接受 scripts 定义的函数
# 定义向量类型和维度
{"mappings": {"properties": {"my_vector": {"type": "dense_vector","dims": 768}}}
}# 定义相似度函数
{
"query": {"bool": {"must": {"function_score": {"functions": [{"script_score": {"script": {"source": "cosineSimilarity(params.queryVector, 'TitleVector') + 2.0","params": {"queryVector": query_embedding}}}}]}}}},
}

查询

  • 分析器
    • 被分析的字符串片段通过 analyzer 来传递,将字符串转换为一串 terms(词条) 用于索引及检索
    • 分析器 analyzer 和分词器 tokenizer 并不相同,分析器不等于分词器,分词器只是分析器的一部分
    • analyzer = [char_filter] + tokenizer + [token filter]
      • char filter: 对输入字符进行预处理,如去除 HTML 标签,ES 内置字符处理器
      • tokenizer: 对文本进行分词操作,如按照空格分词 (whitespace),标注分词器 (standard) 等,ES 内置分词器
        • standard: Elasticsearch 默认的分词器,它会根据空格和标点符号将文本拆分为 term, 会过滤掉标点符号,大写转小写
        • simple: 会根据非字母字符将文本拆分为 term, 过滤数字和标点符号,大写转小写
        • whitespace: 根据空格字符将文本拆分为 term, 不会进行过滤和大小写转换
        • keyword: 不会对文本进行拆分,常用于关键字字段或精确匹配字段
      • filter (token filter): 对 token 集合的元素做过滤和转换,如统一转小写、过滤停用词等,token 经过 filter 处理之后的结果被定义为:term, ES 内置 token filter
POST _analyze
{"analyzer": "simple","text": ["HI 111 , 哈哈"]
}# 分词结果
{"tokens" : [{"token" : "hi","start_offset" : 0,"end_offset" : 2,"type" : "word","position" : 0},{"token" : "哈哈","start_offset" : 9,"end_offset" : 11,"type" : "word","position" : 1}]
}
  • match 查询
    • 支持全文搜索和精确查询,取决于字段是否支持全文检索
    • operator 默认情况下该操作符是 or, 我们可以将它修改成 and 让所有指定词项都必须匹配
    • minimum_should_match 最小匹配参数,可以指定必须匹配的词项数 (或者百分数) 来表示一个文档是否相关
# 全文搜索
GET job_item_profile/_search
{"query": {"match": {"job_name": "java 工程师"}}
}# 精确查询
# 对于精确值的查询,可以使用 filter 语句来取代 query,因为 filter 将会被缓存
GET job_item_profile/_search
{"query": {"match": {"edu_level": "5000"}}
}# operator
GET job_item_profile/_search
{"query": {"match": {"job_name": {"query": "java 工程师","operator": "and"}}}
}# minimum_should_match
GET job_item_profile/_search
{"query": {"match": {"job_name": {"query": "java 工程师","minimum_should_match": "2"}}}
}
  • multi_match 查询
    • 多字段查询,可以给不同的字段指定不同的权重,返回匹配更高的结果
GET job_item_profile/_search
{"query": {"multi_match": {"query": "red","fields": ["job_name^2.0", "company_name^1.0"]}}
}
  • range 查询
    • 范围查询操作符:gt (大于), gte(大于等于), lt(小于), lte(小于等于)
GET job_item_profile/_search
{"query": {"range": {"salary_max": {"gt": 4,"lt": 8}}}
}
  • term 查询

    • term 查询会去倒排索引中寻找确切的 term, 它并不会走分词器,只会去配倒排索引,若某个字段的 typetext, 若用 term 去查询有可能出现查询不到的情况
    • term 查询也不会处理大小写,typetext 的字段会调用分词器进行大小写转换
  • terms 查询

    • terms 查询与 term 查询一样,但它允许你指定多值进行匹配,如果这个字段包含了指定值中的任何一个值,那么这个文档就满足条件
GET job_item_profile/_search
{"query": {"terms": {"edu_level": [5000, 6000]}}
}
  • match_phrase
    • 短语查询/精确匹配,查询"java 专家"会匹配 job_name 字段包含"java 专家"短语的,而不会进行分词查询,也不会查询出"java 技术专家"这种词汇
GET job_item_profile/_search
{"query": {"match_phrase": {"job_name": "java 专家"}}
}
  • 复合查询
    • 使用 bool 语句实现复合查询,包括 must, must_not, should 和 filter
    • must: 表示文档一定要包含查询的内容
    • must_not: 表示文档一定不要包含查询的内容
    • should: 表示如果文档匹配上可以增加文档相关性得分
    • query DSL: 结构化查询,用于检查内容与条件是否匹配,内容查询中使用的 bool 和 match 语句,用于计算每个文档的匹配得分
    • filter DSL: 结构化过滤,只是简单的决定文档是否匹配,内容过滤中使用的 term 和 range 语句,会过滤掉不匹配的文档,并且不影响计算文档匹配得分,使用过滤查询会被 ES 自动缓存用来提高效率
    • 原则上来说,使用结构化查询语句做全文本搜索或其他需要进行相关性评分的情况,剩下的全部用过滤语句

实践

  • 列表字段如何处理
    • text
      • 纯中文 逗号分隔,simple
      • 纯英文,可能包含下划线,空格分隔,standard
      • 纯数字,空格分隔,standard
    • array, 通用方案,type=keyword, double. 注意,手动转小写。
  • IK 分析器的使用方式
    • 网上很多文章会建议,建立索引的时候使用 ik_max_word 模式;搜索的时候使用 ik_smart 模式。但在实际应用中,我们会发现 ik_smart 的结果并不完全是 ik_max_word 结果的子集,这样会出现搜不出的情况 参考: IK分词器实现原理剖析 —— 一个小问题引发的思考
    • 一种解决方法如下所示,对 title 字段分别以 ik_max_word 方式建立 title 字段,再以 ik_smart 方式建立 title_smart 子字段;在用户搜索时统一使用 ik_smart 方式进行搜索,这样能保证相关的 query 一定能命中索引
  {"properties": {"title": {"type": "text","analyzer": "ik_max_word","search_analyzer": "ik_smart","similarity": "custom_similarity","doc_values": false,"fields": {"title_smart": {"type": "text","analyzer": "ik_smart","search_analyzer": "ik_smart","similarity": "custom_similarity","doc_values": false}}}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/483133.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【ONE·基础算法 || 动态规划(三)】

总言 主要内容:编程题举例,熟悉理解动态规划类题型(回文串问题、两个数组的 dp问题)。                文章目录 总言7、回文串问题7.1、 回文子串(medium)7.1.1、题解 7.2、 最长回文子串&#…

Python 3 教程第33篇(MySQL - mysql-connector 驱动)

Python MySQL - mysql-connector 驱动 MySQL 是最流行的关系型数据库管理系统,如果你不熟悉 MySQL,可以阅读我们的 MySQL 教程。 本章节我们为大家介绍使用 mysql-connector 来连接使用 MySQL, mysql-connector 是 MySQL 官方提供的驱动器。…

LLM*:路径规划的大型语言模型增强增量启发式搜索

路径规划是机器人技术和自主导航中的一个基本科学问题,需要从起点到目的地推导出有效的路线,同时避开障碍物。A* 及其变体等传统算法能够确保路径有效性,但随着状态空间的增长,计算和内存效率会严重降低。相反,大型语言…

【Db First】.NET开源 ORM 框架 SqlSugar 系列

.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…

企业品牌曝光的新策略:短视频矩阵系统

企业品牌曝光的新策略:短视频矩阵系统 在当今数字化时代,短视频已经渗透到我们的日常生活之中,成为连接品牌与消费者的关键渠道。然而,随着平台于7月20日全面下线了短视频矩阵的官方接口,许多依赖于此接口的小公司和内…

006 MATLAB编程基础

01 M文件 MATLAB输入命令有两种方法: 一是在MATLAB主窗口逐行输入命令,每个命令之间用分号或逗号分隔,每行可包含多个命令。 二是将命令组织成一个命令语句文集,使用扩展名“.m”,称为M文件。它由一系列的命令和语句…

Java基于SpringBoot+Vue的IT技术交流和分享平台(附源码+lw+部署)

博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…

【计算机网络】实验3:集线器和交换器的区别及交换器的自学习算法

实验 3:集线器和交换器的区别及交换器的自学习算法 一、 实验目的 加深对集线器和交换器的区别的理解。 了解交换器的自学习算法。 二、 实验环境 • Cisco Packet Tracer 模拟器 三、 实验内容 1、熟悉集线器和交换器的区别 (1) 第一步:构建网络…

UICollectionView在xcode16编译闪退问题

使用xcode15运行工程,控制台会出现如下提示: Expected dequeued view to be returned to the collection view in preparation for display. When the collection views data source is asked to provide a view for a given index path, ensure that a …

Proteus8.17下载安装教程

Proteus是一款嵌入式系统仿真开发软件,实现了从原理图设计、单片机编程、系统仿真到PCB设计,真正实现了从概念到产品的完整设计,其处理器模型支持8051、HC11、PIC10/12/16/18/24/30/DsPIC33、AVR、ARM、8086和MSP430等,能够帮助用…

Vue教程|搭建vue项目|Vue-CLI2.x 模板脚手架

一、项目构建环境准备 在构建Vue项目之前,需要搭建Node环境以及Vue-CLI脚手架,由于本篇文章为上一篇文章的补充,也是为了给大家分享更为完整的搭建vue项目方式,所以环境准备部分采用Vue教程|搭建vue项目|V…

一款支持80+语言,包括:拉丁文、中文、阿拉伯文、梵文等开源OCR库

大家好,今天给大家分享一个基于PyTorch的OCR库EasyOCR,它允许开发者通过简单的API调用来读取图片中的文本,无需复杂的模型训练过程。 项目介绍 EasyOCR 是一个基于Python的开源项目,它提供了一个简单易用的光学字符识别&#xff…

cocotb pytest

打印python中的print , 应该使用 pytest -s

【C++】STL——map和set

目录 1、序列式容器和关联式容器前 2、set 2.1 set类的介绍 2.2 set的构造和迭代器 2.3 set的增删查 set 的插入 set的查找 set的删除 2.4 multiset和set的差异 3、map 3 .1 pair类型 3.2 map的构造 3.3 map的增删查 map的构造遍历 map的插入 map的删除 map的查…

java基础概念46-数据结构1

一、引入 List集合的三种实现类使用了不同的数据结构! 二、数据结构的定义 三、常见的数据结构 3-1、栈 特点:先进后出,后进先出。 java内存容器: 3-2、队列 特点:先进先出、后进后出。 栈VS队列-小结 3-3、数组 3-…

Docker:在 ubuntu 系统上生成和加载 Docker 镜像

本文将介绍在 ubuntu系统上进行 Docker 镜像的生成和加载方法和代码。 文章目录 一、下载和安装 docker二、加载 docker 文件三、保存你的镜像四、将镜像上传到云端并通过连接下载和加载 Docker 镜像五、Docker 容器和本地的文件交互5.1 从容器复制文件到本地宿主机5.1.1 单个文…

《数据挖掘:概念、模型、方法与算法(第三版)》

嘿,数据挖掘的小伙伴们!今天我要给你们介绍一本超级实用的书——《数据挖掘:概念、模型、方法与算法》第三版。这本书是数据挖掘领域的经典之作,由该领域的知名专家编写,系统性地介绍了在高维数据空间中分析和提取大量…

做异端中的异端 -- Emacs裸奔之路4: 你不需要IDE

确切地说,你不需要在IDE里面编写或者阅读代码。 IDE用于Render资源文件比较合适,但处理文本,并不划算。 这的文本文件,包括源代码,配置文件,文档等非二进制文件。 先说说IDE带的便利: 函数或者变量的自动…

【C++】编程题目分析与实现回顾:从浮点数运算到整型转换的全面解读

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯题目一:计算成绩问题分析与优化实现优化后的实现优势 💯题目二:浮点数向零舍入不同实现方式的比较1. 使用强制类型转换 (int)2. 使用标准…

时间表格Java

输入:XXX XXX 小时 分钟 输出: XXX:XXX ~ XXX: XXX XXX:XXX ~ XXX: XXX XXX:XXX ~ XXX: XXX 处理:间隔五分钟、区间45分钟 14:15 ~ 15:0 15:5 ~ 15:50 15:55 ~ 16:40 16:45 ~ 17:30 17:35 ~ 18:20…