我的数据库中有这个JSON:
{
"Id": 1,
"Questions": [
{
"QuestionId": 6,
"Description": "Question 1",
"Alternatives": [
{
"Index": 1,
"CorrectAnswer": false,
"AlternativeId": 26,
"QuestionId": 6,
"Description": "Alternative one",
"Selected": false
},
{
"Index": 2,
"CorrectAnswer": true,
"AlternativeId": 27,
"QuestionId": 6,
"Description": "Alternative two",
"Selected": false
}
]
},
{
"QuestionId": 7,
"Description": "Question 2",
"Alternatives": [
{
"Index": 1,
"CorrectAnswer": false,
"AlternativeId": 26,
"QuestionId": 6,
"Description": "Alternative one",
"Selected": false
},
{
"Index": 2,
"CorrectAnswer": true,
"AlternativeId": 27,
"QuestionId": 6,
"Description": "Alternative two",
"Selected": false
}
]
}
]
}
我在这份文件中只能提出一个问题。我尝试了以下查询:
select data#>'{Questions}' from db.my_table
where (data #> '{Questions,0,QuestionId}')::numeric = 6;
SELECT data ->> 'Questions' AS Questions FROM db.my_table
WHERE (data -> 'Questions' ->> 'QuestionId')::numeric = 6;
SELECT data ->> 'Questions' AS Questions FROM db.my_table
WHERE data -> 'Questions' ->> 'QuestionId' = '6'
我能做错什么?我总是得到0个受影响行的返回。
文档:
https://www.postgresql.org/docs/current/static/datatype-json.html https://www.postgresql.org/docs/current/static/functions-json.html
欢迎每一位帮助!
答案 0 :(得分:2)
让我们先谈谈你的每个问题:
select data#>'{Questions}' from db.my_table
where (data #> '{Questions,0,QuestionId}')::numeric = 6;
这实际上失败了(ERROR: cannot cast type json to numeric
)。您可以将where子句中的运算符更改为#>>
,它将不再出错 - #>>
返回可以强制转换为数字的文本。此时,查询将返回整个Questions
数组,而不是您想要的特定问题。
为什么呢?因为所有问题都属于同一行。
SELECT
返回行,其WHERE
子句对行进行操作。由于您在一行中有许多值,因此使用此方法有条件地提取json子对象时会遇到问题。
其他两个查询成功运行但没有产生结果:
SELECT data ->> 'Questions' AS Questions FROM db.my_table
WHERE (data -> 'Questions' ->> 'QuestionId')::numeric = 6;
SELECT data ->> 'Questions' AS Questions FROM db.my_table
WHERE data -> 'Questions' ->> 'QuestionId' = '6'
在这两种情况下,您都要在json blob中索引不存在的字段。 Questions
是一个数组,因此使用字符串对其进行索引并不起作用,但json足够宽松,可以让您尝试。换句话说,条款WHERE data -> 'Questions' ->> 'QuestionId' = '6'
根本不匹配任何行。
诀窍是将每个问题排成一行。这有点复杂,但并不难做到。
首先,查看函数json_array_elements
,看起来它应该工作 - 它需要一个json数组并将每个元素作为一行返回一个列(名为" value") 。乍一看,似乎你应该能够做一些形式的事情:
SELECT value FROM json_array_elements(...)
WHERE value ->> 'QuestionId'::numeric = 6;
不幸的是,它并不那么简单。这是一个有效的查询:
SELECT datatable.question
FROM my_table,
json_array_elements(my_table.data -> 'Questions') AS datatable(question)
WHERE (question->>'QuestionId')::numeric = 6;
好的,让我们稍微打破一下。最终,它会返回我们使用question
调用创建的datatable
表的json_array_elements
字段。 question
是一个json对象,我们过滤只返回QuestionID == 6
的对象。
但是,请注意,我们还要从my_table
中进行选择,因为最终是数据的来源。在这种情况下,我们会在my_table
和datatable
之间进行无约束的笛卡尔联接。这不好,可能不会很好地扩展。但它适用于我们目前只有几行的情况。
希望能给你一个开始的地方。