我正在尝试为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语法中实现该字段转换?
答案 0 :(得分:3)
由于@ e4c5报告了自Cast以来Django 1.10的Full 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)
答案 1 :(得分:1)
引入JSONB数据类型和JSON/JSONB functions的原因是为了避免这种搜索! Django ORM提供对大多数此功能的访问。 Func expression可用于使用双下划线符号等无法实现的功能。
另一方面,如果您的JSONB列中有一个大文本字段,则确实需要进行全文搜索。这表明数据库设计不是最佳的。该字段应该从JSON中删除,它应该是它自己的一个字段。
Django 1.10刚刚添加了Cast函数。
类Cast(表达式,output_field)
强制结果类型 表达式是output_field中的表达式。
如果您使用的是旧版本的Django,则可以使用RawSQL函数。您将在上面链接的同一页面上找到一个示例。请注意,RawSQL函数的使用与执行原始查询不同。
有一种观点认为使用RawSQL会使你的代码不可移植,你永远不应该使用它。这个问题涉及django.contrib.postgres包,你的代码绝对不是便携式的。因此,如果你想避免使用原始sql,它应该是出于可移植性以外的原因。