gpt4 book ai didi

django - 删除 Django ORM 中的重复项——多行

转载 作者:行者123 更新时间:2023-11-28 19:37:30 25 4
gpt4 key购买 nike

我有一个包含四个字段的模型。如何从我的数据库中删除重复的对象?

丹尼尔罗斯曼对 this question 的回答似乎很合适,但我不确定如何将其扩展到每个对象有四个字段要比较的情况。

谢谢,

W.

最佳答案

def remove_duplicated_records(model, fields):
"""
Removes records from `model` duplicated on `fields`
while leaving the most recent one (biggest `id`).
"""
duplicates = model.objects.values(*fields)

# override any model specific ordering (for `.annotate()`)
duplicates = duplicates.order_by()

# group by same values of `fields`; count how many rows are the same
duplicates = duplicates.annotate(
max_id=models.Max("id"), count_id=models.Count("id")
)

# leave out only the ones which are actually duplicated
duplicates = duplicates.filter(count_id__gt=1)

for duplicate in duplicates:
to_delete = model.objects.filter(**{x: duplicate[x] for x in fields})

# leave out the latest duplicated record
# you can use `Min` if you wish to leave out the first record
to_delete = to_delete.exclude(id=duplicate["max_id"])

to_delete.delete()

你不应该经常这样做。使用 unique_together而是对数据库的约束。

这留下了最大的记录 id在数据库中。如果您想保留原始记录(第一个),请使用 models.Min 稍微修改一下代码。 .您也可以使用完全不同的字段,例如创建日期或其他内容。

底层 SQL

注释django ORM时使用GROUP BY查询中使用的所有模型字段的语句。因此使用 .values()方法。 GROUP BY将所有具有相同值的记录分组。重复的(多个 idunique_fields )稍后在 HAVING 中过滤掉.filter() 生成的语句关于注释 QuerySet .

SELECT
field_1,

field_n,
MAX(id) as max_id,
COUNT(id) as count_id
FROM
app_mymodel
GROUP BY
field_1,

field_n
HAVING
count_id > 1

重复的记录随后在 for 中被删除循环,每个组中出现频率最高的异常(exception)。

空 .order_by()

可以肯定的是,添加一个空的 .order_by() 总是明智的在聚合之前调用 QuerySet .

用于订购 QuerySet 的字段也包含在 GROUP BY 中陈述。空 .order_by()覆盖模型的 Meta 中声明的列结果它们不包含在 SQL 查询中(例如,默认按日期排序会破坏结果)。

您目前可能不需要覆盖它,但稍后可能有人会添加默认顺序,因此毁了您宝贵的删除重复代码,甚至都不知道。是的,我确定您有 100% 的测试覆盖率……

只需添加空.order_by()为了安全。 ;-)

https://docs.djangoproject.com/en/3.2/topics/db/aggregation/#interaction-with-default-ordering-or-order-by

交易

当然,您应该考虑在单个事务中完成所有操作。

https://docs.djangoproject.com/en/3.2/topics/db/transactions/#django.db.transaction.atomic

关于django - 删除 Django ORM 中的重复项——多行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13700200/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com