【问题标题】:django rawsql postgres nested json/jsonb querydjango rawsql postgres 嵌套 json/jsonb 查询
【发布时间】:2018-03-13 18:42:44
【问题描述】:

我在 postgres 上有一个名为 data 的 jsonb 结构,其中每一行(大约有 300 万行)如下所示:

[
    {
        "number": 100,
        "key": "this-is-your-key",
        "listr": "20 Purple block, THE-CITY, Columbia",
        "realcode": "LA40",
        "ainfo": {
            "city": "THE-CITY",
            "county": "Columbia",
            "street": "20 Purple block",
            "var_1": ""
        },
        "booleanval": true,
        "min_address": "20 Purple block, THE-CITY, Columbia LA40"
    },
    .....
]

我想以最快的方式查询min_address 字段。在 Django 中我尝试使用:

APModel.objects.filter(data__0__min_address__icontains=search_term)

但这需要很长时间才能完成(另外,“THE-CITY”是大写的,所以我必须在这里使用icontains。我尝试像这样下降到rawsql:

cursor.execute("""\
    SELECT * FROM "apmodel_ap_model" 
    WHERE ("apmodel_ap_model"."data" 
    #>> array['0', 'min_address'])
    @> %s \
    """,\
    [json.dumps([{'min_address': search_term}])]
)

但这会给我带来奇怪的错误,例如:

LINE 4:       @> '[{"min_address": "some lane"}]'       
              ^
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.

我想知道使用 rawsql 游标查询字段 min_address 的最快方法是什么。

【问题讨论】:

  • data 字段包含一个 JSON,它实际上是一个包含大量对象的数组。您真的要仅在数组的第一个对象 (data__0__min_address) 中搜索 min_address 吗?
  • @cezar:你是对的 - 我想搜索数组中的所有对象。我该怎么做呢?这就是我想要进行 rawSQL 搜索的原因。

标签: django postgresql psycopg2 django-orm


【解决方案1】:

迟到的答案,可能不再帮助OP了。此外,我根本不是 Postgres/JSONB 方面的专家,所以这可能是个糟糕的主意。

鉴于此设置;

so49263641=# \d apmodel_ap_model;
         Table "public.apmodel_ap_model"
 Column | Type  | Collation | Nullable | Default
--------+-------+-----------+----------+---------
 data   | jsonb |           |          |

so49263641=# select * from apmodel_ap_model ;
                                           data
-------------------------------------------------------------------------------------------
 [{"number": 1, "min_address": "Columbia"}, {"number": 2, "min_address": "colorado"}]
 [{"number": 3, "min_address": "  columbia "}, {"number": 4, "min_address": "California"}]
(2 rows)

以下查询将对象从data 数组“扩展”到各个行。然后它将模式匹配应用于min_address 字段。

so49263641=# SELECT element->'number' as number, element->'min_address' as min_address 
    FROM apmodel_ap_model ap, JSONB_ARRAY_ELEMENTS(ap.data) element 
    WHERE element->>'min_address' ILIKE '%col%';
 number |  min_address
--------+---------------
 1      | "Columbia"
 2      | "colorado"
 3      | "  columbia "
(3 rows)

但是,我怀疑它是否会在大型数据集上表现良好,因为在模式匹配之前将 min_address 值转换为文本。

编辑:这里有一些关于索引 JSONB 数据以供搜索 https://stackoverflow.com/a/33028467/1284043 的好建议

【讨论】:

    猜你喜欢
    • 2023-04-07
    • 1970-01-01
    • 2017-11-25
    • 1970-01-01
    • 2017-01-28
    • 2023-04-03
    • 2019-03-14
    • 1970-01-01
    • 2021-02-18
    相关资源
    最近更新 更多