使用 Django,使用具有多个模式的 REGEXP_REPLACE 更新模型以匹配

Using Django, updating a model using REGEXP_REPLACE with multiple patterns to match

提问人:Dan 提问时间:10/24/2023 更新时间:10/24/2023 访问量:44

问:

我搜索并找到了类似的帖子,但不是这么具体。我目前正在尝试使用 .我想在一个查询中完成此操作,因此我想匹配多个模式并在一次调用中替换它们。在我目前的设置中,如果我只有一个模式,我想匹配代码工作正常,例如。name1,但是一旦我尝试使用(name1|name2)匹配多个,它就不起作用。REGEXP_REPLACE

一个小例子: 我们在模型上有一个 JSON 字段。信息字段填充了以下内容:informationPerson

{"name": "first_name last_name", "description": "Test description", "address": "123 example street"}

我目前用来做REGEXP_REPLACE的代码是:

find_pattern = r'(name|description)": "(.*?)",'
repl_pattern = r'\1": "filler",'
Cast(
    Case(
        When(
            **{f'information__isnull': False},
            then=Func(
                Cast(information, output_field=CharField()),
                Value(find_pattern),
                Value(repl_pattern),
                Value('g'),
                function='REGEXP_REPLACE',
                output_field=CharField(),
            ),
        ),
        default=None,
    ),
    output_field=JSONField(),
)

但是,这不起作用,我不知道为什么。我收到以下错误:

django.db.utils.DataError: invalid input syntax for type json
DETAIL:  The input string ended unexpectedly.

任何帮助/想法将不胜感激,谢谢。

django postgresql django-models 正则表达式替换

评论

0赞 willeM_ Van Onsem 10/24/2023
在数据库端这样做是有原因的吗?为什么不直接在 Python/Django 层处理它。对结构化数据使用正则表达式和文本处理通常不是一个好主意。
0赞 willeM_ Van Onsem 10/24/2023
另一个问题是你想做什么,只是注入 as 的值 和 ?是否要更新记录?或者只是将其作为价值检索?fillernamedescription
0赞 Dan 10/24/2023
@WillemVanOnsem这样做数据库端的原因是,我们正在尝试创建数据库的匿名版本。因此,目的是更新记录以删除任何敏感信息。
0赞 willeM_ Van Onsem 10/24/2023
但我真的不明白这如何真正帮助在数据库端执行此操作,您可以在 Django 端使用两个查询来执行此操作,然后数据再次“消失”。
0赞 Dan 10/24/2023
@WillemVanOnsem 在数据库端和一次查询中执行此操作背后的想法是它会更快/更高效。如果我们有数百万人,并且我们想一次更新他们的信息以匿名化,我看不出在两个查询中这样做会更好。这两个问题会是什么来帮助我遵循你的思路?

答:

0赞 willeM_ Van Onsem 10/24/2023 #1

我认为你使这个问题比应有的要困难得多。使用文本处理通常是一个非常糟糕的主意。尤其是正则表达式,正则表达式非常好,但人们总是倾向于将它们用于正则表达式不用于的事情。

我们可以在 Django/Python 端做到这一点,使用:

data = list(
    MyModel.objects.filter(information__isnull=False).only('pk', 'information')
)

for item in data:
    item.information['name'] = item.information['description'] = 'filler'

MyModel.objects.bulk_update(data, fields=('information',))

如果数据量非常大,我们可以用类似迭代器的方式来做到这一点:

data = []

for item in (
    MyModel.objects.filter(information__isnull=False)
    .only('pk', 'information')
    .iterator(10000)
):
    item.information['name'] = item.information['description'] = 'filler'
    data.append(item)
    if len(data) > 10000:
        MyModel.objects.bulk_update(data, fields=('information',))
        data = []

if data:
    MyModel.objects.bulk_update(data, fields=('information',))

因此,在这里,我们将读取和更新项目,例如,每次都会有 10'000 条记录。