【问题标题】:How to search for substring in array of JSON Field?如何在 JSON 字段数组中搜索子字符串?
【发布时间】:2021-11-10 16:43:20
【问题描述】:

我正在使用 Django 提供的 JSONField,并将此类数据存储在该字段中:

[
        {
            "number": 1,
            "text": "This text is about dogs"
        },
        {
            "number": 2,
            "text": "Only cats in this text here"
        },
        {
            "number": 3,
            "text": "However, this text does also contain dogs"
        },
    ]

我想要实现的是某种子字符串匹配 - 即,如果一个人搜索字符串 "dog",结果应该返回如下内容:

        {
            "number": 1,
            "text": "This text is about dogs"
        },
        {
            "number": 3,
            "text": "However, this text does also contain dogs"
        },

查看 Django 文档,似乎可以查询 JSON 字段,因此

Model.objects.filter(field__text__contains='dogs')

但是,contains 仅适用于单个字典值,不适用于存在字典数组时。

有什么建议吗?通过 Django ORM 或直接通过 Postgres。

【问题讨论】:

  • 您可能会找到使用 JSONPATH 查询的解决方案,但效果不佳。使用规范化的数据模型而不是 JSON 数组,练习会变得简单,查询也会很快。

标签: django postgresql django-orm


【解决方案1】:

我假设您正在搜索的表中有一个 ID 列,并且保持此信息完整是很重要的。你想要的只能用 Postgres 的 jsonb 数据类型来完成(至少,我想不出另一种方式),如果你需要在数据库中搜索,你可能应该重新考虑如何将它存储在数据库中没有任何顶级键的 json 对象数组,以便在查询中更轻松地搜索和引用。

也就是说,这是我对基本 postgres 查询的尝试,该查询在“文本”键值对中搜索匹配项,然后删除不匹配的值。

WITH search_set AS (
        SELECT  t.id,
                t.js
        FROM ( VALUES (1,'[{"number": 1,"text": "This text is about dogs"},{"number": 2,"text": "Only cats in this text here"},
        {"number": 3,"text": "However, this text does also contain dogs"}]'::jsonb) 
        ) AS t(id,js) 
        WHERE jsonb_path_exists(js, '$.text[*] ? (@ like_regex "(dogs)" flag "i")') 
)
SELECT rs.id,
      jsonb_agg(arr.elem)
FROM search_set rs,
jsonb_array_elements(rs.js) AS arr(elem)
WHERE
    arr.elem::varchar ILIKE '%dog%'
    GROUP BY rs.id 
 ;

【讨论】:

    猜你喜欢
    • 2022-01-23
    • 2013-05-10
    • 2011-07-04
    • 1970-01-01
    • 1970-01-01
    • 2021-04-25
    • 2023-04-05
    • 2017-10-29
    相关资源
    最近更新 更多