【发布时间】:2021-05-30 19:05:12
【问题描述】:
我有一个名为 myContent 的 JSONB 列,每行的 JSON 中的一个对象如下所示:
"metadata": {
"key": "key",
"teamBased": false,
}
我想选择所有 teamBased 为 false 的行。
这是我的查询的样子:
set enable_seqscan=false;
EXPLAIN ANALYZE
SELECT *
FROM table n
WHERE n.key = 'key'
AND myContent @> ALL(array[:searchTerms]::jsonb[]));
我从我的 Java 应用程序中将 searchTerms 作为数组发送,在这种情况下,该数组如下所示:
['{"metadata":{"teamBased":false}}']
我创建了一个如下所示的 GIN 索引:
create index "myIndex"
on myTable using gin (myContent);
当我查看explain analyze query 的输出时,我发现它没有使用我的索引。但是,如果我将查询更改为此
set enable_seqscan=false;
EXPLAIN ANALYZE
SELECT *
FROM table n
WHERE n.key = 'key'
AND myContent @> '{"metadata":{"teamBased":false}}';
它确实使用了它,所以我假设它与我在原始查询中的搜索词数组存在问题。但是,我真的需要这样的查询,因为这个查询也用于其他情况,当我需要多个搜索词时。
这可能是什么问题?另外,如何修改我的 GIN 索引,使其不设置为整个 JSON,而是设置为其中一个对象,例如 metadata?
谢谢!
【问题讨论】:
-
如果您只有一个元素,我不明白您为什么要使用数组进行比较。
-
@a_horse_with_no_name 在这种特殊情况下,我只有一个元素。在其他情况下,我有不止一个。我在所有情况下都重复使用相同的查询。如果我有多个搜索词,这个索引不应该工作吗?
-
@a_horse_with_no_name 我不确定“该列仅包含一个元素”是什么意思。如果我在问题中添加了一些带有 json 的行,那么查询中的 where 子句将如下所示:
@> ALL(array['{"metadata":{"teamBased":false}}', '{"metadata":{"key":"key"}}']::jsonb[])并且它工作得很好。它选择所有在其 json 中具有值为“key”且teamBased为 false 的键的行。因此,它基本上匹配这两个搜索词。 -
您是否尝试取消嵌套数组并加入?
-
@clamp 我不确定你的意思。能否提供一段代码?
标签: postgresql jsonb