2012-04-13 3 views
0

mongdb에 매우 큰 정수 (정확히 수천 자릿수)를 저장하고 싶습니다. 물론 BSON에서 지원하는 표준 유형에서는 작동하지 않습니다. 범위 검색 및 유사한 작업을 수행하려는 경우 가장 효율적인 해결 방법을 생각하려고합니다. 이 요구 사항은 범위 검색을 비실용적으로 만들기 때문에 정수를 문자열로 저장하는 것을 제외합니다.bson 어레이는 어떻게 비교합니까 (mongodb/pymongo에서)?

내가 생각할 수있는 한 가지 방법은 표준 정수의 (가변 길이) 배열을 사용하여 2^32 확장을 인코딩하고이 배열에 배열 자체의 길이에 대한 첫 번째 항목을 추가하는 것입니다. 그런 식으로 배열에 대한 사전 식 순서는 임의로 큰 정수의 일반적인 순서와 일치합니다.

예를 들어, 컬렉션 내가

{"name": "me", "fortune": [1,1000]} 
{"name": "scrooge mcduck", "fortune": [11,1,0,0,0,0,0,0,0,0,0,0]} 
{"name": "bruce wayne","fortune": [2, 10,0]} 
{"name": "bill gates", "fortune": [2,1,1000]} 
{"name": "francis", "fortune": [0]} 

는 따라서 브루스 웨인의 순 가치가 10 5 문서를 가질 수 *^(32)이, 2^32 + 1000 빌 게이츠 '와 스크루지 맥덕의 2^(320).

그때 사용하여 정렬 할 수 있습니다 { "재산을": 1} 내 컴퓨터에 (pymongo로) 그들을 예상대로, 순서 프랜시스 < 나 < 법안 < 브루스 < 스크루지에 반환합니다.

그러나, 나는 내가 BSON 배열을 비교하는 방식에 대해 어디 문서화 보지 가정을 만드는 중이라서 및 범위 검색, 내가 예를 들어 (생각하는 방법을 작동하지 않는

find({"fortune":{$gte:[2,5,0]}}) 

아무 문서도 반환하지 않지만 나는 브루스와 스크루지를 원할 것입니다.)

아무도 도와 줄 수 있습니까? 감사합니다

+0

Dhruv와 Remon이 설명한 아래의 두 솔루션 모두 최대 길이를 알고 있어야하며 많은 패딩 0을 저장해야합니다. – user1199915

답변

0

대신 재산과 동일한 정확한 정수를 나타내는 왼쪽 패딩 문자열을 저장할 수 있습니다.

eg. "1000000" = 1 million 
    "0010000" = 10 thousand 
    "2000000" = 2 million 
    "0200000" = 2 hundred thousand 

왼쪽 패딩을 0으로 설정하면 이러한 문자열의 사전 식 비교가 숫자 값으로 직접 비교 될 수 있습니다.

{"name": "scrooge mcduck", "fortune": "00001100000000000000" } 
    {"name": "bruce wayne", "fortune": "00000200000000000000" } 

질의 :

> db.test123.find() 
{ "_id" : ObjectId("4f87e142f1573cffecd0f65e"), "name" : "bruce wayne", "fortune" : "00000200000000000000" } 
{ "_id" : ObjectId("4f87e150f1573cffecd0f65f"), "name" : "donald", "fortune" : "00000150000000000000" } 
{ "_id" : ObjectId("4f87e160f1573cffecd0f660"), "name" : "mickey", "fortune" : "00000000000000100000" } 


> db.test123.find({ "fortune" : {$gte: "00000200000000000000"}}); 
{ "_id" : ObjectId("4f87e142f1573cffecd0f65e"), "name" : "bruce wayne", "fortune" : "00000200000000000000" } 


> db.test123.find({ "fortune" : {$lt: "00000200000000000000"}}); 
{ "_id" : ObjectId("4f87e150f1573cffecd0f65f"), "name" : "donald", "fortune" : "00000150000000000000" } 
{ "_id" : ObjectId("4f87e160f1573cffecd0f660"), "name" : "mickey", "fortune" : "00000000000000100000" } 
가 여기에 행운의 안전 가능한 최대 값을 가정 20 자리 숫자를 말할 및 패드가 0 따라 그래서 샘플 문서는 것에 당신은해야합니다

mongodb에서 문자열을 사전 적으로 비교하기 때문에 쿼리/정렬이 자연스럽게 작동합니다. 그러나 데이터에서 다른 숫자 연산을 수행하려면 데이터 처리 스크립트 (PHP, Python, Ruby 등)에 사용자 정의 논리를 써야합니다.

쿼리 및 데이터 저장의 경우이 문자열 버전이 올바르게 작동해야합니다.

0

불행히도 배열 비교에 대한 가정은 올바르지 않습니다. 예를 들어 3보다 작은 모든 배열 값 ({array : {$ lt : 3}})을 쿼리하는 범위 쿼리는 요소의 위치에 관계없이 적어도 하나의 요소가 3보다 작은 모든 배열을 반환합니다. 따라서 귀하의 접근 방식은 효과가 없습니다.

작동하는 것은 약간의 차이는 있지만 매우 큰 정수는 바이트 순서이므로 비교하면 이진 정수를 사용할 수 있습니다.그건 당신이 당신의 정수에 대한 상위 비트 한계를 설정해야하지만 그것은 매우 간단해야합니다.

db.col.find({fortune:{$gt:BinData(0, "e8MEnzZoFyMmD7WSHdNrFJyEk8M=")}}) 

그래서 당신이 문자열, 말,에서 큰 정수를 변환하는 방법을 만들 수 있습니다해야 할 것 모두 진 두-보완하고 당신 : 당신은 BinData (하위 유형 64 기수) 표기법을 사용하여 쉘에서 테스트 할 수 있습니다 다시 설정됩니다. 행운을 빌어 요.

관련 문제