mysql不支持在json字段上创建fulltext索引,因其仅支持char、varchar、text类型;需通过生成列提取并转换json路径值为字符串,显式指定非二进制排序规则后建全文索引。

MySQL 本身不支持对 JSON 字段直接创建全文索引(FULLTEXT),所谓“JSON字段全文索引失效”本质是误用——你根本建不了,不是建了但失效。
为什么不能在JSON字段上建FULLTEXT索引?
MySQL 的 FULLTEXT 索引只支持 CHAR、VARCHAR 和 TEXT 类型,而 JSON 是独立数据类型,内部结构不可见、不可分词。执行如下语句会直接报错:
CREATE FULLTEXT INDEX ft_data ON t(data); -- ERROR 1214: The used table type doesn't support FULLTEXT indexes
这不是配置或版本问题,是引擎层面限制(InnoDB 和 MyISAM 均不支持)。
想按JSON内文本内容模糊搜索,该怎么做?
必须把目标路径的值“抽出来”,转成可索引的字符串类型,再建全文索引。常见路径如 $.title、$.content 等。
- 添加生成列(
STORED,物理存储,推荐):ALTER TABLE t ADD COLUMN content_text TEXT AS (JSON_UNQUOTE(JSON_EXTRACT(data, '$.content'))) STORED; - 建全文索引:
CREATE FULLTEXT INDEX ft_content ON t(content_text); - 查询时必须查生成列,不能查原始 JSON:
SELECT * FROM t WHERE MATCH(content_text) AGAINST('数据库优化' IN NATURAL LANGUAGE MODE);
注意:JSON_EXTRACT() 返回带引号的 JSON 字符串(如 "MySQL优化"),JSON_UNQUOTE() 才能去掉引号,否则分词结果含多余双引号,影响召回率。
字符集和排序规则不匹配导致MATCH失效
这是最常被忽略的坑:生成列若没显式指定 COLLATE,可能继承源字段的 utf8mb4_bin,而 FULLTEXT 要求列使用**非二进制排序规则**(如 utf8mb4_0900_ai_ci),否则 MATCH ... AGAINST 会静默返回空结果,且 EXPLAIN 看不出异常。
- 检查生成列排序规则:
SHOW FULL COLUMNS FROM t LIKE 'content_text';—— 看Collation列是否为utf8mb4_0900_ai_ci - 重建列并强制指定:
ALTER TABLE t DROP COLUMN content_text;ALTER TABLE t ADD COLUMN content_text TEXT AS (JSON_UNQUOTE(JSON_EXTRACT(data, '$.content'))) STORED COLLATE utf8mb4_0900_ai_ci;
漏掉 COLLATE,哪怕全文索引显示已存在,MATCH 也永远不命中。
函数索引不能替代全文索引
有人尝试用 MySQL 8.0+ 的函数索引加速 LIKE 查询,例如:CREATE INDEX idx_func ON t((LOWER(JSON_UNQUOTE(JSON_EXTRACT(data, '$.content')))));
这只能支撑前缀匹配(WHERE LOWER(...) LIKE 'mysql%'),无法实现真正的语义分词、相关性排序、停用词过滤。它不是全文索引,只是带函数的 B+ 树索引,别混淆。
真正需要全文检索能力时,生成列 + FULLTEXT 是唯一原生方案;若需高阶功能(模糊拼写、同义词、权重控制),就得引入 Elasticsearch 或 MeiliSearch。











