Elasticsearch实战(二十三)---ES数据建模与Mysql对比 一对多模型

news2024/9/30 1:41:58

Elasticsearch实战—ES数据建模与Mysql对比实现 一对多模型

文章目录

    • Elasticsearch实战---ES数据建模与Mysql对比实现 一对多模型
      • 1.一对多 模型
        • 1.1 Mysql建模
      • 2.一对多 Index ES 数据模型
        • 2.1 类似Mysql, 依旧创建两个Index索引库
        • 2.2 采用ES架构 嵌套数组模型
        • 2.3采用ES架构 冗余部分字段Object对象模型
      • 3.冗余ES字段Object对象模型实战
      • 4.冗余ES字段Object对象模型缺陷
        • 4.1 演示Object对象缺陷
      • 5. 解决办法

我们如何把Mysql的模型合理的在ES中去实现? 就需要你对要存储的数据足够的了解,及对应用场景足够的深入分析,才能建立一个合适的模型,便于你后期扩展

  1. 一对一 模型
  2. 一对多 模型
  3. 多对多 模型

1.一对多 模型

我们现在有两个模型, 一个商品Product, 一个分类Category , 我们对比下一对多模型如何处理 ,一个分类下有多个商品, 商品对分类 1:N 1对多关系

1.1 Mysql建模

对于一对多的数据模型, mysql 可以用2个表 来在Mysql中实现 一对多,通过关联外键主键等, 查 produce_id的同时, 再根据 attribute_id属性id去 关联 查属性表查出商品和分类的关系
手机是一个分类, 但是 手机下面分为 华为手机, 小米手机, VIVO手机等 一对多模型
在这里插入图片描述

#关联查询
select * from category left join product on category.category_id = product.category_id;

Table :category 手机分类表

字段类型
id唯一主键,自增
category_id分类id
category_name分类名称
category_remark分类标签

Table :product 商品表 基本信息 包含分类 id 用于关联

字段类型
id唯一主键,自增
product_id商品id
category_id分类id
product_name商品名称
product_price商品价格
product_number商品数量

2.一对多 Index ES 数据模型

对于ES 这种1:N的, 如果我们的场景是查出 一个分类下面的所有商品, 我们应该如何建模?
三种方式

2.1 类似Mysql, 依旧创建两个Index索引库

一个库存 category, 一个存product, 想要查一个分类下面的所有商品 分2步, 先查分类,再根据category_id去 商品库中查所有的商品
优点: 设计简单,参照Mysql,依旧没有冗余数据
缺点: 查询逻辑复杂, 需要多次调用不同索引库的Index去查询API,效率低下
这种方式我们不推荐使用,这里就不再给出 Index mapping结构

2.2 采用ES架构 嵌套数组模型

既然一个分类下多个商品,那我就按照 { 分类1:[商品1, 商品2, 商品3, …, 商品X] } 把所有的商品存储在 一个分类下的数组结构中, 乍一看挺好的,一次性能取出来所有数据
优点: 依旧没有冗余数据, 更新的时候只更新1条数据
缺点: ES的更新document是把原来的记录删掉,重新再插入的机制,如果更新一个分类的名称如果按照分库结构, 只需要更细一个index库的 一条数据就即可, 但是采用ES嵌套数组就要把下面的所有的商品全都查出来,然后更新完他的分类字段后,再全部插入,等同于该分类的所有商品全部更新一遍, 操作数据量大,而且更新不方便
这种方式我们同样不推荐使用, 这里不再给出 Index mapping结构

2.3采用ES架构 冗余部分字段Object对象模型

既然嵌套数组模型不太符合,那我采用冗余方式, 我现在把所有的分类全都存一份 存到商品信息中, 商品信息式最小粒度{ {商品1: 属性, 分类信息1}, {商品2: 属性, 分类信息1}, {商品3: 属性, 分类信息2}, {商品4: 属性, 分类信息2} }, 以冗余分类数据到商品信息中来实现关联
优点: 更新一个商品,不会再更新所有的商品,商品粒度最小
缺点: 更新一个分类, 更新多条数据, 就要更新所有商品的分类的数据, 全部都需要更新, 有多少个此分类的商品,就要更新多少条

  • 操作简单, 一次性就能搜索出所有的结果字段

3.冗余ES字段Object对象模型实战

我们采用大致类似与 这样的 Mysql Table :produce 商品表 基本信息

字段类型
id唯一主键,自增
product_id商品id
product_name商品名称
product_price商品价格
product_number商品数量
category_name分类名称
category_remark分类标签

下面创建Index mapping结构, 我们把多个手机相同的分类信息,作为冗余字段 冗余到 手机基本信息中

索引库结构

PUT /phone_index
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 2
  },
  "mappings": {
    "properties": {
      "productId": {
        "type": "long"
      },
      "productName": {
        "type": "keyword"
      },
      "productPrice": {
        "type": "long"
      },
      "productNumber": {
        "type": "long"
      },
      "category": {
        "properties": {
          "categoryName": {
            "type": "keyword"
          },
          "categoryRemark": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

下面我们给 phone_index 索引库插入数据, 插入 6条手机信息

put /phone_index/_bulk
{"index":{"_id":1}}
{"productId":1,"productName":"P20","productPrice":4000,"productNumber":50,"category":{"categoryName":"华为手机","categoryRemark":"高端"}}
{"index":{"_id":2}}
{"productId":2,"productName":"Honor30","productPrice":2000,"productNumber":100,"category":[{"categoryName":"华为手机","categoryRemark":"很好"},{"categoryName":"荣耀手机","categoryRemark":"便宜"}]}
{"index":{"_id":3}}
{"productId":3,"productName":"小米8","productPrice":2000,"productNumber":600,"category":{"categoryName":"小米手机","categoryRemark":"中端"}}
{"index":{"_id":4}}
{"productId":4,"productName":"红米10","productPrice":2500,"productNumber":300,"category":{"categoryName":"小米手机","categoryRemark":"发烧"}}
{"index":{"_id":5}}
{"productId":5,"productName":"小米Max","productPrice":4000,"productNumber":800,"category":{"categoryName":"小米手机","categoryRemark":"很好"}}

4.冗余ES字段Object对象模型缺陷

上面的结构似乎看起来很合理,而且能解决一部分问题,但是这种对象结构是存在很大缺陷的,为什么 ?

是因为底层ES在存储对象结构的时候都是以数组的形式存储, 比如这个Honor30 手机牌子 ,底层数据存储的就是

  • categoryName:[华为i手机, 荣耀手机]
  • categoryRemark[很好, 便宜]
  • 这里已经失去了绑定关系了, 比如 华为手机-很好, 荣耀手机-便宜 这种对应关系
  • 查询的时候就会出现 华为手机-便宜的 这种数据出现
    在这里插入图片描述

4.1 演示Object对象缺陷

我们要查询 华为手机 便宜的 标签,must 查询, 分类:华为手机,描述:便宜

按照存储的数据, 这种数据应该不存在


get /phone_index/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "category.categoryName": "华为手机"
          }
        },
        {
          "match": {
            "category.categoryRemark": "便宜"
          }
        }
      ]
    }
  }
}

查询结果 不是我们想要的, 是错误的
在这里插入图片描述

或者 我们再查询以下 华为手机-发烧的 场景, 按照我们的数据, 不存在任何数据把华为手机和发烧关联

must查询, 分类:华为手机, 标签:发烧

get /phone_index/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "category.categoryName": "华为手机"
          }
        },
        {
          "match": {
            "category.categoryRemark": "发烧"
          }
        }
      ]
    }
  }
}

查询结果错误, 要查询 华为手机-发烧的数据,结果把 小米手机查询出来了,这是明显的错误
在这里插入图片描述

5. 解决办法

Object对象存储会出现上面的问题, 为了解决这种问题,我们要采用Nest结构来存储数据, 这种Nest结构底层不是数组存储的,就不会出现上面的情况

下一篇 我们来介绍Nest结构 解决对象冗余存储Object对象的缺陷

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JUC-2】Synchronized关键字相关知识

Synchronized synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种: 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象&#xf…

【C++2】进程 信号 dbus

文章目录 1.进程:fork(),ps -ef (同-aux) | more2.信号:signal(, EXIT),jps2.1 捕捉信号:ctrlc:22.2 捕捉信号:kill -9:92.3 捕捉信号:kill&#…

欧几里得算法

0x00 前言 改补的内容是一点都不会少。本章来看欧几里得算法 0x01 概述 欧几里得算法又称为辗转相除法,指用于计算两个非负整数a和b的最大公约数。 两个整数的最大公约数是能够同时整除他们的最大的正整数。 基本原理:两个整数的最大公约数等于其中…

【动态规划】子数组系列(上)

子数组问题 文章目录 【动态规划】子数组系列(上)1. 最大子数组和1.1 题目解析1.2 算法原理1.2.1 状态表示1.2.2 状态转移方程1.2.3 初始化1.2.4 填表顺序1.2.5 返回值 1.3 代码实现 2. 环形子数组的最大和2.1 题目解析2.2 算法原理2.2.1 状态表示2.2.2 …

C++2(表达式和关系运算)

目录 1.表达式基础 1.表达式基础 运算符重载,就是自己定义 - * / 之类的运算符怎么运算 C中的左值和右值 C语言左值在左侧,右值在右侧 在cpp中要复杂的多 能取到地址的表达式是左值 不能取到地址的表达式是右值 常量对象为代表的左值不能作为赋值语句的左…

【Linux】网络相关概念概述以及原理简单分析介绍

文章目录 [toc] Linux 网络概述网络发展独立模式网络互联局域网LAN 和 广域网WAN 认识 "协议"协议的分层网络协议栈OSI七层模型TCP/IP五层(四层)模型TCP/IP网络协议栈 与 操作系统 的关系 **重新以计算机的视角看待 网络协议栈 局域网内部通信原理简单介绍不同局域网…

mybatis web使用02

处理 transfer 请求的 servlet package com.wsd.web;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRe…

GAMES101 笔记 Lecture08 Shading 2(Shading, Pipeline and Texture Mapping)

目录 Specular Term(高光项)Ambient Term(环境光照项)Blinn-Phong Reflection ModelShading Frequencies(着色频率)Shade each triangle(flat shading)在每个三角形上进行着色Shade each vertex (Gouraud shading)(顶点着色)Shade each pixel (Phong shading)Defining Per-Vert…

【C++详解】——哈希

目录 unordered系列关联式容器 unordered_map unordered_map的接口说明 1.unordered_map的构造 2.unordered_map的容量 3.迭代器相关 4.unordered_map的元素访问 5. unordered_map的查询 6.unordered_map的修改操作 unordered_set 性能测试 底层结构——Hash 哈希…

copula简介

二元正态copula最为重要

MySQL - 自连接查询

1. 测试数据 创建 category 表 : CREATE TABLE category(categoryid INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 主题id,pid INT(10) NOT NULL COMMENT 父id,categoryName VARCHAR(50) NOT NULL COMMENT 主题名字,PRIMARY KEY(categoryid) ) ENGINEINNODB AUTO_INCREM…

cmd的学习

目录 常用的cmd命令 使用cmd的例子 常用的cmd命令 指令作用盘符名称:盘符切换dir查看当前路径下的内容tree以树形结构输出当前路径下的内容cd进入单级目录cd ..回退到上一级目录cd 目录1\目录2\...进入多级目录cd \回退到盘符目录cls清屏exit退出窗口 (值得注意的…

Android AlertDialog setView,kotlin

Android AlertDialog setView&#xff0c;kotlin <?xml version"1.0" encoding"utf-8"?> <com.google.android.material.textfield.TextInputLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width…

MySQL数据库——主从复制和读写分离

MySQL数据库——主从复制和读写分离 一、主从复制和读写分离的相关知识1.什么是读写分离&#xff1f;2.为什么要读写分离呢&#xff1f;3.什么时候要读写分离&#xff1f;4.主从复制与读写分离5.mysql支持的复制类型6.主从复制的工作过程7.MySQL 读写分离原理8.目前较为常见的 …

前端实现俄罗斯方块游戏(内含源码)

目录 一、前言 二、功能介绍 三、页面搭建 四、样式设置 五、逻辑部分 一、前言 今天带领大家完成俄罗斯方块游戏&#xff0c;功能也比较简单&#xff0c;也是想借助这样一个简单的功能&#xff0c;然后来帮助大家了解我们JavaScript在前端中的作用&#xff0c; 后续也会带…

【服务器】ASP.Net Core(C#)创建Web站点

简单几步实现本地ASP.Net.Core web 站点结合cpolar内网穿透工具实现远程访问 1. 创建站点 *环境搭建,这边测试,使用.NET 6.0 SDK,可以点击跳转到官网下载,下载后安装即可. 安装完成后,进入到某个文件夹,打开powershell执行下面命令,创建新的 Web 应用,名称叫:aspnetcoreapp …

机器学习 day22(ReLU激活函数)

ReLU激活函数 如果想让a取更大的非负数&#xff0c;激活函数g(z)可以选用ReLU激活函数&#xff0c;他在z&#xff1c;0时取0&#xff0c;在z ≥ 0时取z 常见的激活函数 左侧的为线性激活函数&#xff0c;因为f(x) wxb&#xff0c;使用激活函数后f(x) g(z)&#xff0c;此…

综合评价算法 | Matlab实现基于TOPSIS法的综合评价算法

文章目录 效果一览文章概述研究内容源码设计参考资料效果一览 文章概述 综合评价算法 | Matlab实现基于TOPSIS法的综合评价算法 研究内容 C.L.Hwang 和 K.Yoon 于1981年首次提出 TOPSIS (Technique for Order Preference by Similarity to an Ideal Solution)。TOPSIS 法是一种…

卷积神经网络--猫狗系列【CNN】

数据集&#xff0c;这次这个是分了类的【文末分享】 各12500张&#xff1a; 两点需要注意&#xff1a; ①猫狗分类是彩色图片&#xff0c;所以是3个channel&#xff1b; ②猫狗分类的图片大小不一&#xff0c;但是CNN的输入要求是固定大小&#xff0c;所以要resize。 划分训练…

【动态规划】子数组系列(下)

子数组问题 文章目录 【动态规划】子数组系列&#xff08;下&#xff09;1. 等差数组划分1.1 题目解析1.2 算法原理1.2.1 状态表示1.2.2 状态转移方程1.2.3 初始化1.2.4 填表顺序1.2.5 返回值 1.3 代码实现 2. 最长湍流子数组2.1 题目解析2.2 算法原理2.2.1 状态表示2.2.2 状态…