使用 jooq/postgresql 从 json 中提取键/值对 - java

Posted

技术标签:

【中文标题】使用 jooq/postgresql 从 json 中提取键/值对 - java【英文标题】:Extracting key/value pairs from json using jooq/postgresql - java 【发布时间】:2017-02-04 00:04:51 【问题描述】:

我在 PostgreSQL 数据库列中有以下格式的 json 数据:

myData ["key1": "value1", "key2": "value2", "key1": "value1", "key2": "value2" ]

其中myData 是一个包含两个对象的数组。 我阅读了以下链接以仅使用 java 解决我的问题,但我的问题略有不同。 Converting JSON to Java 和 Parsing JSON Object in Java

    在数据库 (postgresql) 中提取键/值对会更有效,还是应该在 java 中获取整个字符串并使用 java 库?甚至可以在数据库中进行吗?

    如果可以在数据库中执行此操作,JOOQ 是否对此提供任何支持?

    如果在 Java 中解析是更好的选择,以上链接中给出的两个库中哪个更稳定/更高效? org.json 或 Gson

【问题讨论】:

对于 (1),我怀疑如果你在 postgres 中使用 jsonb 列会更快。 here 你有一个很好的 Java 和 PostgreSQL 实现示例。我喜欢这种选择select jsonColumn->'key1'->'subKey1' from myTable 【参考方案1】:

您有几个有趣的问题。

1。数据库中的查询逻辑与 Java 中的查询逻辑

取决于。首先,在 PostgreSQL 中,jsonb 有更好的索引支持。我不是该主题的专家,但我敢肯定,一旦您对 1-2 个事物进行基准测试,您就会得出这个结论。这是一篇有趣的博文,比较了 PostgreSQL 中不同数据类型的性能:

http://www.databasesoup.com/2015/01/tag-all-things.html

... 这让我想到是将谓词放入 SQL 查询中,还是稍后在 Java 中执行它们。一般来说:把它放在数据库中。如果您的谓词非常有选择性,那么您可以:

    避免大量不必要的 I/O 数据库中 使用数据库避免大量不必要的 I/O

这两种方法都可以大大降低您的查询延迟。如果您的谓词不是很有选择性,那么这几乎不是问题,除非在极端负载下。但是,如果您的系统处于极端负载下并且您的谓词选择性的,那么如果您在数据库中运行谓词,您仍然会大大减少该负载。

2。 jOOQ 对 JSON 谓词的支持

jOOQ 目前不提供任何开箱即用的 JSON(B) 谓词支持,但您可以使用 jOOQ 的纯 SQL 支持轻松地自己构建实用程序:

http://www.jooq.org/doc/latest/manual/sql-building/plain-sql

本质上,只要写:

public static Condition someJsonPredicate(Field<?> someJsonColumn, String someValue) 
    return DSL.condition("some_json_predicate(0, 1)", 
        someJsonColumn, DSL.val(someValue));

3。 org.json vs Gson

我不会在这里回答这部分,因为您的基准可能与我的不同。

【讨论】:

【参考方案2】:

从 Java 中的 PostgreSQL 数据库获取 JSON 数据的解决方案。

this article的总结。 我发现此答案的最后一部分非常强大且易于阅读。很容易将它包装在一个方法中 代码用于提供视觉提示,而不是完整的工作示例。 此答案不要使用 jooq。

PostgreSQL JSON(存储为文本)和 JSONB(存储为二进制)的比较

JSON JSONB
Stores data in text format Stores data in decomposed binary format
Input is fast, as no conversion are required Input is slightly slower, as there is an overhead related to binary conversion
Processing functions must re-parse the data on each execution Re-parsing is not needed, making data processing significantly faster
All white space and line feeds in the input are preserved as-is Extra white space and line feeds are stripped
Indexing is not supported Indexing is supported
Duplicate keys are retained, processing functions only consider the last value Duplicate keys are purged at input, only the last value is stored
Order of the keys is preserved Order is not preserved

数据库结构

my_table
   id = PK
   json_column = JSON or BYTEA

json_column 的数据示例

    "customer_name": "John", "items":  "description": "milk", "quantity": 4  
    "customer_name": "Susan", "items":  "description": "bread", "quantity": 2  

JAVA解析json(bof bof...)

String sql = "select json_column from my_table";
Statement stmt = conn.createStatement(...);
ResultSet rs = stmt.executeQuery(sql);
 
while(rs.next()) 
   // Not really true as data are store in binary, not nice to parse it in string here...
   JSONObject json = new JSONObject(rs.getString(1));
   JSONObject json2 = (JSONObject)json.get("items");
   System.out.println(json.get("customer_name"));
   System.out.println(json2.get("quantity"));

PostgreSQL(喜欢这部分!

select json_column->'customer_name' from my_table
select json_column->'items'->'quantity' from my_table

两者(非常好的解决方案)

sql = "select json_column->'items'->'quantity' from my_table";
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
while(rs.next()) 
   rs.getInt(1);
   ...

【讨论】:

以上是关于使用 jooq/postgresql 从 json 中提取键/值对 - java的主要内容,如果未能解决你的问题,请参考以下文章

使用 PHP 从 JSON 中删除

使用 jQuery 从 JSON 填充表

如何使用 SwiftyJSON 从 JSON 对象中获取 JSON 密钥?

使用 Cloudant 从 JSON 数组中检索 JSON 对象

如何使用 JSON 输入字符串从编排中调用 JSON 解码器?

使用改造从(本地)android资产文件夹获取Json数据