如何在存储在json列中的数组中搜索元素?(Update: Also see the 9.4 updated answer for 101 columns.)

如果我有这样一个JSON文档,存储在一个名为blobjson列中:

{"name": "Wolf",
 "ids": [185603363281305602,185603363289694211]}

我想做的是:

SELECT * from "mytable" WHERE 185603363289694211 = ANY("blob"->'ids');

把所有匹配的行都取出来.但这不起作用,因为"blob"->'ids'返回的是JSON值,而不是Postgresarray.

如果可能的话,我还想在各个ID上建立一个索引.

推荐答案

The following original answer applies only for Postgres 9.3. For a Postgres 9.4 answer, see the Update below.

这是建立在Erwin's referenced answers的基础上的,但对这个问题来说更明确一点.

本例中的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;

我们本可以很容易地(也许更容易重用)在这里返回一个textarray.我怀疑在bigint上建立索引要比在text上建立索引快得多,但我很难在网上找到支持这一点的证据.

为了建立索引:

CREATE INDEX "myindex" ON "mytable" 
  USING GIN (json_array_bigint("blob"->'ids'));

对于查询,它可以工作并使用索引:

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

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

SELECT * FROM "mytable" 
  WHERE 185603363289694211 = ANY(json_array_bigint("blob"->'ids'));

Update for 9.4

Postgres 9.4引入了jsonb类型.This is a good SO answer about jsonb and when you should use it over json.简而言之,如果你要查询JSON,应该使用jsonb.

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

SELECT * FROM "mytable"
  WHERE blob @> '{"ids": [185603363289694211]}';

@>是Postgres的包含运算符,documented for jsonb here.

Mongodb相关问答推荐

MongoDB 4.4如何使用未知密钥更新dict

字段$set聚合导致错误美元($)前缀字段$concatArrays对于存储无效"

mongo如何通过聚合加载嵌套文档

mongoDB文档数组字段中的唯一项如何

判断对象数组中的值是否存在golang

聚合 $accumulator + $project

查找对象是否在预保存钩子mongoose中更改

声明多个模式后无法从数据库中获取数据(mongoose + express + mongodb

Mongoose.js 通过一个 connect() 调用创建到 MongoDB 的多个连接

Mongo按实际上是数字的字符串值排序

是否有支持 MongoDB 和 Devise 的 Rails 管理界面?

Flask:设置应用程序和请求特定的属性?

无法将 Mongoose 连接到 Atlas

如何在 Ubuntu 上安装 mongodb-clients 最新版本?

使用 mongoengine 将多文档插入到 mongodb

如何从mongoose中的对象 ID 获取创建日期?

PyMongo 创建具有 2 个或更多字段的唯一索引

在 mongodb 集合中查找最旧/最新的帖子

MongoDB Compass 中 JSON 输入意外结束

创建模型时出现mongoose错误