这个 SQL 语句有 django ORM 版本吗?
Posted
技术标签:
【中文标题】这个 SQL 语句有 django ORM 版本吗?【英文标题】:Is there a django ORM version of this SQL statement? 【发布时间】:2016-04-15 16:02:09 【问题描述】:使用 Django 1.9 和 Postgres 9.4。
我有一个名为 json_field
的 jsonb 字段。 json_field
可以包含密钥 title
,它可能看起来像 'the cow jumped over the moon'
。
所以我想搜索title
包含moon
的行。
使用以下原始 SQL 可以正常工作
SELECT * FROM web_file where (json_field ->> 'title')::text LIKE '%moon%';
但我宁愿使用 Django ORM。
编辑:
我想尝试一下(正如@kloddant 所指出的那样)
title = WebFile.objects.filter(json_field__title__contains='moon')
但它给出了以下错误
DataError: invalid input syntax for type json
LINE 1: ...le" WHERE "web_file"."json_field" -> 'title' @> 'moon' ORD...
^
DETAIL: Token "moon" is invalid.
CONTEXT: JSON data, line 1: moon
这里是相关的models.py
from django.contrib.postgres.fields import JSONField
class WebFile(MPTTModel):
json_field = JSONField(null=True, blank=True, default=dict())
这可能是 django 模型和 MPTTModel 之间的冲突,尽管我对此表示怀疑?
【问题讨论】:
JSONField 字段类型从何而来?它不是 Django 的一部分,也不是 MPTT 的一部分。 @MadWombat 它在 Django 1.9 中的新功能docs.djangoproject.com/es/1.9/ref/contrib/postgres/fields/… 您可能想阅读文档。 JSONField 不是字符串,因此看起来__contains
过滤器可能与字符串不同。 docs.djangoproject.com/es/1.9/ref/contrib/postgres/fields/…
阅读更多,看起来你需要将字典传递给__contains
【参考方案1】:
https://docs.djangoproject.com/es/1.9/ref/contrib/postgres/fields/
你会做这样的事情:
WebFile.objects.filter(json_field__title__contains='moon')
【讨论】:
我也这么认为,但它似乎不起作用:` DataError: invalid input syntax for type json LINE 1: ...le" WHERE "web_file"."json_field" -> 'title' @> 'moon' ORD... ^ DETAIL: token "moon" is invalid. CONTEXT: JSON data, line 1: moon ` 这很奇怪。WebFile.object.filter(json_field__title='moon')
工作吗(我的意思是工作是否找到标题为“月亮”的东西,我意识到它不会给你你想要的东西)?也许这与__contains
有关?【参考方案2】:
title = WebFile.objects.filter(title__icontains=moon)
当然,您必须先创建 WebFile 模型,然后从 models.py 文件中将其导入页面顶部。
【讨论】:
这不起作用,因为title
包含在json_field
中
如果你的数据库字段中有一个 json 对象,那么我会考虑重组你的数据库,如果可能的话,这样所有的 json 数据都在一个单独的表中,该表使用一个链接到 webfile 表外键。
有些用例是应用程序用户希望创建自己的无模式键值对,但我不想为每个用户创建一个新表。我认为我的用例与 Postgres 9.4 jsonb 可以做的非常一致。
@kloddant 不需要重组。 JSON 字段是 PostgreSQL 的一个特性,有很多真实的用例。它不能用来代替 NoSQL 数据库,但在某些情况下它肯定是有用的,尤其是 Django 内置的 Postgres 字段。【参考方案3】:
您没有使用来自django.contrib.postgres.fields
的JSONField
吗?在那种情况下,它只是like this:
WebFile.objects.filter(json_field__title__contains='moon')
可以发一下相关的models.py
吗?此外,如果您不使用 django.contrib.postgres.fields
并依赖默认模型(例如手动扩展 CharField
或其他东西),您将会遇到困难。
【讨论】:
我已经发布了model.py
您尝试过我发布的方法吗?问题是您无法过滤title
上的对象,因为title
不是WebFile
的属性。此外,您的 default
应该是可调用的。使用dict
作为空默认值。从文档中:“错误地使用 default= 创建了一个可变的默认值,在 JSONField 的所有实例之间共享。”
是的,我已经尝试过您的方法,但我收到了一个错误(我已将错误包含在我的问题中)。感谢您在默认值上的指针。以上是关于这个 SQL 语句有 django ORM 版本吗?的主要内容,如果未能解决你的问题,请参考以下文章