开发者

MySQL进行JSON复杂查询的完全指南

目录
  • 一、jsON对象全等判断:当强迫症遇到数据结构
    • 1.1 精确匹配(键顺序敏感)
    • 1.2 松散全等判断(键顺序无关)
  • 二、数组的“灵魂拷问”式查询
    • 2.1 数组完全相等(顺序敏感)
    • 2.2 数组包含所有元素(顺序无关)
    • 2.3 数组包含任意元素(类似OR条件)
  • 三、嵌套结构的“掘地三尺”查询
    • 3.1 多层级路径查询
    • 3.2 通配符搜索所有层级
    • 3.3 深度过滤数组对象
  • 四、混合条件综合查询
    • 4.1 JSON字段 + 关系字段联合查询
    • 4.2 多JSON字段关联查询
    • 4.3 动态条件生成查询
  • 五、性能优化黑科技
    • 5.1 虚拟列 + 索引加速
    • 5.2 函数索引(mysql 8.0+)
    • 5.3 查询重写优化
  • 六、经典踩坑案例
    • 6.1 隐式类型转换陷阱
    • 6.2 通配符滥用灾难
    • 6.3 大JSON修改雪崩
  • 七、超硬核面试题

    一、JSON对象全等判断:当强迫症遇到数据结构

    1.1 精确匹配(键顺序敏感)

    -- 案例:查找配置完全相同的设备(键顺序必须一致)
    SELECT * FROM device_configs 
    WHERE config_json = '{"resolution": "1080p", "brightness": 80}';
    
    -- 陷阱警告:以下两个JSON会被认为不同(键顺序不同)
    '{"a":1, "b":2}' vs '{"b":2, "a":1}'
    

    1.2 松散全等判断(键顺序无关)

    -- 方法:使用JSON_CONTAINS双向包含 + 长度相同
    SELECT * FROM device_configs 
    WHERE 
      JSON_CONTAINS(config_json, '{"brightness": 80, "resolution": "1080p"}') 
      AND 
      JSON_CONTAINS('{"brightness": 80, "resolution": "1080p"}', config_json)
      AND
      JSON_LENGTH(config_json) = 2; -- 确保没有多余字段
    

    二、数组的“灵魂拷问”式查询

    2.1 数组完全相等(顺序敏感)

    -- 查找tags数组严格等于["VIP","北京"]的用户(顺序、数量、元素完全一致)
    SELECYQyqST * FROM users 
    WHERE tags_json = CAST('["VIP","北京"]' AS JSON);
    

    2.2 数组包含所有元素(顺序无关)

    -- 查找tags包含"VIP"和"北京"的用户(android类似AND条件)
    SELECT * FROM users 
    WHERE 
      JSON_CONTAINS(tags_json, '"VIP"') 
      AND 
      JSON_CONTAINS(tags_json, '"北京"');
    

    2.3 数组包含任意元素(类似OR条件)

    -- 查找tags包含"VIP"或"北京"的用户
    SELECT * FROM users 
    WHERE 
      JSON_CONTAINS(tags_json, '["VIP"]') 
      OR 
      JSON_CONTAINS(tags_json, '["北京"]');
    

    三、嵌套结构的“掘地三尺”查询

    3.1 多层级路径查询

    -- 查找住在"北京朝阳区"的用户(嵌套对象查询)
    SELECT * FROM users 
    WHERE address_json->>'$.city' = '北京' 
      AND address_json->>'$.district' = '朝阳区';
    

    3.2 通配符搜索所有层级

    -- 查找任意层级包含"error_code":500的日志(递归搜索)
    SELECT * FROM service_logs 
    WHERE JSON_SEARCH(log_json, 'all', '500', NULL, '$**.error_code') IS NOT NULL;
    

    3.3 深度过滤数组对象

    -- 查找订单中有商品ID=100且数量>2的订单(数组对象过滤)
    SELECT * FROM orders 
    WHERE JSON_EXISTS(
      items_json, 
      '$[*]?(@.product_id == 100 && @.quantity > 2)'
    );
    

    四、混合条件综合查询www.devze.com

    4.1 JSON字段 + 关系字段联合查询

    -- 查找2023年后注册,且扩展信息中device_type="IOS"的用户
    SELECT * FROM users 
    WHERE 
      register_time > '2023-01-01' 
      AND 
      ext_info->>'$.device_type' = 'iOS';
    

    4.2 多JSON字段关联查询

    -- 查找购物车总价>1000且包含"急件"标签的订单
    SELECT * FROM orders 
    WHERE 
      CAST(cart_info->>'$.total_price' AS DECIMAL) > 1000 
      AND 
      JSON_CONTAINS(tags_json, '"急件"');
    

    4.3 动态条件生成查询

    -- 根据前端传入的JSON过滤条件动态查询(php示例)
    $filters = '{"status":"pending","price":{"$gt":100}}';
    $where = [];
    foreach(json_decode($filters, true) as $key => $value){
      if(is_array($value)){
        $where[] = "data_json->>'$.$key' > ".$value['$gt'];
      }else{
        $where[] = "data_json->>'$.$key' = '$value'";
      }
    }
    $sql = "SELECT * FROM products WHERE ".implode(' AND ', $where);
    

    五、性能优化黑科技

    5.1 虚拟列 + 索引加速

    -- 为常用查询条件创建虚拟列索引
    ALTER TABLE users 
    ADD COLUMN city VARCHAR(20) 
      GENERATED ALWAYS AS (address_json->>'$.city'),
    ADD INDEX idx_city (city);
    

    5.2 函数索引(MySQL 8.0+)

    -- 直接为JSON路径表达式创建索引
    CREATE INDEX idx_price ON products ((CAST(data_json->>'$.price' AS DECIMAL)));
    

    5.3 查询重写优化

    -- 原查询(性能差)
    SELECT * FROM logs 
    WHERE JSON_EXTRACT(log_data, '$.request.time') > '2023-01-01';
    
    -- 优化后(提取时间到独立字段 + 索引)
    ALTER TABLE logs ADD COLUMN request_time DATETIME 
      GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(log_data, '$.request.time')));
    CREATE INDEX idx_request_time ON logs(request_time);
    

    六、经典踩坑案例

    6.1 隐式类型转换陷阱

    -- 错误:字符串与数字比较导致索引失效
    SELECT * FROM products 
    WHERE data_json->>'$.id' = 100; -- $.id值是字符串"100"
    
    -- 正确:显式类型转换
    SELECT * FROM products 
    WHERE CAST(data_json->>'$.id' AS UNSIGNED) = 100;
    

    6.2 通配符滥用灾难

    -- 错误:左模糊查询全表扫描
    SELECT * FROM articles 
    WHERE content_json->>'$.text' LIKE '%重要通知编程%';
    
    -- 正确:使用全文索引或专用搜索引擎(如Elasticsearch)
    

    6.3 大JSON修改雪崩

    -- 错误:频繁更新大JSON字段导致IO飙升
    UPDATE user_activities 
    SET log_json = JSON_ARRAY_APPEND(log_json, '$', '新事件') 
    WHERE user_id = 1001;
    
    -- 正确:拆分成关系表或分片存储
    

    七、超硬核面试题

    题目:如何高效实现JSON数组的交集查询?

    示例:查找tags数组同时包含["VIP","北京","90后"]的用户

    参考答案

    -- 方法1:JSON_CONTAINS链式调用
    SELECT * FROM users 
    WHERE 
      JSON_CONTAINS(tags_json, '"VIP"') 
      AND JSON_CONTAINS(tags_json, '"北京"')
      AND JSON_CONTAINS(tags_json, '"90后"');
    
    -- 方法2:利用JSON_TABLE展开后统计(MySQL 8.0+)
    SELECT user_id 
    FROM users, JSON_TABLE(
      tags_json,
      '$[*]' COLUMNS(tag VARCHpythonAR(10) PATH '$')
    ) AS tags 
    WHERE tag IN ('VIP', '北京', '90后')
    GROUP BY user_id
    HAVING COUNT(DISTINCT tag) = 3;
    

    到此这篇关于MySQL进行JSON复杂查询的完全指南的文章就介绍到这了,更多相关MySQL JSON查询内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

    0

    上一篇:

    下一篇:

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新数据库

    数据库排行榜