Django全文搜索JSON字段

时间:2016-08-08 17:24:58

标签: json django postgresql full-text-search

我正在尝试为Django 1.10实施新添加的全文搜索Postgres支持。

我尝试搜索的其中一个字段是JSON字段:

Product.objects.annotate(
    search=SearchVector('attributes'),
).filter(search=keyword)

如果我尝试使用SearchVector

进行以下搜索
django.db.utils.DataError: invalid input syntax for type json
LINE 1: ...ol1, to_tsvector(COALESCE("product"."attributes", '')) AS "s...
                                                         ^
DETAIL:  The input string ended unexpectedly.
CONTEXT:  JSON data, line 1:

会提出:

select to_tsvector(attributes::text) from product;

这是有道理的,像这样的原始SQL查询需要

var config = { ... }
firebase.initializeApp(config);

但是如何在Django语法中实现该字段转换?

2 个答案:

答案 0 :(得分:3)

由于@ e4c5报告了自Cast以来Django 1.10Full Text Search support for JSON and JSONB功能(与您使用的版本相同)。

因此,如果您要将JSON字段作为文本进行搜索,则必须将其转换为文本:

from django.contrib.postgres.search import SearchVector
from django.db.models import TextField
from django.db.models.functions import Cast

Product.objects.annotate(
    search=SearchVector(Cast('attributes', TextField())),
).filter(search=keyword)

您还可以在SearchVector中仅使用JSON字段的特定部分:

from django.contrib.postgres.search import SearchVector
from django.contrib.postgres.fields.jsonb import KeyTextTransform

Product.objects.annotate(
    search=SearchVector(KeyTextTransform('key1', 'attributes')),
).filter(search=keyword)

PostgreSQL 10添加了enter image description here

答案 1 :(得分:1)

为什么你不应该这样做

引入JSONB数据类型和JSON/JSONB functions的原因是为了避免这种搜索! Django ORM提供对大多数此功能的访问。 Func expression可用于使用双下划线符号等无法实现的功能。

另一方面,如果您的JSONB列中有一个大文本字段,则确实需要进行全文搜索。这表明数据库设计不是最佳的。该字段应该从JSON中删除,它应该是它自己的一个字段。

如果你还想这样做

Django 1.10刚刚添加了Cast函数。

  

类Cast(表达式,output_field)
   强制结果类型   表达式是output_field中的表达式。

如果您使用的是旧版本的Django,则可以使用RawSQL函数。您将在上面链接的同一页面上找到一个示例。请注意,RawSQL函数的使用与执行原始查询不同。

2018年1月更新

有一种观点认为使用RawSQL会使你的代码不可移植,你永远不应该使用它。这个问题涉及django.contrib.postgres包,你的代码绝对不是便携式的。因此,如果你想避免使用原始sql,它应该是出于可移植性以外的原因。