Django: отфильтровать объект и создать миллион записей - PullRequest
0 голосов
/ 26 марта 2020

get_or_create () - это просто вспомогательная функция, но если мне нужно (Filter + create) миллион записей в одном go ?. bulk_create только создавать объекты, но не фильтровать. Могу ли я сделать это, используя with transition или rawquery - единственное решение?

result = Model.objects.filter(field__lookup=value)[0] if not result: result = Model.objects.create(...) return result

1 Ответ

0 голосов
/ 26 марта 2020

Я предоставлю возможные решения в Django, не прибегая к исходным данным, учитывая предоставленную вами информацию. Я обновлю этот ответ, если вы сможете предоставить больше информации, например, о базе данных, которую вы используете, и с какими ограничениями вы работаете (например, время выполнения, целостность / согласованность данных и т. Д. c.)

Решение 1

Если вы используете последнюю версию Django, вы можете использовать bulk_create и передать ignore_conflicts=True

objects = [
    Model(field_1='Object Value 1'),
    Model(field_1='Object Value 2'),
    Model(field_1='Object Value 3'),
    Model(field_1='Object Value 1'),
]
Model.objects.bulk_create(objects, ignore_conflicts=True)

Обратите внимание на причину установки этого для параметра true:

В базах данных, которые его поддерживают (все, кроме Oracle), установка для параметра ignore_conflicts значения True указывает базе данных игнорировать сбой при вставке любых строк, которые не соответствуют ограничениям, таким как повторяющиеся уникальные значения. , Включение этого параметра отключает установку первичного ключа для каждого экземпляра модели (если база данных обычно его поддерживает).

https://docs.djangoproject.com/en/dev/ref/models/querysets/#django .db.models.query.QuerySet.bulk_create

Решение 2

В качестве альтернативы вы можете использовать django .db.transaction.atomi c для выполнения следующих действий:

  1. Фильтруйте объекты, уже находящиеся в db
  2. . Обрежьте свой список, удалив объекты, возвращенные из 1
  3. bulk_create тех, которые не добавлены в базу данных
objects_to_add = []
with transaction.atomic():
     trimmed_list = filter_out_those_in_db(objects_to_add)
     Model.objects.bulk_create(trimmed_list)

Обратите внимание, что это заблокирует базу данных во время выполнения блока кода внутри транзакции.

Атомность является определяющим свойством транзакций базы данных. Atomi c позволяет нам создать блок кода, в котором гарантируется атомарность в базе данных. Если блок кода успешно завершен, изменения фиксируются в базе данных. Если есть исключение, изменения отменяются.

https://docs.djangoproject.com/en/dev/topics/db/transactions/#django .db.transaction.atomi c

Решение 3

Если вы хотите сохранить простоту и никакие другие модели / таблицы не ссылаются на эту модель, вы можете сделать следующее:

  1. Фильтр для записей
  2. Избирательно удалите ВСЕ эти записи
  3. Вставьте свой список

Это очень похоже на решение 2, но вы можете выполнить шаги 1 и 2 одним движением oop в БД, сокращая время выполнения по сравнению с выполнением фильтрации в python.

Решение 4

Если вы хотите обновить существующие записи вместо того, чтобы просто не добавлять дубликаты, вы можете использовать update_or_create для обновления существующих записей и создания не дубликатов.

Концепция похожа на get_or_create в том смысле, что вам все равно придется делать это для каждого объекта, но часть фильтрации и обновления выполняется также в одном sw oop в БД, а не в python

Удобный метод для обновления объекта с заданными kwargs, создания нового при необходимости. По умолчанию это словарь пар (поле, значение), используемых для обновления объекта. Значения по умолчанию могут быть вызываемыми.

https://docs.djangoproject.com/en/dev/ref/models/querysets/#update -или-create

...