Вставлять или игнорировать несколько документов в mongoDB
У меня есть коллекция, в которой все мои документы имеют по крайней мере эти 2 поля, например name
и url
(где url
уникально, поэтому я установил на нем уникальный индекс). Теперь, если я попытаюсь вставить документ с дубликатом url
, он даст ошибку и остановит программу. Я не хочу этого поведения, но мне нужно что-то вроде mysql
insert or ignore
, так что mongoDB не должен вставлять документ с дубликатом url
и продолжить со следующими документами.
Есть ли какой-нибудь параметр, который я могу передать команде insert
для достижения такого поведения? Я обычно делаю пакет вставки с помощью pymongo
как:
collection.insert(document_array)
Здесь collection
представляет собой набор, а document_array
- это массив документов.
Итак, можно ли каким-либо образом реализовать функциональность insert or ignore
для вставки нескольких документов?
Ответы
Ответ 1
Установите флаг continue_on_error
при вызове insert(). Обратите внимание на драйвер PyMongo 2.1 и версию сервера 1.9.1:
continue_on_error (необязательно): если True, база данных не остановится обрабатывая объемную вставку, если не удается (например, из-за дубликатов идентификаторов). Это приводит к тому, что объемная вставка ведет себя так же, как серия одиночных вставок, кроме lastError будет установлен, если какая-либо вставка не удалась, а не только последняя один. Если возникает несколько ошибок, будут сообщены только самые последние данные по ошибке().
Ответ 2
Используйте insert_many() и установите упорядоченное = False.
Это гарантирует, что все операции записи будут предприняты, даже если есть ошибки:
http://api.mongodb.org/python/current/api/pymongo/collection.html#pymongo.collection.Collection.insert_many
Ответ 3
Попробуйте следующее:
try:
coll.insert(
doc_or_docs=doc_array,
continue_on_error=True)
except pymongo.errors.DuplicateKeyError:
pass
Операция вставки все равно выдает исключение, если во вставке возникает ошибка (например, попытка вставить дублирующее значение для уникального индекса), но это не повлияет на другие элементы массива. Затем вы можете усвоить ошибку, как показано выше.
Ответ 4
Почему бы просто не поместить ваш вызов в .insert()
внутри блока try: ... except:
и продолжить, если вставка не удалась?
Кроме того, вы также можете использовать обычный вызов update()
с флагом upsert
. Подробности здесь: http://www.mongodb.org/display/DOCS/Updating#Updating-update%28%29
Ответ 5
Если у вас есть свой массив документов, уже находящихся в памяти вашего python script, почему бы не вставить их путем итерации через них и просто поймать те, которые не могут быть вставлены из-за уникального индекса?
for doc in docs:
try:
collection.insert(doc)
except pymongo.errors.DuplicateKeyError:
print 'Duplicate url %s' % doc
Где коллекция представляет собой экземпляр коллекции, созданной из ваших экземпляров соединения/базы данных, а документы - это массив словарей (документов), которые вы в настоящее время передаете для вставки.
Вы также можете решить, что делать с дублирующимися ключами, которые нарушают ваш уникальный индекс в блоке except
.
Ответ 6
Что я делаю:
- Генерировать массив идентификаторов MongoDB, которые я хочу вставить (хэш некоторых значений в моем случае)
- Удалите существующие идентификаторы (я использую команду redis queue bcoz, но вы можете запросить mongo)
- Вставьте очищенные данные!
Redis идеально подходит для этого, вы можете использовать Memcached или Mysql Memory, в соответствии с вашими потребностями.
Ответ 7
Настоятельно рекомендуется использовать upsert
stat.update({'location': d['user']['location']}, \
{'$inc': {'count': 1}},upsert = True, safe = True)
Здесь stat
- это коллекция, если местоположение посетителя уже присутствует в коллекции, count
увеличивается на единицу, иначе count
устанавливается на 1
.
Вот ссылка для документации http://www.mongodb.org/display/DOCS/Updating#Updating-UpsertswithModifiers