在Postgres JSON数组中查询

Joe*_*haw 19 arrays postgresql json mongodb postgresql-9.3

您将如何搜索存储在json列中的数组中的元素? (更新:另请参阅jsonb列的9.4更新答案.)

如果我有这样的JSON文档,则存储在json名为的列中blob:

{"name": "Wolf",
 "ids": [185603363281305602,185603363289694211]}
Run Code Online (Sandbox Code Playgroud)

我希望能做的是:

SELECT * from "mytable" WHERE 185603363289694211 = ANY("blob"->'ids');
Run Code Online (Sandbox Code Playgroud)

并获取所有匹配的行.但这不起作用,因为"blob"->'ids'返回JSON值,而不是Postgres数组.

如果可能的话,我还想建立个人ID的索引.

Joe*_*haw 14

以下原始答案仅适用于Postgres 9.3.有关Postgres 9.4的答案,请参阅下面的更新.

这建立在Erwin的参考答案的基础上,但对这个问题更加明确.

在这种情况下的ID是bigints,因此创建一个帮助函数,用于将JSON数组转换为Postgres bigint数组:

CREATE OR REPLACE FUNCTION json_array_bigint(_j json)
  RETURNS bigint[] AS
$$
SELECT array_agg(elem::text::bigint)
FROM json_array_elements(_j) AS elem
$$
  LANGUAGE sql IMMUTABLE;
Run Code Online (Sandbox Code Playgroud)

我们可以轻松(也许更可重复)text在这里返回一个数组.我怀疑索引的bigint速度要快得多,text但我很难在网上找到证据来支持这一点.

用于构建索引:

CREATE INDEX "myindex" ON "mytable" 
  USING GIN (json_array_bigint("blob"->'ids'));
Run Code Online (Sandbox Code Playgroud)

对于查询,这适用于并使用索引:

SELECT * FROM "mytable" 
  WHERE '{185603363289694211}' <@ json_array_bigint("blob"->'ids');
Run Code Online (Sandbox Code Playgroud)

这样做也可以用于查询,但它不使用索引:

SELECT * FROM "mytable" 
  WHERE 185603363289694211 = ANY(json_array_bigint("blob"->'ids'));
Run Code Online (Sandbox Code Playgroud)

更新9.4

Postgres 9.4介绍了这种jsonb类型. 这是一个很好的答案jsonb,当你应该使用它时json.简而言之,如果您曾经查询过JSON,那么您应该使用jsonb.

如果您将列构建为jsonb,则可以使用此查询:

SELECT * FROM "mytable"
  WHERE blob @> '{"ids": [185603363289694211]}';
Run Code Online (Sandbox Code Playgroud)

@>是Postgres的包含运算符,jsonb此处记录.感谢Alain的回答让我注意到这一点.


Erw*_*ter 5

首先,尝试运算符->>而不是->从数组值中剥离JSON层.

接下来,查询可以像这样工作:
如何使用新的PostgreSQL JSON数据类型中的字段进行查询?

索引可能的工作是这样的:
指数以JSON阵列发现的元素