2

背景:我们使用PaperTrail来保存我们不断变化的模型的历史。现在我想查询一个属于某个客户的项目。 PaperTrail可选择存储object_changes,我需要查询此字段以了解何时使用此ID创建或更改为此ID。查询整数成员的jsonb数组

我的表看起来简化这样的:

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"]} 

如何查询元素从或ID 5(所以上面的所有行)改变了吗?我想:

SELECT * FROM versions WHERE object_changes->'customer_id' ? 5; 

这让我:

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. 
+0

您可能还喜欢'where_object_changes'方法。它应该是为'object_changes'列做一个'where'子句的简便方法。 –

+0

那么你有你的答案吗? –

回答

0

对于jsonbcontains operator @>做你问什么:

获取的所有行数是“customer_id”数组的一个元素:

SELECT * 
FROM versions 
WHERE object_changes->'customer_id' @> '5'; 

@>运营商期望jsonb作为右操作数 - 或字符串文字,其有效期为jsonb(而?预计text)。您在示例(5)中提供的没有单引号的数字文字不能被强制为jsonb(也不是text),它默认为integer。因此错误信息。相关阅读:

这可以用不同的指数风格支持。对于我上面的查询建议,使用表达式指数(专,小而快):

CREATE INDEX versions_object_changes_customer_id_gin_idx ON versions 
USING gin ((object_changes->'customer_id')); 

这种替代查询工作,太:

SELECT * FROM versions WHERE object_changes @> '{"customer_id": [5]}'; 

,可以与一般的指数支持(更灵活,更大,更慢):

CREATE INDEX versions_object_changes_gin_idx ON versions 
USING gin (object_changes jsonb_path_ops); 

相关:

According to the manual,操作者?搜索任何top-level key within the JSON value。测试表明,在数组中被认为是“顶级键”,但数字(键必须是字符串毕竟)。因此,尽管此查询将工作:

SELECT * FROM versions WHERE object_changes->'other' ? 'asht'; 

您的查询在数组中寻找不会(甚至当你引用输入字符串字面正确)。它只会找到(引号)字符串"5",归类为,但不包括(未加引号)的号码5,归类为

旁白:Standard JSON only knows 4 primitives布尔。没有整数原语(即使我听说过的软件,并补充说),整数,这是在Postgres的实现为numeric一个公正的一个子集:

所以你的问题标题有点误导,因为没有“整数”成员,严格来说。

0

使用横向联合和jsonb_array_elements_text函数来处理每行的object_changes

SELECT DISTINCT v.* FROM versions v 
JOIN LATERAL jsonb_array_elements_text(v.object_changes->'customer_id') ids ON TRUE 
WHERE ids.value::int = 5; 

DISTINCT是唯一必要的,如果customer_id你正在寻找可以在阵列中出现多次(如不同的领域但是customer_id被跟踪)。