【问题标题】:Query for exact json keys match in Postgresql (Exacly these keys)在 Postgresql 中查询精确的 json 键匹配(正是这些键)
【发布时间】:2016-10-22 14:08:46
【问题描述】:

我正在尝试在名为 data_filters 的 jsonb 列中查询包含键 ['kommune'、'fylke'、'år'] 的行。

据我所知,postgres 只有这个运算符?&,它为我提供了所有具有所有这些键的行,但是我不想要也具有(例如)键“爱好”的行。到目前为止,我正在使用这个:

select * from main_dataitem 
where array['fylke', 'kommune', 'år'] @> ARRAY(select jsonb_object_keys(data_filters)) 
and ARRAY(select jsonb_object_keys(data_filters)) @> array['fylke', 'kommune', 'år'];

但这似乎不是一个最佳解决方案,有没有人有更好的方法来查询这个?

为了清楚起见,这并没有给出想要的结果,因为它匹配包含指定键和任意键(我没有指定)的行:

select * from main_dataitem where data_filters ?& array['fylke', 'kommune', 'år'];

【问题讨论】:

  • 要获得有序数组,您可以使用array(select x from jsonb_object_keys(data_filters) as a(x) order by x) 并将其与仅使用= 的有序常量数组进行比较。
  • 在这种情况下我将不得不对两个数组进行排序,不是吗?这也更快吗?
  • 1) 是的,两个数组都应该排序 (array[1,2] != array[2,1]) 2) 试试看。 IMO 它应该更快,但我不喜欢将结构化数据存储为 JSON,所以我在使用它方面没有太多经验。

标签: postgresql jsonb


【解决方案1】:

应该是最快的(纯C函数除外):

create or replace function jsonb_same_keys(p_json jsonb, p_keys text[])
returns boolean immutable strict language plpythonu as $$
  import json
  j = json.loads(p_json).keys()
  return sorted(j) == sorted(p_keys)
$$;

select jsonb_same_keys('{"1":2,"2":1}'::jsonb, array['2','1']);
╔═════════════════╗
║ jsonb_same_keys ║
╠═════════════════╣
║ t               ║
╚═════════════════╝

当然你应该在PostgreSQL中安装Python和语言扩展:create extension plpythonu;

【讨论】:

    【解决方案2】:

    不确定这是否仍然相关(考虑到这是 > 1 年前提出的),但我最近偶然发现了这个问题。

    如果您使用的是 jsonb,您还可以使用 - 运算符。这会从 JSON 值中删除一组或多组键。如果您只查询具有指定键的对象,则此操作的结果应为空 JSON ({})。

    所以查询将是:

    select * from main_dataitem where (data_filters - array['fylke', 'kommune', 'år']) = '{}';
    

    与@Abelisto 的回答相关(仅出于完整性考虑),您还可以使用jsonb_object_keys / json_object_keys 函数进行JSON 密钥提取和排序。像这样的:

    select * from main_dataitem where array(select x from jsonb_object_keys(data_filters) as x order by x) = array['fylke', 'kommune', 'år'];
    

    在我自己的测试数据集(约 330k 行)中,我发现这比我上面提出的第一个替代方案要慢得多。

    另外,我在 PostgreSQL 10.0 中做了这个。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多