如何编写查询以在 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(此处为 simplejsonnamevalue 并没有太特别 (目前我不知道任何egde-case,也许有人可以指出它出) 您的 jsonfield 数据没有损坏(虽然不太可能)

其实我在做一个可编辑的jsonfield,在考虑是否支持这样的操作。否定证明就是上面说的,感觉有点黑魔法,嗯。

【讨论】:

使用 import jsonjson.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 字段中查找值的主要内容,如果未能解决你的问题,请参考以下文章

如何解析和渲染 json 以在 Django 模板中使用

如何在不使用字段名的情况下运行 django orm 查询?

如何使用`django-filters`编写将在整数字段上使用范围过滤器的GraphQL查询?

如何将 pandas 数据框转换为 json 以在 django 模板中使用

如何按非字段值过滤 Django 查询集

Django 将查询集序列化为 JSON 以仅使用字段信息和 id 构造 RESTful 响应