【 使用环境 】生产环境 or 测试环境
【 OB or 其他组件 】OB
【 使用版本 】4.4.2-ce
【问题描述】
想过滤json字段中的某个字段,应该如何建表,这个是json字段的数据示例,想要过滤addr,匹配到了就直接返回整行数据。
[{"mac": "", "addr": "172.018.005.180", "type": 0}, {"mac": "", "addr": "172.018.005.181", "type": 0}]
下面是遇到的问题。
- 多值索引,建表后不能添加多值索引,必须要建表时指定,但是未来可能会扩展过滤更多字段。
建表语句:
CREATE TABLE `host_nic_config` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`host_id` BIGINT NOT NULL COMMENT '关联主机 ID',
`config_name` VARCHAR(64) NOT NULL DEFAULT 'default' COMMENT '配置名',
`addresses` JSON NOT NULL COMMENT '网卡地址数组 [{"mac":"","addr":"172.018.005.180","type":0}]',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_host` (`host_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COMMENT = '主机网卡配置(JSON 数组)';
建索引失败。
mysql> CREATE INDEX addr_test ON host_nic_config ((CAST(addresses->'$[*].addr' AS CHAR(255) ARRAY)));
ERROR 1235 (0A000): build multivalue index afterward not supported
数据示例:
INSERT INTO host_nic_config (host_id, config_name, addresses) VALUES
(1001, 'default',
'[{"mac":"","addr":"172.018.005.180","type":0},{"mac":"","addr":"172.018.005.181","type":0}]'),
(1002, 'default',
'[{"mac":"aa:bb:cc:dd:ee:01","addr":"172.018.005.182","type":1}]'),
(1003, 'bond0',
'[{"mac":"aa:bb:cc:dd:ee:02","addr":"172.018.005.183","type":0},{"mac":"aa:bb:cc:dd:ee:03","addr":"172.018.005.184","type":0}]'),
(1004, 'default',
'[{"mac":"","addr":"172.018.005.180","type":0}]');
- 生成列,可以查询。
mysql> ALTER TABLE host_nic_config ADD COLUMN all_addrs VARCHAR(1024) GENERATED ALWAYS AS (JSON_EXTRACT(addresses, '$[*].addr')) STORED;
Query OK, 0 rows affected (2.12 sec)
mysql> SELECT * FROM host_nic_config
-> WHERE JSON_CONTAINS(all_addrs, '"172.018.005.180"');
+----+---------+-------------+--------------------------------------------------------------------------------------------------------+---------------------+---------------------+----------------------------------------+
| id | host_id | config_name | addresses | created_at | updated_at | all_addrs |
+----+---------+-------------+--------------------------------------------------------------------------------------------------------+---------------------+---------------------+----------------------------------------+
| 1 | 1001 | default | [{"mac": "", "addr": "172.018.005.180", "type": 0}, {"mac": "", "addr": "172.018.005.181", "type": 0}] | 2026-07-27 16:33:20 | 2026-07-27 16:33:20 | ["172.018.005.180", "172.018.005.181"] |
| 4 | 1004 | default | [{"mac": "", "addr": "172.018.005.180", "type": 0}] | 2026-07-27 16:33:20 | 2026-07-27 16:33:20 | ["172.018.005.180"] |
| 5 | 1006 | default | [{"mac": "", "addr": "172.018.005.180", "type": 0}, {"mac": "", "addr": "172.018.005.181", "type": 0}] | 2026-07-27 19:29:15 | 2026-07-27 19:29:15 | ["172.018.005.180", "172.018.005.181"] |
+----+---------+-------------+--------------------------------------------------------------------------------------------------------+---------------------+---------------------+----------------------------------------+
3 rows in set (0.01 sec)
建索引,无法查询。
mysql> ALTER TABLE host_nic_config ADD INDEX idx_all_addrs (all_addrs);
Query OK, 0 rows affected (0.88 sec)
mysql> SELECT * FROM host_nic_config WHERE JSON_CONTAINS(all_addrs, '"172.018.005.180"');
Empty set (0.03 sec)
mysql> SELECT * FROM host_nic_config WHERE all_addrs = "172.018.005.180";
Empty set (0.00 sec)
可能要建全文索引?但是保证不了性能?
