我的数据库中有一个 json 字段,就像
jsonfield = {'username':'chingo','reputation':'5'}
如何编写查询以便查找用户名是否存在。就像是
username = 'chingo'
query = User.objects.get(jsonfield['username']=username)
我知道上面的查询是错误的,但我想知道是否有办法访问它?
我的数据库中有一个 json 字段,就像
jsonfield = {'username':'chingo','reputation':'5'}
如何编写查询以便查找用户名是否存在。就像是
username = 'chingo'
query = User.objects.get(jsonfield['username']=username)
我知道上面的查询是错误的,但我想知道是否有办法访问它?
如果您使用的是 django-jsonfield 包,那么这很简单。假设您有这样的模型:
from jsonfield import JSONField
class User(models.Model):
jsonfield = JSONField()
然后要搜索具有特定用户名的记录,您可以这样做:
User.objects.get(jsonfield__contains={'username':username})
从 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"')
这种用法有点反模式。此外,它的实现不会有常规性能,并且可能容易出错。
当您需要通过字段查找时,通常不要使用 jsonfield。正如 Daniel 指出的那样,使用 RDBMS 提供的方式或 MongoDB(内部在更快的 BSON 上运行)。
由于JSON 格式的确定性,您可以通过使用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))
只要它有效
simplejson
此处)name
并且value
不太特别(到目前为止我不知道任何egde-case,也许有人可以指出)实际上我正在研究一个可编辑的 jsonfield 并考虑是否支持这样的操作。否定的证明就是上面说的,感觉有点黑魔法,嗯。
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 等其他数据库中的工作原理相同
如果您使用 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 时的任何方法,例如使用纯文本 - 看起来都非常糟糕。所以,我也认为你需要一个更好的数据库模式。
这是我发现可以解决您的问题的方法:
search_filter = '"username":{0}'.format(username)
query = User.objects.get(jsonfield__contains=search_filter)
希望这可以帮助。
你不能那样做。对结构化数据使用普通数据库字段,而不是 JSON blob。
如果您需要搜索 JSON 数据,请考虑使用 MongoDB 等 noSQL 数据库。