web-dev-qa-db-ja.com

再挿入せずにPyMongoのMongoDBドキュメント配列にアイテムを追加

Python Webアプリケーション(PyMongo + Bottle)のバックエンドデータベースとしてMongoDBを使用しています。ユーザーはファイルをアップロードし、オプションでアップロード中にこれらのファイルに「タグを付ける」ことができます。タグはリストとして保存されます文書内で、以下に従って:

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

ユーザーがドキュメントに新しいタグを追加できるようにしようとしています。私はこのようなものを思いつきました:

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)

(fyi; refキーは常に一意です。これは簡単に_idも同様です。)ドキュメント全体を引き戻して再挿入することなく、「タグ」の値を直接更新する方法があるはずです。ここに何かが足りませんか?

どんな考えでも大歓迎です:)

19
deadbits

最初にドキュメントを取得するために使用する必要はありません。 .update 演算子で$Pushメソッドを使用するだけです。

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

更新は推奨されないため、pymongo 2.9以降を使用している場合は find_one_and_update または update_one メソッドを使用する必要があります。

23
styvane

@ssytvaneの回答に追加し、@ Guaravに回答するために、「upsert = True」が存在しない場合は追加できます。

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

または

def update_tags(ref, new_tag):
    coll.update_one({'ref': ref}, {'$Push': {'tags': new_tag}}, upsert = True)
2
Kiluvya.A

簡単にできます

1)単一のエントリを追加する場合

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

例えば:

{
    "_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)複数のエントリを追加する場合

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

例えば:

{
    "_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"
}

注:キーがまだ存在しない場合、mongoは新しいキーを作成します。

2
Nikhil Fulzele