Класс SimpleNamespace может использоваться для создания новых атрибутов с помощью setattr или подкласса SimpleNamespace и создания вашей собственной функции для добавления новых имен атрибутов (переменных).
from types import SimpleNamespace
variables = {"b":"B","c":"C"}
a = SimpleNamespace(**v)
setattr(a,"g","G")
a.g = "G+"
something = a.a
Похоже, вы хотите сделать «upsert». MongoDB имеет встроенную поддержку для этого. Передайте дополнительный параметр вашему вызову update (): {upsert: true}. Например:
key = {'key':'value'}
data = {'key2':'value2', 'key3':'value3'};
coll.update(key, data, upsert=True); #In python upsert must be passed as a keyword argument
Это полностью заменяет ваш блок if-find-else-update. Он будет вставляться, если ключ не существует и будет обновляться, если это произойдет.
До:
{"key":"value", "key2":"Ohai."}
После:
{"key":"value", "key2":"value2", "key3":"value3"}
Вы можете также укажите, какие данные вы хотите записать:
data = {"$set":{"key2":"value2"}}
Теперь ваш выбранный документ обновит значение «key2» и оставьте все остальное нетронутым.
Начиная с MongoDB 2.4 вы можете использовать $ setOnInsert ( http://docs.mongodb.org/manual/reference/operator/setOnInsert/ )
Установить 'insertion_date 'используя $ setOnInsert и' last_update_date ', используя $ set в вашей команде upsert.
Чтобы превратить ваш псевдокод в рабочий пример:
now = datetime.utcnow()
for document in update:
collection.update_one(
{"_id": document["_id"]},
{
"$setOnInsert": {"insertion_date": now},
"$set": {"last_update_date": now},
},
upsert=True,
)
Резюме
Заметьте, я предполагаю, что PyMongo изменится в соответствии с вашим выбранным языком.
Инструкции:
Точки оптимизации клавиш:
В общем, использование update лучше в MongoDB, так как оно просто создаст документ, если он еще не существует, хотя я не уверен, как работать с вашим адаптером python.
Second , если вам нужно только знать, существует ли этот документ, count (), который возвращает только номер, будет лучшим вариантом, чем find_one, который предположительно перенесет весь документ из вашего MongoDB, вызывая ненужный трафик.
Рисование из ответа Ван Нгуена выше, используйте обновление вместо сохранения. Это дает вам доступ к опции upsert.
ПРИМЕЧАНИЕ. Этот метод переопределяет весь документ при обнаружении ( из документов )
var conditions = { name: 'borne' } , update = { $inc: { visits: 1 }} , options = { multi: true };
Model.update(conditions, update, options, callback);
function callback (err, numAffected) { // numAffected is the number of updated documents })
Если вы хотите обновить выбор документа, но не все это, вы можете использовать метод $ set с обновлением. (опять же, Из документов ) ... Итак, если вы хотите установить ...
var query = { name: 'borne' }; Model.update(query, ***{ name: 'jason borne' }***, options, callback)
Отправить его как ...
Model.update(query, ***{ $set: { name: 'jason borne' }}***, options, callback)
Это помогает предотвратить случайную перезапись всех ваших документов с помощью { name: 'jason borne' }
.
Вы всегда можете создать уникальный индекс, который заставит MongoDB отклонить конфликтующее сохранение. Рассмотрим следующее, выполненное с использованием оболочки mongodb:
> db.getCollection("test").insert ({a:1, b:2, c:3})
> db.getCollection("test").find()
{ "_id" : ObjectId("50c8e35adde18a44f284e7ac"), "a" : 1, "b" : 2, "c" : 3 }
> db.getCollection("test").ensureIndex ({"a" : 1}, {unique: true})
> db.getCollection("test").insert({a:2, b:12, c:13}) # This works
> db.getCollection("test").insert({a:1, b:12, c:13}) # This fails
E11000 duplicate key error index: foo.test.$a_1 dup key: { : 1.0 }
Я не думаю, что mongodb поддерживает этот тип выборочного восстания. У меня та же проблема, что и у LeMiz, и с помощью update (критерии, newObj, upsert, multi) не работает правильно, имея дело с «созданной» и «обновленной» меткой времени. Учитывая следующий оператор upsert:
update( { "name": "abc" },
{ $set: { "created": "2010-07-14 11:11:11",
"updated": "2010-07-14 11:11:11" }},
true, true )
Сценарий №1 - документ с именем «abc» не существует: новый документ создается с именем «name» = «abc», «created» = 2010-07-14 11:11:11, и 'updated' = 2010-07-14 11:11:11.
Сценарий №2 - документ с именем «abc» уже существует с следующее: 'name' = 'abc', 'created' = 2010-07-12 09:09:09, и 'updated' = 2010-07-13 10:10:10. После обновления документ теперь будет таким же, как результат в сценарии №1. Невозможно указать в upsert, какие поля должны быть установлены, если вставлять, и какие поля останутся в покое, если обновление.
Моим решением было создать уникальный индекс в полях critera , выполнить вставку и сразу после этого выполнить обновление только в «обновленном» поле.
Вы можете использовать Upsert с оператором $ setOnInsert.
db.Table.update({noExist: true}, {"$setOnInsert": {xxxYourDocumentxxx}}, {upsert: true})