2

我的数据库上有这个 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

欢迎任何帮助!

4

1 回答 1

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 数组并将每个元素作为一行返回,其中包含一列(名为“值”)。乍一看,您似乎应该能够执行以下形式的操作:

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的表的字段。是一个 json 对象,我们过滤以仅返回.datatablejson_array_elementsquestionQuestionID == 6

但请注意,我们也在选择 from my_table,因为最终这就是数据的来源。在这种情况下,我们在 和 之间进行无约束的笛卡尔my_table连接datatable。这不好,而且可能不会很好地扩展。但它适用于我们目前只有几行的情况。

希望这能给你一个开始的地方。

于 2017-10-04T18:36:51.603 回答