查找嵌套 JSON 文档中值大于 INT 的行
Find rows where value in nested JSON document is greater than INT
我是一个 PostgreSQL 新手。但我认为在关系数据库中使用 json/jsonb 听起来很有趣。
//仅供参考:我尝试通过 C# .NET Core WebAPI 和 Dapper 实现它
我想要一个带有(多维)json 列的 table,例如:
id | data
_____________________________________|_________________________________________________________________________________
|
4BF30FE6-D7DD-480B-8592-DC9676576FEF | { timestamps:{ "created":1578614541, "modified":1578615707 }, "type":"single"}
1AC2CD8F-09D0-456C-9FD4-B63E354BD324 | { timestamps:{ "created":1578614676, "modified":1578615921 }, "type":"multiple"}
50AD2D82-5919-4555-BCC2-B24E0DE24263 | { timestamps:{ "created":1578614552, "modified":1578615784 }, "type":"single"}
8C3BE671-17D1-49FD-A891-D5E69FDF7FC2 | { timestamps:{ "created":1578614685, "modified":1578615173 }, "type":"single"}
我想获取所有 data::timestamps.created 大于 1578614670 的 ID。
伪代码:
SELECT id, data FROM table WHERE data::timestamps.created > 1578614670;
id | data
_____________________________________|_________________________________________________________________________________
|
1AC2CD8F-09D0-456C-9FD4-B63E354BD324 | { timestamps:{ "created":1578614676, "modified":1578615921 }, "type":"multiple"}
8C3BE671-17D1-49FD-A891-D5E69FDF7FC2 | { timestamps:{ "created":1578614685, "modified":1578615173 }, "type":"single"}
有没有简单的方法可以做到这一点?
编辑:删除了 Erwin 指出的错误(并投票 )。保留其余答案,因为其他信息可能有用。
下面会按照你的要求去做。这里是 table.
CREATE TABLE example (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
data jsonb NOT NULL
);
一旦您插入数据,这将执行您想要的查询。
SELECT id, data
FROM "table"
WHERE (data->'timestamps'->>'created')::int8 > 1578614670;
这会从 JSONB column as text, and then converts to an 8-byte integer (64-bit int). For a sequential scan on a large table, this can be quite slow, so you'll want an expression index 中提取 "created" 条目。
CREATE INDEX created_idx ON "table" ((data->'timestamps'->>'created')::int8);
在比较之前降低嵌套的多个级别#>>
operator is useful. Then cast the extracted text
to an appropriate numeric type。
SELECT id, data FROM tbl
WHERE (data #>> '{timestamps,created}')::numeric > 1578614670;
相当于:
...
WHERE (data -> 'timestamps' ->> 'created')::numeric > 1578614670;
numeric
是安全的选择。如果您知道 created
中的所有数字都小于 2^31 或 2^63,您可以分别使用 integer
或 bigint
。您的示例显示了有效的数字文字,但这必须适用于 所有 提取的值。
为了加快速度,考虑像 Miles 建议的表达式索引,转换为适当的数字类型 - 但要有适当的括号。
CREATE INDEX tbl_data_created_idx
ON tbl (((data #>> '{timestamps,created}')::numeric)); -- all parentheses required
相关:
此处的所有内容都适用于类型 json
或 jsonb
,在这方面都是一样的。
db<>fiddle here(同时演示)
我是一个 PostgreSQL 新手。但我认为在关系数据库中使用 json/jsonb 听起来很有趣。
//仅供参考:我尝试通过 C# .NET Core WebAPI 和 Dapper 实现它
我想要一个带有(多维)json 列的 table,例如:
id | data _____________________________________|_________________________________________________________________________________ | 4BF30FE6-D7DD-480B-8592-DC9676576FEF | { timestamps:{ "created":1578614541, "modified":1578615707 }, "type":"single"} 1AC2CD8F-09D0-456C-9FD4-B63E354BD324 | { timestamps:{ "created":1578614676, "modified":1578615921 }, "type":"multiple"} 50AD2D82-5919-4555-BCC2-B24E0DE24263 | { timestamps:{ "created":1578614552, "modified":1578615784 }, "type":"single"} 8C3BE671-17D1-49FD-A891-D5E69FDF7FC2 | { timestamps:{ "created":1578614685, "modified":1578615173 }, "type":"single"}
我想获取所有 data::timestamps.created 大于 1578614670 的 ID。
伪代码:
SELECT id, data FROM table WHERE data::timestamps.created > 1578614670;
id | data _____________________________________|_________________________________________________________________________________ | 1AC2CD8F-09D0-456C-9FD4-B63E354BD324 | { timestamps:{ "created":1578614676, "modified":1578615921 }, "type":"multiple"} 8C3BE671-17D1-49FD-A891-D5E69FDF7FC2 | { timestamps:{ "created":1578614685, "modified":1578615173 }, "type":"single"}
有没有简单的方法可以做到这一点?
编辑:删除了 Erwin 指出的错误(并投票
下面会按照你的要求去做。这里是 table.
CREATE TABLE example (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
data jsonb NOT NULL
);
一旦您插入数据,这将执行您想要的查询。
SELECT id, data
FROM "table"
WHERE (data->'timestamps'->>'created')::int8 > 1578614670;
这会从 JSONB column as text, and then converts to an 8-byte integer (64-bit int). For a sequential scan on a large table, this can be quite slow, so you'll want an expression index 中提取 "created" 条目。
CREATE INDEX created_idx ON "table" ((data->'timestamps'->>'created')::int8);
在比较之前降低嵌套的多个级别#>>
operator is useful. Then cast the extracted text
to an appropriate numeric type。
SELECT id, data FROM tbl
WHERE (data #>> '{timestamps,created}')::numeric > 1578614670;
相当于:
...
WHERE (data -> 'timestamps' ->> 'created')::numeric > 1578614670;
numeric
是安全的选择。如果您知道 created
中的所有数字都小于 2^31 或 2^63,您可以分别使用 integer
或 bigint
。您的示例显示了有效的数字文字,但这必须适用于 所有 提取的值。
为了加快速度,考虑像 Miles 建议的表达式索引,转换为适当的数字类型 - 但要有适当的括号。
CREATE INDEX tbl_data_created_idx
ON tbl (((data #>> '{timestamps,created}')::numeric)); -- all parentheses required
相关:
此处的所有内容都适用于类型 json
或 jsonb
,在这方面都是一样的。
db<>fiddle here(同时演示)