json - 在 Postgres 中收集递归 JSON 键

标签 json postgresql recursion

我在 Postgres 中以 JSON 数据类型 (Postgres 9.3) 存储了 JSON 文档,我需要递归地收集树下的键名。

例如,给定这个 JSON 树

{
 "files": {
  "folder": {
   "file1": {
    "property": "blah"
   },
   "file2": {
    "property": "blah"
   },
   "file3": {
    "property": "blah"
   },
   "file4": {
    "property": "blah"
   }
 }
},
"software": {
  "apt": {
    "package1": {
        "version": 1.2
    },
    "package2": {
        "version": 1.2
    },
    "package3": {
        "version": 1.2
    },
    "package4": {
        "version": 1.2
    }
  }
 }
}

我想提取类似 [file1,file2,file3,file3,package1,package2,package3,package4] 的内容

基本上只是我可以用于文本搜索索引的键列表。

我知道我可以使用类似的东西获得最外层对象上的键列表

SELECT DISTINCT(json_object_keys(data))

我知道可以使用类似

的方法递归地爬过树
WITH RECURSIVE data()

但我无法将两者放在一起。

有人能帮忙吗?

最佳答案

诀窍是在正确的位置使用 json_typeof 添加一些最终条件测试。

如果您不关心对象键顺序,您还应该使用 jsonb

这是我的工作环境:

CREATE TABLE test (
  id  SERIAL PRIMARY KEY,
  doc JSON
);

INSERT INTO test (doc) VALUES ('{
 "files": {
  "folder": {
   "file1": {
    "property": "blah"
   },
   "file2": {
    "property": "blah"
   },
   "file3": {
    "property": "blah"
   },
   "file4": {
    "property": "blah",
    "prop" : {
      "clap": "clap"
    }
   }
 }
},
"software": {
  "apt": {
    "package1": {
        "version": 1.2
    },
    "package2": {
        "version": 1.2
    },
    "package3": {
        "version": 1.2
    },
    "package4": {
        "version": 1.2
    }
  }
 }
}');

当第二个查询没有返回任何行时,递归停止。这是通过将一个空对象传递给 json_each 来完成的。

 WITH RECURSIVE doc_key_and_value_recursive(key, value) AS (
  SELECT
    t.key,
    t.value
  FROM test, json_each(test.doc) AS t

  UNION ALL

  SELECT
    t.key,
    t.value
  FROM doc_key_and_value_recursive,
    json_each(CASE 
      WHEN json_typeof(doc_key_and_value_recursive.value) <> 'object' THEN '{}' :: JSON
      ELSE doc_key_and_value_recursive.value
    END) AS t
)
SELECT *
FROM doc_key_and_value_recursive
WHERE json_typeof(doc_key_and_value_recursive.value) <> 'object';

关于json - 在 Postgres 中收集递归 JSON 键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30132568/

相关文章:

algorithm - 检测调度程序时间轴上的冲突(算法)

python - 如何在 python 中通过 jsonschema 过滤 json

sql - PostgreSQL : How to select values with only two digits after decimal point in a table?

sql - 如何在 Postgresql 中加入 array_agg 列的 View ?

mysql - 无法连接到AWS VPC RDS实例(mysql或postgres)

f# - 我如何知道一个函数在 F# 中是否是尾递归的

java - 字符串的递归扩展

php - 验证 JSON 是否在 PHP 上具有确定的结构

mysql - 从 MySQL 中的 JSON 数组中删除所有 JSON 对象

javascript - Angular 不会更改 json 中的音频源