2012-04-30 5 views
10

У меня есть коллекция, в которой все мои документы имеют по крайней мере эти 2 поля, скажем name и url (где url уникален, поэтому я установил на нем уникальный индекс). Теперь, если я попытаюсь вставить документ с дубликатом url, он даст ошибку и остановит программу. Я не хочу этого поведения, но мне нужно что-то вроде mysqlinsert or ignore, так что mongoDB не должен вставлять документ с дубликатом url и продолжить со следующими документами.Вставить или игнорировать несколько документов в mongoDB

Есть ли какой-либо параметр, который я могу передать команде insert, чтобы достичь этого? Я обычно делаю партию вставок с использованием pymongo, как:

collection.insert(document_array) 

Здесь collection является сбор и document_array является массивом документов.

Так можно каким-то образом реализовать функцию insert or ignore для ввода нескольких документов?

+0

Вы исполнительское эти вставки с помощью итератора/цикл объектов в памяти, или с использованием Монго встроенных методов batchInsert? – DeaconDesperado

+0

@DeaconDesperado Я использую метод пакетной вставки 'pymongo'. Таким образом, у меня есть цикл и на каждой итерации я выполняю операцию вставки вставки для вставки нескольких документов. – lovesh

+0

@lovesh. Если бы вы могли принять ответ здесь? –

ответ

0

Почему бы не просто поместить свой вызов в .insert() внутри блока try: ... except: и продолжить, если вставка не удалась?

Кроме того, вы также можете использовать обычный звонок update() с флагом upsert. Подробности здесь: http://www.mongodb.org/display/DOCS/Updating#Updating-update%28%29

+1

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

+0

Не поддерживает mongoDB «вставить или проигнорировать» в mysql или sqlite, где все, что является дубликатом, будет бесшумно игнорироваться и продолжать с остальными – lovesh

0

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

for doc in docs: 
    try: 
    collection.insert(doc) 
    except pymongo.errors.DuplicateKeyError: 
    print 'Duplicate url %s' % doc 

Где коллекция является экземпляром коллекции, созданной из ваших подключений экземпляров/база данных и документации является массивом словарей (документы) вы в настоящее время проездом для вставки.

Вы также можете решить, что делать с дублирующими ключами, которые нарушают ваш уникальный индекс в блоке except.

+1

, я хотел сделать «пакетную вставку», потому что он быстрее, чем вставка одного документа в время и у меня есть тысячи документов для вставки – lovesh

-2

Настоятельно рекомендуется использовать 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

+1

, если я использую upsert, я не могу выполнить пакетную вставку. Я должен пройти каждый документ, проверьте, есть ли в документе какой-то документ с этим URL-адресом, и если его там нет. – lovesh

+0

Документы Mongo DB хранятся в виде дерева B, объемная вставка - это конкретный драйвер. [http://www.mongodb.org/display/DOCS/Inserting#Inserting-Bulkinserts](http://www.mongodb.org/display/DOCS/Inserting#Inserting-Bulkinserts) – Kracekumar

+0

OP не запрашивает подтверждение. Он хочет, чтобы объемная вставка не прерывалась, когда одна запись терпит неудачу. Это совсем другое. – RickyA

-1

Что я делаю:

  1. Сформировать массив MongoDB идентификаторов Я хочу, чтобы вставить (хэш некоторых значений в моем случае)
  2. удалить существующие идентификаторы (Я использую команду redis queue bcoz, но вы можете запросить mongo)
  3. Вставьте очищенные данные!

Redis идеально подходит для этого, вы можете использовать Memcached или Mysql памяти, в соответствии с вашими потребностями

+0

OP не просит redis. – RickyA

+0

Я использую Redis для хранения очереди или для хранения уже вставленного URL. –

9

Попробуйте это:

try: 
    coll.insert(
     doc_or_docs=doc_array, 
     continue_on_error=True) 
except pymongo.errors.DuplicateKeyError: 
    pass 

операция вставки будет еще бросать исключение, если ошибка возникает в вставка (например, попытка вставить дублирующее значение для уникального индекса), но это не повлияет на другие элементы массива. Затем вы можете проглотить ошибку, как показано выше.

+0

, когда я вижу код, сохраняющий выброс DuplicateKeyError, я задаюсь вопросом, является ли это ошибкой или что? Теперь я знаю это ~~ Спасибо ~ – zhkzyth

+0

Помните, что он только выдает последнюю ошибку. не все из них. – RickyA

13

Установить флаг continue_on_error при звонке insert(). Примечание PyMongo драйвер 2.1 и сервер версии 1.9.1 требуется:

continue_on_error (по желанию): Если True, то база данных не остановит обработки массовой вставки, если один выходит из строя (например, из-за дублирования идентификаторов). Это делает объемную вставку так же, как и в серии одиночных вставок, , за исключением того, что lastError будет установлен, если какая-либо вставка терпит неудачу, а не только последний . Если возникает несколько ошибок, будет сообщено только самое последнее по ошибке().

Смежные вопросы