これは、MongoDBが文書をバイナリ(BSON)形式で保存するためです。 BSON文書のキーと値のペアは、任意の順序を持つことができます(ただし、_idが常に先頭です)。 最初にmongo shellから始めましょう。 mongoシェルは、データの読み書き時にキー順を保持します。たとえば :あなたはこの文書の値を使用してreplaceOne()を実行している場合、既存のBSONがありますので
> db.collection.insert({_id:1, a:2, b:3})
{ "_id" : 1, "a" : 2, "b" : 3 }
、それは修正を避けるだろう。
> var doc = db.collection.findOne()
> db.collection.replaceOne(doc, doc)
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 0 }
しかし、あなたはフィールドの順序を変更した場合、それは変更を検出します
> var doc_2 = {_id:1, b:3, a:2}
> db.collection.replaceOne(doc_2, doc_2)
{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
はのは、Pythonの世界に一歩を踏み出してみましょう。 PyMongoはデフォルトでPython辞書としてのBSON文書を表し、Python辞書のキーの順序は定義されていません。したがって、BSONにどのようにシリアライズされるのか予測できません。あなたの例のように:
> doc = db.collection.find_one()
{u'_id': 1.0, u'a': 2.0, u'b': 3.0}
> result = db.collection.replace_one(doc, doc)
> result.raw_result
{u'n': 1, u'nModified': 1, u'ok': 1, 'updatedExisting': True}
それはあなたのユースケースのために重要な場合は、1つの回避策はbson.SONを使用することです。たとえば:
> from bson import CodecOptions, SON
> opts=CodecOptions(document_class=SON)
> collection_son = db.collection.with_options(codec_options=opts)
> doc_2 = collection_son.find_one()
SON([(u'_id', 1.0), (u'a', 2.0), (u'b', 3.0)])
> result = collection_son.replace_one(doc_2, doc_2)
{u'n': 1, u'nModified': 0, u'ok': 1, 'updatedExisting': True}
はまたbson.SON
はすなわちPyMongo(V3.3.0)_update() methodで使用されていることを確認することができます。関連記事:PyMongo and Key Order in SubDocumentsも参照してください。
更新が追加の質問に答えるために:
を私の知る限りでは、SONにネストされた辞書を変換する「標準」の機能はありません。、あなたを
def to_son(value):
for k, v in value.iteritems():
if isinstance(v, dict):
value[k] = to_son(v)
elif isinstance(v, list):
value[k] = [to_son(x) for x in v]
return bson.son.SON(value)
# Assuming the order of the dictionary is as you desired.
to_son(a_nested_dict)
するか、SON
形式で
from bson import CodecOptions, SON, BSON
nested_bson = BSON.encode(a_nested_dict)
nested_son = BSON.decode(nested_bson, codec_options=CodecOptions(document_class=SON))
一度中間フォーマットとしてBSONを利用:カスタムを書くことができますがdict
SON
には、例えば、自分自身をコンバータSON.to_dict()
0を使ってPython辞書に戻すことができます
MongoDBとpymongoのバージョンは何ですか? –
@KevinAdistambha 3.2.7とpymongo 3.3もpymongoにダウングレードしようとしました3.2.2 –
修正する前にドキュメントを返して結果を比較するが、なぜこれがうまくいかなかったのかを知りたい 'find_one_and_replace'でこれを解決しました。私は実際にpre.pdfドキュメントを検索する気にはならないので、これは最適ではない –