首页 > 解决方案 > Postgres:按注释/连接的 json 值搜索

问题描述

我有一个使用 postgres json 列的 django 模型。

class ClassName:
    json=JsonField()

这是 json 字段中的模式。

{
  'lev1': {
    'lev2': {
      first_name: 'Alex',
      last_name: 'Anderson',
      street: '242 Bell St,',
      city:'New York',
      state:'NY',
    }
}

现在我有了这些数据,我必须使用用户的全名和完整地址对其进行过滤。

我正在寻找类似的东西

ClassName.objects.annotate(
    full_name=Concat(F('lvl1__lvl2__first_name'), Value(' '),
                    F('lvl1__lvl2__last_name')),
    full_address=Concat(F('lvl1__lvl2__address'), Value(' '),
                        F('lvl1__lvl2__city'), Value(' '),
                        F('lvl1__lvl2__state'), Value(' '),
                        F('lvl1__lvl2__zipcode')),
).filter(full_name__icontains="Alex Anderson")

我尝试了所有不同的 json 函数,但无法获得正确的组合。

标签: djangopostgresqldjango-models

解决方案


不幸的是,Django 中有一个问题阻止在F函数中直接使用 JSON 字段...这会阻止您的代码工作...

解决方案是在您的代码中嵌入原始 SQL 片段。丑陋,但这就是我们所拥有的。

TestJsonAnn.objects.annotate(
    full_name=Concat(
        RawSQL("(json->'lev1'->'lev2'->>'first_name')", ()),
        Value(' '),
        RawSQL("(json->'lev1'->'lev2'->>'last_name')", ())
    )
).filter(full_name__icontains="Alex Anderson")

注意->>最后提取时使用的运算符而不是->. 这是必需的,因为->会将数据作为 JSON 对象返回,因此您的字符串将被额外引用,->>并将其作为字符串返回。有关在原始 SQL 中提取字段的更多信息,请参阅PostgreSQL 文档


推荐阅读