一、 映射(Mapping)是什么?

简单来说,映射就像是关系型数据库中的表结构定义(Schema)。它定义了索引(Index)中的文档(Document)可以包含哪些字段(Field),以及每个字段的数据类型、格式、分词方式、是否索引、是否存储等属性。

核心思想: Elasticsearch是一个** schema-on-write **(写时定义模式)的系统。这意味着在数据被写入之前,最好就明确其结构,而不是像MongoDB这类 NoSQL 数据库是 schema-on-read(读时解析模式)。预先定义好映射,可以让ES更高效地处理、索引和存储数据。

映射的三大组成部分:

  1. 字段类型(Field datatypes): 定义字段的数据类型,如 text, keyword, long, integer, date, boolean, nested, object, geo_point 等。
  2. 元字段(Metadata fields): 用于处理文档的元信息,如 _index, _id, _source
  3. 映射参数(Mapping parameters): 精细化控制字段的索引和存储行为,如 index, analyzer, copy_to, fields 等。

二、 为什么映射如此重要?(架构师视角)

  1. 性能优化(Performance):

    • 正确的数据类型(如使用 keyword 而非 text 进行精确匹配和聚合)可以大幅提升查询和聚合速度。
    • 避免不必要的字段索引("index": false)可以节省磁盘空间和内存,减少索引大小,提升写入和检索效率。
  2. 存储效率(Storage Efficiency):

    • 选择合适的类型(如 integerlong 更省空间)和开启索引压缩(如 doc_values)可以减少磁盘占用。
  3. 功能正确性(Functionality Correctness):

    • 错误的映射会导致查询结果不符合预期。例如,一个本应做全文搜索的字段被错误地设置为 keyword 类型,将无法被分词搜索;一个日期字段被存为 text 类型,将无法进行时间范围查询。
  4. 避免后期重构(Avoiding Reindexing):

    • 映射一旦确定,虽然可以添加新字段,但不允许修改现有字段的类型。如果后期需要修改,必须进行 _reindex 操作(创建一个新索引并重建数据),这对于大数据量的集群来说成本极高。预先精心设计映射可以避免这种痛苦的重构过程。

三、 映射的核心概念详解

1. 字段类型(Field Data Types)
  • 核心类型:

    • text: 用于全文搜索的字符串类型,会被分词器(Analyzer)切分成倒排索引。适用于内容描述、正文等需要被搜索的文本。
    • keyword: 用于精确值过滤、排序和聚合的字符串类型,不会被分词。适用于状态码、标签、姓名、邮箱等。
    • date: 日期类型,可以指定格式。
    • long, integer, short, byte, double, float: 数值类型。
    • boolean: 布尔类型。
    • binary: 二进制类型。
    • range (如 integer_range, date_range): 范围类型。
  • 复杂类型:

    • object: 用于处理单个JSON对象。
    • nested: 非常重要的类型。用于处理对象数组,且需要数组中的对象被独立索引和查询。普通 object 数组中的对象在Lucene底层会被扁平化,导致跨对象的查询出现逻辑错误。nested 类型通过为数组中的每个对象创建独立的隐藏文档来解决这个问题。
    • flattened: 将整个子对象或数组映射为一个字段,其值被存储为 keyword 类型。适用于不确定子结构且不需要深层查询的场景,是 nested 的一种轻量级替代方案。
  • 专用类型:

    • geo_point: 存储经纬度坐标,用于地理位置搜索和距离计算。
    • ip: 存储IPv4/IPv6地址,支持IP范围查询。
    • completion: 用于实现自动补全(Suggesters)功能。
2. 关键映射参数(Mapping Parameters)
  • index: 控制字段是否被索引。默认为 true。如果设置为 false,则该字段不可被搜索,但仍会出现在 _source 中。
  • analyzer: 指定在索引和搜索时用于 text 字段的分词器。如 standard(默认), ik_smart, ik_max_word(中文常用), english
  • search_analyzer: 指定在搜索时使用的分词器,默认与 analyzer 一致。
  • fields: 多字段(Multi-fields)特性。允许对同一个字符串值以不同的方式索引多次,实现不同的目的。这是映射设计的精髓之一。
    • 例如:一个 product_name 字段可以同时被定义为 text 类型(用于全文搜索)和 keyword 类型(用于精确聚合和排序)。
    "product_name": {"type": "text","analyzer": "ik_max_word","fields": {"raw": { // 定义一个名为 raw 的子字段,类型为 keyword"type": "keyword"}}
    }
    
    查询时,使用 product_name 进行全文搜索,使用 product_name.raw 进行精确匹配或聚合。
  • copy_to: 将多个字段的值复制到一个组字段中,实现类似 _all 的跨字段搜索(ES7已移除 _all)。
  • doc_values: 默认开启。为 keyword, numeric, date, geo 等类型生成一个列式存储结构,用于排序、聚合和脚本访问。消耗磁盘空间,但极大提升聚合性能。
  • dynamic: 控制是否动态添加新字段。策略包括:
    • true (默认): 自动添加新字段。
    • false: 忽略新字段(不会被索引,但会出现在 _source 中)。
    • strict: 遇到新字段时抛出异常,拒绝文档写入。生产环境推荐使用 strictfalse 以避免“映射爆炸”(mapping explosion)

四、 结合实际案例:电商平台商品搜索

让我们以一个典型的电商平台商品数据模型为例,来设计其ES映射。

1. 需求分析

我们需要存储和搜索商品信息,核心功能包括:

  • 按商品名称、描述、分类进行全文搜索。
  • 按品牌、分类、店铺进行精确筛选和聚合。
  • 按价格、销量、上架时间进行排序和范围过滤。
  • 按商品属性(如颜色、尺寸、CPU型号)进行动态筛选和聚合。
  • 根据用户地理位置推荐附近的商品(基于店铺地址)。
2. 映射设计

我们将创建一个名为 products 的索引,并预先定义其映射。

PUT /products
{"settings": {"number_of_shards": 3,"number_of_replicas": 1,"analysis": {"analyzer": {"my_ik_analyzer": {"type": "custom","tokenizer": "ik_max_word"}}}},"mappings": {"dynamic": "strict", // 严格模式,防止未知字段污染映射"properties": {"id": {"type": "keyword"},"name": {"type": "text","analyzer": "my_ik_analyzer", // 使用IK中文分词器"fields": {"raw": {"type": "keyword" // 用于精确匹配,如作为聚合键}},"copy_to": "full_text" // 复制到全文搜索字段},"description": {"type": "text","analyzer": "my_ik_analyzer","copy_to": "full_text"},"brand": {"type": "keyword" // 品牌是典型的精确值字段},"category_id": {"type": "integer" // 分类ID用于关联查询,整数类型更高效},"category_path": {"type": "keyword" // 存储分类路径,如 "家电/空调/壁挂式"},"price": {"type": "scaled_float", // 缩放浮点型,避免浮点数精度问题"scaling_factor": 100},"sales_volume": {"type": "integer"},"is_on_shelf": {"type": "boolean"},"listing_time": {"type": "date","format": "epoch_millis" // 使用时间戳格式存储},"tags": {"type": "keyword" // 标签,用于精确过滤和聚合},"specs": { // 商品规格(动态属性),如 {"color": "红色", "size": "XL"}"type": "flattened" // 使用flattened类型,避免映射爆炸,且支持基本的键值查询},"store_info": { // 店铺信息,是一个对象"type": "object","properties": {"id": {"type": "keyword"},"name": {"type": "text","analyzer": "my_ik_analyzer","fields": {"raw": {"type": "keyword"}}},"location": { // 店铺地理位置"type": "geo_point"}}},"full_text": { // 用于跨字段全文搜索的组字段"type": "text","analyzer": "my_ik_analyzer"}}}
}
3. 使用方法与查询示例

a. 插入数据

POST /products/_doc/1001
{"id": "1001","name": "Apple iPhone 15 Pro Max 256GB 原色钛金属","description": "全新A17 Pro芯片,钛金属设计,强悍性能与卓越影像能力。","brand": "Apple","category_id": 1,"category_path": "手机通讯/手机/苹果手机","price": 8999.00,"sales_volume": 1500,"is_on_shelf": true,"listing_time": 1696118400000,"tags": ["新品", "优惠", "免息"],"specs": {"color": "原色钛金属","memory": "256GB","network": "5G"},"store_info": {"id": "s100","name": "Apple官方旗舰店","location": {"lat": 39.9042,"lon": 116.4074}}
}

b. 复杂查询示例

  • 全文搜索 + 过滤 + 聚合:搜索包含“苹果手机”且价格在5000-10000元之间的商品,并按品牌聚合。

    GET /products/_search
    {"query": {"bool": {"must": [{"match": {"full_text": "苹果手机"}}],"filter": [{"range": {"price": {"gte": 5000,"lte": 10000}}},{"term": {"is_on_shelf": true}}]}},"aggs": {"brands": {"terms": {"field": "brand"}}},"sort": [{"sales_volume": {"order": "desc"}}]
    }
    
  • 基于地理位置的查询:查找距离我(经纬度[116.40, 39.90])10公里以内的店铺的商品。

    GET /products/_search
    {"query": {"bool": {"filter": [{"geo_distance": {"distance": "10km","store_info.location": {"lat": 39.90,"lon": 116.40}}}]}}
    }
    
  • 查询特定规格:查询内存为“256GB”的商品。

    GET /products/_search
    {"query": {"match": {"specs": "256GB" // Flattened字段支持简单的匹配查询}}
    }
    

五、 最佳实践与总结

  1. 预先定义映射:切忌依赖动态映射。对于核心业务索引,务必在写入数据前通过 PUT /my_index { "mappings": { ... } } 创建好映射。
  2. 善用 keywordtext:明确字段是用来全文搜索还是精确匹配。绝大多数字符串字段都应使用 fields 配置为 text + keyword 多字段。
  3. 谨慎使用 nestednested 类型查询性能开销较大,仅在确实需要独立查询数组内对象时使用。如果关系简单,考虑使用 flattened
  4. 控制映射大小:使用 dynamic: strictfalse,避免无效字段无限增长。一个索引中字段过多(例如超过1000)会影响集群性能。
  5. 规划索引策略:结合ILM(Index Lifecycle Management),根据时间或数据量进行滚动索引(Rollover),这也能在一定程度上缓解映射不可修改的问题(因为新索引可以用新映射)。
  6. 进行映射评审:像评审数据库表结构一样,将重要的ES索引映射设计纳入技术评审流程。

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

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

相关文章

【Linux | 网络】多路转接IO之poll

一、poll函数二、poll的优缺点三、实现poll服务器(只关心读事件)3.1 Log.hpp(日志)3.2 Lockguard.hpp(自动管理锁)3.3 Socket.hpp(封装套接字)3.4 PollServer.hpp(服务端…

一站式资源共享平台模板,助力快速搭建专属资源站源码

内容目录一、详细介绍二、效果展示1.部分代码2.效果图展示三、学习资料下载一、详细介绍 这个资源分享网站模板是一个功能完整、设计现代的单页网站,非常适合快速搭建资源分享平台。以下是关于这个模板的详细介绍,帮助你更好地理解并发布到自己的网站&a…

ngnix的部分配置

1. 禁止特定IP地址访问你可以通过在Nginx配置文件中添加deny指令来阻止特定IP地址或IP地址段的访问。server {listen 80;server_name example.com;location / {deny 192.168.1.0/24;allow all;} }2. 允许特定IP地址访问如果你想允许只有特定IP地址或IP地址段的访问,…

Qwt7.0-打造更美观高效的Qt开源绘图控件库

概述 Qt 生态里能画图的库不多,主流的为QCustomPlot、Qwt、Qt Charts和KDChart,Qt6.8之后把原来的 Qt Charts(2D) 与 Qt DataVisualization(3D) 合并为统一的Qt Graphs模块(注意不是Qt Graphic…

NFC线圈设计计算

对工作于13.56MHz的电感耦合的NFC系统,针对小距离的传统天线通常是环形或者矩形的扁平线圈。 圆形扁平线圈计算评估 对于二阶估计,我们可以由匝数决定的电感等式为 考虑到线圈的物理参数,设置平均直径:D_averD0-N(gw) 线圈周长: ;d2*(w t)/π 初始设置中的这种电感…

mac设置鼠标滚轮方向

mac中滚轮的滑动方向和windows是相反的,如果需要设置和windows相同,设置如下:将自然滚动关闭即可。

QSpinBox的用法及其使用QSS对其美化

摘要 在现代应用程序开发中,提供一个直观且用户友好的界面至关重要。Qt框架提供了丰富的控件和工具,帮助开发者实现这一目标。本文将详细介绍如何使用Qt的QSpinBox控件让用户输入数值,并通过Qt Style Sheets (QSS) 美化界面,提升…

18 继续学习

要设计出一个好的系统,需要多年的知识积累。有一个捷径是研究真实世界的系统架构。本文将介绍一些有帮助的阅读材料。 务必留意那些真实系统之间共通的原理和相同的底层技术。研究每个技术并了解它解决了什么问题, 这是一个巩固基础知识和完善设计过程的…

深度学习篇---混淆矩阵

要理解混淆矩阵(Confusion Matrix),我们可以从它的名字入手:它本质是一张 “帮你理清模型预测结果到底‘混淆’在哪里” 的表格,核心作用是评估分类模型的表现 —— 比如判断一张图片是 “猫” 还是 “狗”、一封邮件是…

MySQL重大隐患!mysqlpump的--set-gtid-purged参数在5.7和8.0的雷区

MySQLPump是MySQL官方提供的一个用于备份和恢复MySQL数据库的工具。它于MySQL 5.7.8版本中首次引入,旨在提供一种快速、可靠且高效的备份和恢复解决方案。MySQL Pump首次支持了并行导出、压缩导出,可以利用多核CPU来提高备份能力,在效率上要比…

低质量视频变高清AI:告别模糊,重现清晰画质

在数字时代,视频内容的创作和消费日益普及,然而,许多早期拍摄或存储的视频,由于技术限制或压缩等原因,往往存在画质不佳的问题,如模糊、噪点多、分辨率低等。这不仅影响观看体验,也限制了这些珍…

Linux入门教程 第十二章 防火墙

文章目录前言一、 iptables 概述Netfilter二、iptables 的表、链结构2.1 ptables的四表五链结构介绍2.1.1 四表五链2.1.2 四表2.1.3 **五链**2.2 数据包过滤的匹配流程(数据包到防火墙)2.2.1 规则链之间的匹配顺序:主机型防火墙:2.2.2 规则链内的匹配顺序…

单词搜索+回溯法

题目&#xff1a;思考&#xff1a; 1.经典回溯 实现&#xff1a; class Solution { public:bool find_word(vector<vector<char>>&board,string word,int pos,int i,int j){bool retfalse;if (posword.size()-1) return board[i][j]word[pos];if (board[i][j…

【嵌入式开发 Linux 常用命令系列 8 -- git checkout 解冲突详细介绍】

文章目录1. Git 冲突产生的场景2. 冲突标记符号解释3. git checkout --ours 和 git checkout --theirs语法含义使用场景4. 操作完成后的流程5. 举例演示1. Git 冲突产生的场景 当你在 git merge、git rebase、git cherry-pick 等操作时&#xff0c;如果 同一个文件的同一部分在…

16-day13强化学习和训练大模型

强化学习 强化学习和监督学习是机器学习中的两种不同的学习范式 强化学习&#xff1a;目标是让智能体通过与环境的交互&#xff0c;学习到一个最优策略&#xff0c;以最大化长期累积奖励。 例如&#xff0c;在机器人导航任务中&#xff0c;智能体需要学习如何在复杂环境中移动&…

OpenAI o1:OpenAI最新推出的AI大语言模型,更擅长推理也更贵

本文转载自&#xff1a;OpenAI o1&#xff1a;OpenAI最新推出的AI大语言模型&#xff0c;更擅长推理也更贵 - Hello123工具导航 ** 一、&#x1f916; OpenAI o1 是什么&#xff1f; OpenAI o1 是 2024 年推出的推理特化型 AI 模型&#xff0c;主打 “慢思考、深分析”&#…

自然语言处理——03 RNN及其变体

1 认识RNN 1.1 概念循环神经网络 RNN &#xff08;Recurrent Neural Network&#xff0c;简称RNN&#xff09;——处理序列数据的神经网络&#xff1b;一般以序列数据作为输入&#xff0c;通过网络内部的结构设计有效捕捉序列之间的关系特征&#xff0c;一般也是以序列形式进行…

量子计算基础

量子计算 量子计算一般由三个基本步骤组成&#xff1a;制备输入量子态、对于量子态执行幺正变换以及测量输出态&#xff0c;这里将介绍这三个基本要素。 1 量子态 与经典计算中比特(bit)的概念相对应&#xff0c;量子计算中最小信息载体和处理单位是量子比特(quantum bit, or t…

Apache Maven 3.1.1 (eclipse luna)

Apache Maven 3.1.1 &#xff08;eclipse luna&#xff09;D:\apache-maven-3.1.1\binMAVEN_HOME:D:\apache-maven-3.1.1PATH:D:\apache-maven-3.1.1\binmvn -vMaven Integration for Eclipse(Luna)

应用篇#1:YOLOv8模型在Windows电脑摄像头上的部署

一、前言如何部署YOLOv8模型在摄像头上是完成模型应用必须解决的问题&#xff0c;通过使用“cv2”这个库&#xff0c;可以完成对电脑摄像头的调用&#xff08;本人Windows联想&#xff09;&#xff0c;实时检测并输出图像。二、代码实现与解读import warnings import cv2 from …