2014-04-10 3 views
12

Pymongo에서 주문 된 사전을 얻으려고합니다. 나는 bson.son.Son과 함께 할 수 있다고 읽었습니다. 문서 도구는 다음과 같습니다. Herepymongo에서 주문 된 사전을 얻는 방법?

그러나 작동하지 않는 것 같습니다. 그것에 대해 Google에별로 없습니다. 먼저 pymongo를 설정하여 SON 객체를 사용하도록 설명하지만 예제는 없습니다. 친구가 찾으려고 할 때 param을 건네 줄 것을 친구가 제안했습니다. 그는 기억할 수 없었다.

나는 SON 개체를 만들 수 있습니다. 그러나 그들이 DB에 삽입되고 나서 다시 나오는 것은 단지 평범한 것입니다.

정말 어디서부터 시작해야할지 모르기 때문에 어떤 코드 예제가 좋을지 잘 모르겠습니다. 아래 스 니펫은 새 사용자를 추가 할 때마다 빈 SON 객체를 만듭니다. 'sub_users'객체도 SON을 사용하여 만들었습니다. DB에서 계정 문서를 다시 읽을 때 그들은 보통의 python dicts입니다.

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

어쩌면이 구성을 찾으려면 과거에 매개 변수가 있습니까? 이것은 내 친구들의 제안 이었지만 그는 기억할 수 없었습니다.

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

아이디어가 있으십니까?

답변

9

bson.son.SON 또는 OrderedDict을 사용하여 주문 된 사전을 저장할 수 있습니다.

그리고 as_class=OrderedDict 옵션을 사용하여 데이터를 검색하십시오. 여기

은 예입니다

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))) 

출력 :

[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

굉장한 답변입니다. 감사. –

+0

+1 영리하고 유용한 – shx2

+1

'OrderedDict'와'SON' 객체를 사용하는 사이에 성능에 차이가 있습니까? 출처 ([here] (https://github.com/mongodb/mongo-python-driver/blob/master/bson/son.py#L33) 및 [여기] (https://github.com)를 보면 /python/cpython/blob/d4edfc9abffca965e76ebc5957a92031a4d6c4d4/Lib/collections/__init__.py)) 둘다'dict'의 서브 클래스이지만'OrderedDict'는 C 구현 (순수한 파이썬을 폴백으로 사용)을 가졌지 만'SON'은 파이썬 구현 만하면 ... –

13

위의이 솔루션은 이전 MongoDB의 버전과 pymongo 드라이버 있지만 더 이상 지금 pymongo3 및 MongoDB3 + 당신과 함께 작동에 대한 올바른 document_class=OrderedDict을 MongoClient 생성자에 추가해야합니다. pymongo3 호환성에 대한 위의 대답 수정.

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}))) 

출력 :

[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

PyMongo의 V3.2에서 insert()는 사용되지 않으며,이 예에서 이것은 insert_one()로 대체되어야한다. 업데이트 된 코드는 다음과 같습니다 :

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}))) 

출력 :

[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

표준 발견() 당신이 그것을 검색하는 경우 PyMongo에서이 필드는 해당 객체와 같은 순서에의 객체를 반환하지 않습니다 몽고 껍질을 통해.

반환되는 기본 유형은 Dict이며 주문이 정의되지 않았기 때문입니다.

제안 된대로 SON을 사용할 수 있습니다. 여기 내가 어떻게 그랬어. 필드 주문이 준수됩니다.

이것은 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'})