【问题标题】:Django Postgres JSONField queryDjango Postgres JSONField 查询
【发布时间】:2018-10-19 11:10:40
【问题描述】:

我有一个类,里面有一个 json 字段

class A(models.Model)
    brand = JSONField()

如果我发布一个 JSON 数组,例如 [{'brand_id:1', 'name':'b1'}, {'brand_id:2', 'name':'b2'}] ,它将存储为一个数组的 JSON。这很好用。

我应该如何查询以检查该数组中任何字典的brand_id中是否存在“1”?

【问题讨论】:

标签: django python-3.x postgresql django-rest-framework


【解决方案1】:

首先,您的 JSON 格式不正确。我想它应该是:

[{'brand_id': 1, 'name': 'b1'}, {'brand_id': 2, 'name': 'b2'}] 

如果是这种情况,要在这样的 blob 中测试 1,类似这样的内容会告诉您 1 是否可以在 JSON 中的任何地方作为值找到:

def check_for_one(json_data):
    return any([1 in data.values() for data in json_data])

但您想具体了解1 是否为键所拥有的值 brand_id JSON 中的任何位置,因此您还可以使用循环添加一些额外的条件:

def check_for_one(json_data):
    match = []
    for data in json_data:
        for key, value in data.items():
            if key == 'brand_id' and value == 1:
                match.append(True)
    return any(match)

你可以像这样在你的模型类中加入诸如方法之类的逻辑:

class A(models.Model):
    brand = JSONField()

    def check_for_one_comprehension(self):
        return any([1 in data.values() for data in self.brand])

    def check_for_one_loop(self):
        match = []
        for data in self.brand:
            for key, value in data.items():
                if key == 'brand_id' and value == 1:
                    match.append(True)
        return any(match)

但是,如果您真的想从数据库中过滤实例,其中 JSON 数据是顶层数组和 brand_id == 1,则需要一种不同的方法,应该这样做:

A.objects.filter(brand__contains=[{'brand_id': 1}])

注意额外的[{}] 大括号!如果你只是调用contains=['brand_id': 1],它会抛出一个语法错误,如果你调用contains={'brand_id': 1},它将不匹配。

【讨论】:

  • 您能解释一下为什么brand__contains=[{'brand_id': 1}] 有效,而brand__contains={'brand_id': 1} 无效吗?
  • 因为contains={'brand_id': 1} 没有考虑到它需要过滤顶级列表 我们拥有的json 形状为:brand = [{'brand_id': 1, 'name': 'b1'}, {'brand_id': 2, 'name': 'b2'}] 。如果 json 的形状像 brand = {'brand_id': 1, 'name': 'b1'},那么它会匹配。
  • 非常有帮助。请注意,如果 JSON 结构不是列表(例如,{'brand_id: 1},没有 []s),那么在 python 中您不需要[]s。
【解决方案2】:

这行得通:

A.objects.filter(brands__contains=[{'brand_id':1}])

我没有先使用数组检查它。 @Bear Brown 指出的链接提供了足够的信息。 它在 django 中很容易,但找到它需要时间:P。

【讨论】:

  • 如果 JSON 字段存储一个数组,这不起作用。
  • @rtindru 不正确,您可以通过 json 数组进行过滤,但在这种情况下您需要 {} 才能正确转换键和值。 ['brand_id':1] 会抛出语法错误。
  • @jhrr 真;上面的代码引发了SyntaxError。如果字段存储 JSON 数组,您能否描述过滤器在 JSON 字段中的工作方式?
  • @rtindru 我已经在上面的主要答案中放入了正确的版本。看到最后。
  • 像魅力一样工作;我的错。我错过了数组表示法。你能解释一下为什么brand__contains=[{'brand_id': 1}] 有效而brand__contains={'brand_id': 1} 无效吗?
猜你喜欢
  • 1970-01-01
  • 2017-02-21
  • 1970-01-01
  • 2018-10-02
  • 2020-10-08
  • 1970-01-01
  • 2021-08-12
  • 1970-01-01
  • 2016-05-10
相关资源
最近更新 更多