如何编写查询以在 django 的 json 字段中查找值
Posted
技术标签:
【中文标题】如何编写查询以在 django 的 json 字段中查找值【英文标题】:how to write a query to get find value in a json field in django 【发布时间】:2012-05-13 18:46:45 【问题描述】:我的数据库中有一个 json 字段,类似于
jsonfield = 'username':'chingo','reputation':'5'
如何编写查询,以便查找用户名是否存在。像
username = 'chingo'
query = User.objects.get(jsonfield['username']=username)
我知道上面的查询是错误的,但我想知道是否有办法访问它?
【问题讨论】:
【参考方案1】:如果你使用的是 django-jsonfield 包,那么这很简单。假设你有一个这样的模型:
from jsonfield import JSONField
class User(models.Model):
jsonfield = JSONField()
然后要搜索具有特定用户名的记录,您可以这样做:
User.objects.get(jsonfield__contains='username':username)
【讨论】:
显然它不适用于最后一个(1.0.3)jsonfield。 那么解决办法是什么。我正在使用 1.0.3 @VladE.Borovtsov 嗯,我记得我找到了一些不好的解决方案。但最终停止使用该字段。很久以前在 postgres 中使用原生 json 字段。 @ShashankHegde 是的。即使我会尝试从 mysql 迁移到 postgres 并开始使用其内置的 JsonField 和 django 1.9。感谢回复 你可以使用User.objects.get(jsonfield__contains='"username":""'.format(username))
【参考方案2】:
从 Django 1.9 开始,您已经能够使用 PostgreSQL 的原生 JSONField。这使得搜索 JSON 变得非常简单。在您的示例中,此查询将起作用:
User.objects.get(jsonfield__username='chingo')
如果您有旧版本的 Django,或者您正在使用 Django JSONField 库与 MySQL 或类似的东西兼容,您仍然可以执行查询。
在后一种情况下,jsonfield
将被存储为文本字段并在带入 Django 时映射到字典。在数据库中,你的数据会这样存储
"username":"chingo","reputation":"5"
因此,您可以简单地搜索文本。您在这种情况下的查询是:
User.objects.get(jsonfield__contains='"username":"chingo"')
【讨论】:
【参考方案3】:这种用法有点反模式。此外,它的实现不会有常规性能,也许很容易出错。 当您需要通过字段查找时,通常不要使用 jsonfield。正如 Daniel 指出的那样,使用 RDBMS 提供的方式或 MongoDB(内部运行在更快的 BSON 上)。
由于deterministic of JSON format,
您可以通过使用contains
来实现它(regex
在处理多个'\'
时会出现问题,甚至更慢),我认为以这种方式使用 username
并不好,所以请改用 name
:
def make_cond(name, value):
from django.utils import simplejson
cond = simplejson.dumps(name:value)[1:-1] # remove '' and ''
return ' ' + cond # avoid '\"'
User.objects.get(jsonfield__contains=make_cond(name, value))
只要有效果
使用相同转储实用程序的 jsonfield(此处为simplejson
)
name
和 value
并没有太特别 (目前我不知道任何egde-case,也许有人可以指出它出)
您的 jsonfield 数据没有损坏(虽然不太可能)
其实我在做一个可编辑的jsonfield,在考虑是否支持这样的操作。否定证明就是上面说的,感觉有点黑魔法,嗯。
【讨论】:
使用import json
和 json.dumps(...
simplejson
已弃用。顺便说一句,这不适用于旧版本的 postgres!【参考方案4】:
2019:正如@freethebees 指出的那样,现在很简单:
User.objects.get(jsonfield__username='chingo')
但是正如文档示例中提到的,您可以深入查询,如果 json 是一个数组,您可以使用整数对其进行索引:
https://docs.djangoproject.com/en/2.2/ref/contrib/postgres/fields/#querying-jsonfield
>>> Dog.objects.create(name='Rufus', data=
... 'breed': 'labrador',
... 'owner':
... 'name': 'Bob',
... 'other_pets': [
... 'name': 'Fishy',
... ],
... ,
... )
>>> Dog.objects.create(name='Meg', data='breed': 'collie', 'owner': None)
>>> Dog.objects.filter(data__breed='collie')
<QuerySet [<Dog: Meg>]>
>>> Dog.objects.filter(data__owner__name='Bob')
<QuerySet [<Dog: Rufus>]>
>>> Dog.objects.filter(data__owner__other_pets__0__name='Fishy')
<QuerySet [<Dog: Rufus>]>
虽然这是针对 postgres 的,但我相信它在 MySQL 等其他数据库中的工作原理是一样的
Postgres:https://docs.djangoproject.com/en/2.2/ref/contrib/postgres/fields/#querying-jsonfield MySQL:https://django-mysql.readthedocs.io/en/latest/model_fields/json_field.html#querying-jsonfield【讨论】:
【参考方案5】:如果你使用 PostgreSQL,你可以使用原始 sql 来解决问题。
username = 'chingo'
SQL_QUERY = "SELECT true FROM you_table WHERE jsonfield::json->>'username' = '%s'"
User.objects.extra(where=[SQL_EXCLUDE % username]).get()
you_table
是数据库中表的名称。
使用 JSON 时的任何方法,例如使用纯文本 - 看起来都非常糟糕。 所以,我也认为你需要一个更好的数据库架构。
【讨论】:
【参考方案6】:这是我发现的解决您问题的方法:
search_filter = '"username":0'.format(username)
query = User.objects.get(jsonfield__contains=search_filter)
希望这会有所帮助。
【讨论】:
【参考方案7】:你不能那样做。对结构化数据使用普通数据库字段,而不是 JSON blob。
如果您需要搜索 JSON 数据,请考虑使用 MongoDB 等 noSQL 数据库。
【讨论】:
相当过时的答案以上是关于如何编写查询以在 django 的 json 字段中查找值的主要内容,如果未能解决你的问题,请参考以下文章
如何在不使用字段名的情况下运行 django orm 查询?
如何使用`django-filters`编写将在整数字段上使用范围过滤器的GraphQL查询?