【问题标题】:Unknown duplicates from querying a nested JSON来自查询嵌套 JSON 的未知重复项
【发布时间】:2017-02-26 00:29:10
【问题描述】:

我想在表格中的 JSON 对象中进行文本搜索。

我有一个名为 Audio 的表,其结构如下:

id| keyword | transcript | user_id | company_id | client_id 
-----------------------------------------------------------

这是transcript的JSON数据结构:

{"transcript": [
    {"duration": 2390.0, 
    "interval": [140.0, 2530.0], 
    "speaker": "Speaker_2", 
    "words": [
        {"p": 0, "s": 0, "e": 320, "c": 0.545, "w": "This"}, 
        {"p": 1, "s": 320, "e": 620, "c": 0.825, "w": "call"}, 
        {"p": 2, "s": 620, "e": 780, "c": 0.909, "w": "is"}, 
        {"p": 3, "s": 780, "e": 1010, "c": 0.853, "w": "being"}, 
        {"p": 4, "s": 1010, "e": 1250, "c": 0.814, "w": "recorded"}
        ]
    }, 
    {"duration": 4360.0, 
    "interval": [3280.0, 7640.0], 
    "speaker": "Speaker_1", 
    "words": [
        {"p": 5, "s": 5000, "e": 5020, "c": 0.079, "w": "as"},
        {"p": 6, "s": 5020, "e": 5100, "c": 0.238, "w": "a"},
        {"p": 7, "s": 5100, "e": 5409, "c": 0.689, "w": "group"},
        {"p": 8, "s": 5410, "e": 5590, "c": 0.802, "w": "called"},
        {"p": 9, "s": 5590, "e": 5870, "c": 0.834, "w": "tricks"}
        ]
    },
    ...
}

我要做的是在“words”中的“w”字段中进行文本搜索。这是我尝试运行的查询:

WITH info_data AS (
    SELECT transcript_info->'words' AS info
    FROM Audio t, json_array_elements(transcript->'transcript') AS transcript_info)
SELECT info_item->>'w', id
FROM Audio, info_data idata, json_array_elements(idata.info) AS info_item
WHERE info_item->>'w' ilike '%this';

现在我只有四列数据,第五列为空。总共有五列。但是,我得到了以下结果,即使没有数据的列也会产生输出:

?column? | id 
----------+----
 This     |  2
 This     |  5
 This     |  1
 This     |  3
 This     |  4
 This     |  2
 This     |  5

我很想知道我的查询存在什么问题,以及是否有更有效的方法来执行此操作。

【问题讨论】:

    标签: json postgresql jsonb


    【解决方案1】:

    问题是您一方面在表Audio 和另一方面info_datainfo_item 之间进行笛卡尔连接(后两者之间存在隐式横向连接):

    FROM Audio, info_data idata, json_array_elements(idata.info) AS info_item
    

    您可以通过在 CTE 中添加 Audio.id 然后添加 WHERE Audio.id = info_data.id 来解决此问题。

    这是否是最有效的解决方案值得怀疑(CTE 很少如此)。如果你只是想得到那些单词“this”是成绩单中的单词的行,那么你很可能像这样更好:

    SELECT DISTINCT id
    FROM (
        SELECT id, transcript_info->'words' AS info
        FROM Audio, json_array_elements(transcript->'transcript') AS transcript_info) AS t,
        json_array_elements(info) AS words
    WHERE words->>'w' ILIKE 'this';
    

    请注意,模式字符串中的% 效率非常低。由于除了“this”以外的英语单词很少有相同的结尾,我冒昧地删除了它。

    【讨论】:

    • 非常感谢!在过去的几个小时里,我一直在挣扎。这是我正在寻找的更好的解决方案!
    • 您是否知道如何解决 sqlalchemy 中的隐式横向连接问题?我试图将您的建议转换为 sqlalchemy 查询,并且遇到了完全相同的问题。在此处查看更多信息:stackoverflow.com/questions/41050712/…
    • 我不能在这里帮助你,因为我不知道 SQLAlchemy。然而,一个万无一失的解决方案是将上述查询包装在一个视图中,省略WHERE 子句并根据需要将尽可能多的其他列添加到选择列表中(至少words)。在 SQLAlchemy 中,您可以简单地从视图中 SELECT 并附加 WHERE 子句。这是一种适用于所有数据库框架(Hibernate、rails 等)的可靠方法:将所有查询复杂性留在数据库中,并在框架中做简单的事情。
    猜你喜欢
    • 2019-10-12
    • 2019-05-05
    • 2019-12-06
    • 2019-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-21
    相关资源
    最近更新 更多