2014-04-10 14 views
12

Ich versuche bestellte Wörterbücher in Pymongo. Ich habe gelesen, dass es mit bson.son.Son gemacht werden kann. Die Docs sind HereWie bestelle ich Wörterbücher in Pymongo?

Allerdings kann ich nicht scheinen, damit es funktioniert. Es gibt nicht viel über Google. Es gibt einige Diskussionen darüber, Pymongo zuerst zu konfigurieren, um SON-Objekte zu verwenden, aber keine Beispiele. Ein Freund schlug vor, einen Parameter zu übergeben, wenn Sie einen Fund machen. Er konnte sich nicht erinnern.

Ich bin in der Lage, die SON-Objekte zu erstellen. Aber wenn sie in die Datenbank eingefügt werden und dann wieder herauskommen, sind sie einfach nur Diktate.

Ich bin mir nicht sicher, welches Code-Beispiel ich Ihnen geben soll, weil ich wirklich nicht weiß, wo ich anfangen soll. Das folgende Snippet erstellt jedes Mal ein leeres SON-Objekt, wenn ich einen neuen Benutzer hinzufüge. Das Objekt 'sub_users' wurde ebenfalls mit SON erstellt. Wenn ich das Kontodokument aus der DB lese, sind das normale Python-Dicts.

account['sub_users'][sub_user_name] = bson.SON() 
    with mongo_manager.Collection(CFG.db, 'Users') as users: 
     users.save(account) 

Vielleicht ein param Vergangenheit auf den finden Sie so konfigurieren? Das war der Vorschlag meiner Freunde, aber er konnte sich nicht erinnern.

with mongo_manager.Collection(CFG.db, 'Users') as users:         
    account = users.find_one({'_id': _id, 'DOC':'OrderedDict}) 

Irgendwelche Ideen?

Antwort

9

Sie können bson.son.SON oder verwenden, um geordnete dict zu speichern.

Und retrive Daten mit as_class=OrderedDict Option. Hier

ein Beispiel:

from collections import OrderedDict 
from pymongo import MongoClient 
import bson 

client = MongoClient() 
sample_db = client['sample'] 
test_col = sample_db['test'] 

test_col.drop() 

data = OrderedDict([("one", 1), ("two", 2), ("three", 3), ("four", 4)]) 
test_col.insert(data) 
print(list(test_col.find({}, {'_id': 0}, as_class=OrderedDict))) 

test_col.drop() 

data = bson.son.SON([("one", 1), ("two", 2), ("three", 3), ("four", 4)]) 
test_col.insert(data) 
print(list(test_col.find({}, {'_id': 0}, as_class=OrderedDict))) 

Ausgang:

[OrderedDict([(u'one', 1), (u'two', 2), (u'three', 3), (u'four', 4)])] 
[OrderedDict([(u'one', 1), (u'two', 2), (u'three', 3), (u'four', 4)])] 
+0

Super Antwort. Vielen Dank. –

+0

+1 clever und nützlich – shx2

+1

Gibt es einen Unterschied in der Leistung zwischen einem 'OrderedDict' und einem' SON' Objekt? Schauen Sie sich die Quellen an ([hier] (https://github.com/mongodb/mongo-python-driver/blob/master/bson/son.py#L33) und [hier] (https://github.com /python/cpython/blob/d4edfc9abffca965e76ebc5957a92031a4d6c4d4/Lib/collections/__init__.py)), beide sind Unterklassen von 'dict', aber' OrderedDict' hat eine C-Implementierung (mit einer reinen Python-Eins als Fallback), während 'SON' erscheint nur eine Python-Implementierung zu haben ... –

13

Diese Lösung ist korrekt für ältere Versionen von MongoDB und dem pymongo Fahrer, aber es funktioniert nicht mehr mit pymongo3 und MongoDB3 + Sie jetzt müssen dem MongoClient-Konstruktor document_class=OrderedDict hinzufügen. Ändern der obigen Antwort für Pymongo3-Kompatibilität.

from collections import OrderedDict 
from pymongo import MongoClient 
import bson 

client = MongoClient(document_class=OrderedDict) 
sample_db = client['sample'] 
test_col = sample_db['test'] 

test_col.drop() 

data = OrderedDict([("one", 1), ("two", 2), ("three", 3), ("four", 4)]) 
test_col.insert(data) 
print(list(test_col.find({}, {'_id': 0}))) 

test_col.drop() 

data = bson.son.SON([("one", 1), ("two", 2), ("three", 3), ("four", 4)]) 
test_col.insert(data) 
print(list(test_col.find({}, {'_id': 0}))) 

Ausgang:

[OrderedDict([(u'one', 1), (u'two', 2), (u'three', 3), (u'four', 4)])] 
[OrderedDict([(u'one', 1), (u'two', 2), (u'three', 3), (u'four', 4)])] 
2

In PyMongo v3.2 insert() ist veraltet und in diesem Beispiel sollte es mit insert_one() ersetzt werden. Aktualisiert Code ist unten:

from collections import OrderedDict 
from pymongo import MongoClient 
import bson 

client = MongoClient(document_class=OrderedDict) 
sample_db = client['sample'] 
test_col = sample_db['test'] 

test_col.drop() 

data = OrderedDict([("one", 1), ("two", 2), ("three", 3), ("four", 4)]) 
test_col.insert_one(data) 
print(list(test_col.find({}, {'_id': 0}))) 

test_col.drop() 

data = bson.son.SON([("one", 1), ("two", 2), ("three", 3), ("four", 4)]) 
test_col.insert_one(data) 
print(list(test_col.find({}, {'_id': 0}))) 

Ausgang:

[OrderedDict([(u'one', 1), (u'two', 2), (u'three', 3), (u'four', 4)])] 
[OrderedDict([(u'one', 1), (u'two', 2), (u'three', 3), (u'four', 4)])] 
3

Ein Standard find() in PyMongo nicht ein Objekt zurückgeben, die Felder ist in der gleichen Reihenfolge wie das Objekt, wenn Sie es abgerufen über Mongo Shell.

Dies liegt daran, dass der zurückgegebene Standardtyp ein Dict ist und die Reihenfolge nicht definiert ist.

Sie können SON wie vorgeschlagen verwenden. Hier ist, wie ich es gemacht habe. Jetzt wird die Reihenfolge der Felder berücksichtigt.

Dies ist für pymongo == 3.4.0

from bson.codec_options import CodecOptions 
from bson.son import SON 

opts = CodecOptions(document_class=SON) 
collection_son = mongo.db.collection.with_options(codec_options=opts) 

collection_son.find_one({"imsid": '12345'})