25

我的数据库中有一个 json 字段,就像

jsonfield = {'username':'chingo','reputation':'5'}

如何编写查询以便查找用户名是否存在。就像是

username = 'chingo'
query = User.objects.get(jsonfield['username']=username)

我知道上面的查询是错误的,但我想知道是否有办法访问它?

4

7 回答 7

24

如果您使用的是 django-jsonfield 包,那么这很简单。假设您有这样的模型:

from jsonfield import JSONField
class User(models.Model):
    jsonfield = JSONField()

然后要搜索具有特定用户名的记录,您可以这样做:

User.objects.get(jsonfield__contains={'username':username})
于 2015-04-10T06:27:39.977 回答
20

从 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"')
于 2017-11-28T14:30:27.147 回答
16

这种用法有点反模式。此外,它的实现不会有常规性能,并且可能容易出错。
当您需要通过字段查找时,通常不要使用 jsonfield。正如 Daniel 指出的那样,使用 RDBMS 提供的方式或 MongoDB(内部在更快的 BSON 上运行)。

由于JSON 格式的确定性,您可以通过使用containsregex在处理多个'\'甚至更慢时出现问题)来实现它,我认为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 并考虑是否支持这样的操作。否定的证明就是上面说的,感觉有点黑魔法,嗯。

于 2012-05-04T14:16:37.350 回答
9

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 等其他数据库中的工作原理相同

于 2019-07-25T22:52:13.453 回答
1

如果您使用 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 时的任何方法,例如使用纯文本 - 看起来都非常糟糕。所以,我也认为你需要一个更好的数据库模式。

于 2016-02-04T21:34:17.927 回答
1

这是我发现可以解决您的问题的方法:

search_filter = '"username":{0}'.format(username)
query = User.objects.get(jsonfield__contains=search_filter)

希望这可以帮助。

于 2017-11-14T15:14:21.187 回答
-1

你不能那样做。对结构化数据使用普通数据库字段,而不是 JSON blob。

如果您需要搜索 JSON 数据,请考虑使用 MongoDB 等 noSQL 数据库。

于 2012-05-04T08:36:48.153 回答