Ken*_* Li 5 postgresql index array json
如果您只想要简单的匹配,这很好用。假设在 JSON 数据中tracks同时具有Artist和Title字段。所以我们有类似的东西:
INSERT INTO tracks (id, data)
VALUES (1, '[{"artist": "Simple Plan", "title": "Welcome to My Life"}]');
Run Code Online (Sandbox Code Playgroud)
我们像在原始问题中一样创建索引:
CREATE INDEX tracks_artists_gin_idx ON tracks
USING GIN (json2arr(data, 'artist'));
CREATE INDEX tracks_title_gin_idx ON tracks
USING GIN (json2arr(data, 'title'));
Run Code Online (Sandbox Code Playgroud)
所以现在我们有两个字段要匹配。如您所见,如果我们执行以下原始查询(经过非常简单的修改):
SELECT *
FROM tracks
WHERE '{"ARTIST NAME"}'::text[] <@ (json2arr(data, 'artist'))
AND '{"TITLE"}'::text[] <@ (json2arr(data, 'title'))
Run Code Online (Sandbox Code Playgroud)
这将给出错误的答案,因为 JSON 数组中的艺术家和标题数组的索引不必匹配此查询以匹配 JSON 中的某些内容。执行此查询的正确方法是什么,以便我们可以获得所需的精确匹配?是否json2arr()需要改变?
编辑:为什么这是错误的
假设我们的表有如下记录:
INSERT INTO tracks (id, data) VALUES
(1, '[{"artist": "Simple Plan", "title": "Welcome to My Life"}]')
, (2, '[{"artist": "Another Artist", "title": "Welcome to My Life"},
{"artist": "Simple Plan", "title": "Perfect"}]');
Run Code Online (Sandbox Code Playgroud)
如果您查询如下:
SELECT *
FROM tracks
WHERE '{"Simple Plan"}'::text[] <@ (json2arr(data, 'artist'))
AND '{"Welcome to my Life"}'::text[] <@ (json2arr(data, 'title'))
Run Code Online (Sandbox Code Playgroud)
两条记录都会匹配(记录 1 和 2),即使您真的只想要第一条记录。
明确要求artist和必须在 JSON 数组的同一title元素中匹配,这一要求不会反映在您的查询中,该查询会查找至少一个元素与 匹配且另一个元素(可能是不同的元素)与 . 匹配的所有行。artisttitle
第一种情况的示例数据不确定,因为对于单个数组元素,查询不能以这种方式失败。不过,你的第二个例子很好地说明了这种情况。
有多种方法可以解决这个问题。一种方法是将每个 json 数组元素转换为由和组成的复合类型SQL 数组,并将整个类型匹配为一个。artisttitle
另一种方法是保留像现在这样的索引(或者甚至是跨越两个表达式的单个组合:(json2arr(data, 'artist'), json2arr(data, 'title'))。您当前的查询标识可能的data匹配项。为所有已识别的候选者取消嵌套 json 数组,并检查两者artist和是否在同一元素title上匹配。可能或可能效率不够。
jsonb在 Postgres 9.4 中更好地使用我不会详细介绍/pg 9.3,因为具有高级索引功能的Postgres 9.4json的发布基本上解决了这个问题。通过列上的本机 GIN 索引,可以更简单、更高效地实现这一点。有多种选择。针对当前案例进行优化:jsonbjsonb
CREATE TABLE tracks (id serial, data jsonb);Run Code Online (Sandbox Code Playgroud)
INSERT INTO tracks (id, data) VALUES
(1, '[{"artist": "Simple Plan", "title": "Welcome to My Life"}]')
, (2, '[{"artist": "Another Artist", "title": "Welcome to My Life"},
{"artist": "Simple Plan", "title": "Perfect"}]');
Run Code Online (Sandbox Code Playgroud)
指数:
CREATE INDEX tracks_data_gin_idx ON tracks USING gin (data jsonb_path_ops);
Run Code Online (Sandbox Code Playgroud)
询问:
SELECT * FROM tracks
WHERE data @> '[{"artist": "Simple Plan", "title": "Welcome to My Life"}]';
Run Code Online (Sandbox Code Playgroud)
JSON 值中的属性序列和无关紧要的空格对于jsonb. 我将 jsonb 的详细信息添加到 SO 上引用的答案中:
| 归档时间: |
|
| 查看次数: |
3504 次 |
| 最近记录: |