【问题标题】:Search within nested Django JSONField (either via Django ORM or raw sql)在嵌套的 Django JSONField 中搜索(通过 Django ORM 或原始 sql)
【发布时间】:2017-06-28 21:14:48
【问题描述】:

编辑:在下面添加了解决方案。没有人能够推荐原生 Postgres,一键搜索和替换,所以我不得不在 Python 中解析日志,然后进行更新。

版本Django==1.10.3Postgres 9.6

有没有办法在嵌套的 Django JSONField(由 Postgres jsonb 支持)中搜索特定的键/值状态?理想情况下,这将是一个原生 Django,但如果需要,我可以分解为原始 sql。

例如在以下数据中搜索一次或多次出现的{"status":"running}

{"subtask1": {"status":"running"},
 "subtask2": {"status":"complete"}}

背景:

我正在使用JSONField 记录长时间运行的子任务的当前状态。每个子任务通过服务器上的 nativePostgres jsonb_set() 操作选择性地更新其 json 字段的元素。

在每个子任务之后,我想查询log 字段以查看此子任务是否是最后完成的。如果一切都完成了(即在嵌套的 json 树中没有出现 {"status":"running"}),那么我将更新 Django RunningTask 实例的主要 .complete 字段。

示例和简化模型:

class LongRunningTask(models.model):
    id = models.AutoField(primary_key=True)
    complete = models.BooleanField(default=False)
    log = JSONField(null=True, blank=True, default=dict)

log 字段的示例数据:

{"subtask1": {"status":"running"},
 "subtask2": {"status":"complete"}}

提前感谢您的任何指点。

注意:

我已经尝试过 Django 的内置 contains 运算符,但这找不到值,因为它们嵌套了一层。我对 values operator 的前景感到兴奋,但从我的测试来看,它并没有在 JSONField 上实现(仅限 HStoreField)。

解决方案:

找不到原生 Postgres 一键搜索和替换调用,所以我最终在每个子任务完成后用 Python 解析日志,以确定它是否是最后一个。希望能及时找到更好的解决方案。

_current_log = LongRunningTask.objects.get(pk=current_task.id).log
_statuses = [True if _current_log[i]["status"] == "complete"
             else False
             for i in _current_log]
if all(_statuses):
    LongRunningTask.objects.filter(pk=adhoc_task.id).update(complete=True)

【问题讨论】:

  • 必须有unque key,不能为“subtask1”做reference,“subtask2”最好改成“subtask”。
  • 嗨@PiyushS.Wanare - 这是子任务的唯一标识符,所以不能相同。

标签: python json django postgresql jsonb


【解决方案1】:

试试这个:-

LongRunningTask.objects.filter(log__values__contains={"status":"running"})

【讨论】:

  • 我在文档中看到了 values 运算符,但不幸的是,它没有为 JSONField 实现 - 只有 HStoreField
【解决方案2】:

试试这个方法:

import json

all_completed=True
json_dict=json.loads(json_log)
for key,value in json_dict.items():
   if json_dict[key]['status']!='complete':
       all_completed=False
       break

这只是一个提示。您可以根据自己的要求进行更改。

【讨论】:

  • 感谢@Mohammed 的评论。我希望在 Postgres 查询中而不是在 Python 中执行此操作,以避免每个更新记录的子任务之间的竞争条件。
  • 我无法找到一种本地方法来做到这一点,尽管我有一种直觉,认为对 Postgres 中的 jsonb 方法有更好理解的人可以想出一个。我现在接受了这一点,因为我采用了类似的方法。
猜你喜欢
  • 2019-08-05
  • 2021-10-07
  • 1970-01-01
  • 2018-05-15
  • 2020-10-21
  • 2019-07-28
  • 2018-01-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多