2015-10-17 21 views
8

Python web uygulaması (PyMongo + Bottle) için arka uç veritabanı olarak MongoDB kullanıyorum. Kullanıcılar yükleme sırasında dosya yükleyebilir ve isteğe bağlı olarak bu dosyaları 'etiketleyebilir'. etiketleri aşağıda başına, belge içinde liste halinde saklanır:Yeniden ekleme eklenmeden PyMongo'daki MongoDB belge dizisine öğe ekle

{ 
    "_id" : ObjectId("561c199e038e42b10956e3fc"), 
    "tags" : [ "tag1", "tag2", "tag3" ], 
    "ref" : "4780" 
} 

Kullanıcıların herhangi bir belgeye yeni etiketler eklemek için izin çalışıyorum. Böyle bir şey ile geldi: (.. Bilginize; daima tektir ref anahtar bu kolayca yanı _id olabilir)

def update_tags(ref, new_tag) 
    # fetch desired document by ref key as dict 
    document = dict(coll.find_one({'ref': ref})) 
    # append new tag 
    document['tags'].append(new_tag) 
    # re-insert the document back into mongo 
    coll.update(document) 

sadece 'Etiket' değerini güncellemek için bir yol olması gerektiği gibi görünüyor tüm belgeyi geri çekmeden ve yeniden takmadan. Burada bir şey mi eksik?

Herhangi bir düşünce büyük takdir edilmektedir :)

cevap

12

sadece $push operatör ile .update yöntemi kullanmak ilk belgeyi almak için kullanmak gerekmez.

def update_tags(ref, new_tag): 
    coll.update({'ref': ref}, {'$push': {'tags': new_tag}}) 

güncelleme cevabı @ssytvane için pymongo 2.9 veya daha yeni

+1

İkisi arasındaki fark nedir? Sadece dönüş değeri (belge bir UpdateResult nesnesine göre)? Ne zaman birini kullanıyorsun? – stackoverflowwww

+4

'Etiketler' alanı yoksa ne olur? –

+0

"Etiketler" alanı mevcut değilse, oluşturulur. @GauravOjha – styvane

0

Hemen eklemek kullanıyorsanız find_one_and_update veya update_one yöntemi kullanmalısınız ve @Guarav cevap kaldırılmış olduğundan: "ekleyebilirsiniz o yoksa Upsert "Gerçek =:

def update_tags(ref, new_tag): 
    coll.update({'ref': ref}, {'$push': {'tags': new_tag}}, upsert = True) 

veya

def update_tags(ref, new_tag): 
    coll.update_one({'ref': ref}, {'$push': {'tags': new_tag}}, upsert = True) 
+0

Yığın Taşması'na katkıda bulunduğunuz için teşekkür ederiz. Lütfen yalnızca kod yanıtlarının kaldırıldığını unutmayın, çünkü sorunu nasıl çözdüklerini açıklamıyorlar. Diğer cevaplara/yorumlara atıfta bulunmak yerine, bunun ne yaptığını ve sorunu nasıl ele aldığını açıklamak için cevabınızı güncellemeyi düşünün, böylece tek başına bir cevaptır ve diğer cevap veya yorumların kaldırılması durumunda yine de mantıklıdır. – FluffyKitten

1

Sadece yapabilirsiniz Eğer tek giriş eklemek istiyorsanız

1)

def update_tags(ref, new_tag): 
    coll.update({'ref': ref}, {'$push': {'tags': new_tag}}) 

örn: Birden girdileri

def update_tags(ref, new_tag): 
    coll.update({'ref': ref}, {'$pushAll': {'tags': new_tag}}) #type of new_tag is list 

eklemek istiyorsanız

{ 
    "_id" : ObjectId("561c199e038e42b10956e3fc"), 
    "tags" : [ "tag1", "tag2", "tag3" ], 
    "ref" : "4780" 
} 
>> update_tags("4780", "tag4") 
{'updatedExisting': True, u'nModified': 1, u'ok': 1, u'n': 1} 
>> coll.find_one({"ref":"4780"}) 
{ 
    "_id" : ObjectId("561c199e038e42b10956e3fc"), 
    "tags" : [ "tag1", "tag2", "tag3" , "tag4" ], 
    "ref" : "4780" 
} 

2) örneğin:

{ 
    "_id" : ObjectId("561c199e038e42b10956e3fc"), 
    "tags" : [ "tag1", "tag2", "tag3" ], 
    "ref" : "4780" 
} 
>> update_tags("4780", ["tag5", "tag6", "tag7"]) 
{'updatedExisting': True, u'nModified': 1, u'ok': 1, u'n': 1} 
>> coll.find_one({"ref":"4780"}) 
{ 
    "_id" : ObjectId("561c199e038e42b10956e3fc"), 
    "tags" : [ "tag1", "tag2", "tag3" , "tag4" , "tag5", "tag6", "tag7" ], 
    "ref" : "4780" 
} 

Not: Anahtar zaten mevcut değilse, o zaman mongo yeni anahtar oluşturur.