使用MySQL 5.7.19,我发誓一小时前这有效,但现在我的查询没有返回任何内容
CREATE TABLE FlattenedData.blog_posts
(
post_id CHAR(13) NOT NULL PRIMARY KEY UNIQUE,
post_data JSON,
date_published DATETIME NOT NULL, # for primary indexing
date_added DATETIME DEFAULT CURRENT_TIMESTAMP,
date_updated DATETIME DEFAULT CURRENT_TIMESTAMP on UPDATE CURRENT_TIMESTAMP,
post_categories VARCHAR(255) GENERATED ALWAYS AS (post_data->>"$.categories[*].slug"),
post_tags VARCHAR(512) GENERATED ALWAYS AS (post_data->>"$.tags[*].slug"),
KEY idx_date_published (date_published),
INDEX idx_categories (post_categories),
INDEX idx_tags (post_tags),
INDEX idx_categories_tags (post_categories, post_tags)
);
作为注释:帖子可以有多个类别,就像标签一样
这是我的查询
select
*
from blog_posts
WHERE
post_data->>"$.categories[*].slug" = "site-news"
就像我说的那样,我发誓这是在早些时候工作,但现在我什么都没有回来。
以下是解释:
即使我删除了索引和生成的列,只使用普通的json字段,我仍然突然得不到任何东西。我可以使用的唯一结果是JSON_SEARCH
,但是有成千上万的记录,这些是相当大的json blob,并且搜索到的文本可能会出现在正文中
顺便说一句,类别字段看起来像这样
[{slug: "site-news", title: "Site News"}, {slug: "personal", title: "Personal"}]
标签遵循完全相同的结构
修改
我刚试过post_data->>"$.categories[0].slug" = "site-news"
并带来了记录。但是我需要where子句来考虑数组的所有元素,因为我不能保证这个类别的数组元素插槽。
正如MySQL的文档所述:[*] represents the values of all cells in the array.
https://dev.mysql.com/doc/refman/5.7/en/json-path-syntax.html
使用
的核心问题select
*
from blog_posts
WHERE
JSON_CONTAINS(post_data->"$.categories[*].slug", json_quote("site-news"))
是完全避免使用我的索引,这将是关键
答案 0 :(得分:1)
带有通配符的路径表达式返回一个值数组,作为JSON表示法中的数组。
SELECT post_data->>'$[*].slug' FROM blog_posts;
+---------------------------+
| post_data->>'$[*].slug' |
+---------------------------+
| ["site-news", "personal"] |
+---------------------------+
这显然不等于标量字符串' site-news'。
因此,您可以在JSON数组上使用JSON_SEARCH()来查找特定字符串:
SELECT * FROM blog_posts
WHERE JSON_SEARCH(post_data->>'$[*].slug', 'one', 'site-news') IS NOT NULL;
我用MySQL 8.0.3-rc测试了它。我加载了这些数据:
INSERT INTO blog_posts (post_id, date_published, post_data)
VALUES('blah blah', now(), '[{"slug": "site-news", "title": "Site News"}, {"slug": "personal", "title": "Personal"}]');
我知道这不是post_data的格式,但它仍然表明在JSON上使用通配符路径会返回一个数组。