iGE*_*GEL 7 postgresql ruby-on-rails paper-trail-gem jsonb postgresql-9.6
背景:我们使用 PaperTrail 来保存我们不断变化的模型的历史。现在我想查询属于某个客户的项目。PaperTrail 可选择存储object_changes,我需要查询此字段以了解何时使用此 ID 创建或更改为此 ID。
我的表看起来像这样简化:
item_type | object_changes
----------|----------------------------------------------------------
"Item" | {"customer_id": [null, 5], "other": [null, "change"]}
"Item" | {"customer_id": [4, 5], "other": ["unrelated", "change"]}
"Item" | {"customer_id": [5, 6], "other": ["asht", "asht"]}
Run Code Online (Sandbox Code Playgroud)
如何查询从 ID 5 更改为或更改为 ID 5 的元素(所以上面的所有行)?我试过:
SELECT * FROM versions WHERE object_changes->'customer_id' ? 5;
Run Code Online (Sandbox Code Playgroud)
这让我:
Run Code Online (Sandbox Code Playgroud)ERROR: operator does not exist: jsonb ? integer LINE 1: ...T * FROM versions WHERE object_changes->'customer_id' ? 5; ^ HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
对于jsonb中包含运营商@>做你问什么:
获取数字5是“customer_id”数组元素的所有行:
SELECT *
FROM versions
WHERE object_changes->'customer_id' @> '5';
Run Code Online (Sandbox Code Playgroud)
该@>运营商期望jsonb做为右值-或者一个字符串,其有效期为jsonb(同时?预计text)。您在示例 ( ) 中提供的没有单引号的数字文字5不能强制为jsonb(nor text),它默认为integer. 因此出现错误消息。有关的:
这可以通过不同的索引样式来支持。对于我上面建议的查询,使用表达式索引(专用、小而快):
CREATE INDEX versions_object_changes_customer_id_gin_idx ON versions
USING gin ((object_changes->'customer_id'));
Run Code Online (Sandbox Code Playgroud)
这个替代查询也有效:
SELECT * FROM versions WHERE object_changes @> '{"customer_id": [5]}';
Run Code Online (Sandbox Code Playgroud)
并且可以通过通用索引来支持(更通用、更大、更慢):
CREATE INDEX versions_object_changes_gin_idx ON versions
USING gin (object_changes jsonb_path_ops);
Run Code Online (Sandbox Code Playgroud)
有关的:
根据手册,操作员?搜索任何top-level key within the JSON value。测试表明,字符串数组中被视为“顶级钥匙”,但数字是不是(键具有毕竟是字符串)。所以虽然这个查询可以工作:
SELECT * FROM versions WHERE object_changes->'other' ? 'asht';
Run Code Online (Sandbox Code Playgroud)
您在数组中查找数字的查询不会(即使您正确引用输入字符串文字)。它只会找到(带引号的!)字符串"5",归类为key,而不是(不带引号的)数字5,归类为value。
旁白:标准 JSON 只知道 4 个原语:string、number、boolean和null。没有整数原语(即使我听说过软件添加它),integer只是number 的一个子集,它numeric在 Postgres 中实现:
所以你的问题标题有点误导,因为严格来说没有“整数”成员。
| 归档时间: |
|
| 查看次数: |
2047 次 |
| 最近记录: |