2017-11-03 6 views
0

Pythonライブラリpymongoを使用してMongoDBにドキュメントを一括挿入しようとしています。BulkWriteErrorのためにpymongoを使用したバルク挿入マッピング配列

import pymongo 
def tryManyInsert(): 
    p = {'x' : 1, 'y' : True, 'z': None} 
    mongoColl = pymongo.MongoClient('localhost', 27017)['test']['multiIn'] 
    mongoColl.insert_many([p for i in range(10)]) 
tryManyInsert() 

しかし、私はBulkWriteErrorのために失敗し続けます。

Traceback (most recent call last): 
    File "/prog_path/testMongoCon.py", line 9, in <module> 
    tryManyInsert(); 
    File "/prog_path/testMongoCon.py", line 7, in tryManyInsert 
mongoColl.insert_many([p for i in range(10)]) 
    File "/myenv_path/lib/python3.6/site-packages/pymongo/collection.py", line 724, in insert_many 
blk.execute(self.write_concern.document) 
    File "/myenv_path/lib/python3.6/site-packages/pymongo/bulk.py", line 493, in execute 
return self.execute_command(sock_info, generator, write_concern) 
    File "/myenv_path/lib/python3.6/site-packages/pymongo/bulk.py", line 331, in execute_command 
raise BulkWriteError(full_result) 
    pymongo.errors.BulkWriteError: batch op errors occurred 

私はこのanswer/discussionの条件は、ここでは適用されませんので_idずに順次のみ10ドキュメントを挿入しようとしています。同様のquestionには答えがありません。

私はpymongo 3.4pymongo 3.5.1を試しましたが、両方とも同じエラーが発生します。私はpython3.6mongodb 3.2.10です。 ここで何が間違っていますか?

答えて

1

Pythonは、まだpを各配列メンバーで同じものとして参照しています。

import pymongo 
from copy import copy 
def tryManyInsert(): 
    p = {'x' : 1, 'y' : True, 'z': None} 
    mongoColl = pymongo.MongoClient('localhost', 27017)['test']['multiIn'] 
    mongoColl.insert_many([copy(p) for i in range(10)]) 
tryManyInsert() 

あるいは単に:あなたは、各アレイメンバーのためのpcopy()たい

mongoColl.insert_many([{ 'x': 1, 'y': True, 'z': None } for i in range(10)]) 

ない限りやるだけ一度割り当てられますし、あなたは、単に「同じ文書を繰り返している_idいます同じ_idinsert_many()の引数に置きます。したがって、重複キーのエラー。簡単なデモとして

from bson import ObjectId 

p = { 'a': 1 } 

def addId(obj): 
    obj['_id'] = ObjectId() 
    return obj 

docs = map(addId,[p for i in range(2)]) 
print docs 

はあなたに与える:

[ 
    {'a': 1, '_id': ObjectId('59fbc4a16cb6b30bdb3de0fd')}, 
    {'a': 1, '_id': ObjectId('59fbc4a16cb6b30bdb3de0fd')} 
] 

以上簡潔に:

p = { 'a': 1 } 

def addKey(x): 
    x[0]['b'] = x[1] 
    return x[0] 

docs = map(addKey,[[p,i] for i,p in enumerate([p for i in range(3)])]) 
print docs 

与える:

[{'a': 1, 'b': 2}, {'a': 1, 'b': 2}, {'a': 1, 'b': 2}] 

明確にインデックス値が渡されたのと同じ値を上書き渡さ実証

しかし、値のコピーを取るためにcopy()を使用して:。

from bson import ObjectId 

p = { 'a': 1 } 

def addId(obj): 
    obj['_id'] = ObjectId() 
    return obj 

docs = map(addId,[copy(p) for i in range(2)]) 
print docs 

はあなたを与える:

[ 
    {'a': 1, '_id': ObjectId('59fbc5466cb6b30be4d0fc00')}, 
    {'a': 1, '_id': ObjectId('59fbc5466cb6b30be4d0fc01')} 
] 

または、私たちの基本デモンストレーション:

p = { 'a': 1 } 

def addKey(x): 
    x[0]['b'] = x[1] 
    return x[0] 

docs = map(addKey,[[p,i] for i,p in enumerate([copy(p) for i in range(3)])]) 
print docs 

返信:

[{'a': 1, 'b': 0}, {'a': 1, 'b': 1}, {'a': 1, 'b': 2}] 

これは基本的にどのようにpythonが動作するのですか。実際に意図的に新しい値に代入していない場合は、同じ参照値を返して、単に「新しいもの」を生成するのではなく、ループ内の各参照値を更新するだけです。

+0

はい、ありがとうございます。私は[docs](https://api.mongodb.com/python/3.5.1/tutorial.html)をもっと慎重に読んでいたはずです。 'ドキュメントが挿入されると、特別なキー" _id "が自動的に追加されます文書にまだ "_id"キーが含まれていない場合。 – parthasarathy

+0

@parthasarathyそれはその一部ですが、実際のところここではpythonがオブジェクトの割り当てをどのように処理するかが重要です。したがって、ここでの主な違いは、配列にマップされる「同じ参照」とは対照的に「コピー」です。 –