2012-07-10 4 views
0

제 3 자에 의해 만들어진 꽤 큰 데이터 콜렉션이 있는데, 보통 ASCII가 실제로 저장된 Bindata "패키지"컬럼을 포함하고 있습니다. 그들은 텍스트를 문자열로 저장할 수있었습니다.Bongata로 저장된 텍스트를 mongodb에 내 보냅니다.

이 컬렉션을 csv 형식으로 내 보내야합니다.이 컬렉션은 mongoexport와 잘 호환되지만 출력에는 "패키지"열의 base64 인코딩 값이 포함되어 있습니다. BinData(0,\"NDYuN.....==")이 아니라 해당 열의 실제 텍스트가 필요합니다. 지금까지 IS 같은 새 열 "RAWDATA"로 컬렉션을 업데이트하려고했습니다 무엇

은 :

db.segments.find({"_id" : ObjectId("4fc79525f65181293930070b")}).forEach(function(data) { 
    db.segments.update(
    {_id:data._id}, 
    {$set:{ "rawData" : data.package.toString() }} 
); 
}); 

나는 바로 그것을 얻을 때까지 하나 개의 문서에 찾기를 제한했습니다. 불행히도 toString은 내가 기대하는 마법을 수행하지 않습니다.

또한, 나는이 시도했다 :

db.segments.find({"_id" : ObjectId("4fc79525f65181293930070b")}).forEach(function(data){ 
    data.package = new String(data.package); 
    db.segments.save(data); 
}); 

결과는 더욱 심각했다. 나는 PHP로 문서, $response = $db->execute('return db.segments.findOne()'); 다음 print_r($response)을 읽으면

, 나는 64 기수로, 데이터가 제대로 저장되어있는 것을 확인할 수 있습니다.

어디서나 솔루션을 찾을 수 없었습니다. 아무도 이처럼 어리석은 짓을 할 필요가 없었기 때문일 것입니다.

답변

8

JavaScript BinData 개체의 메서드는 각각 base64()hex()이며 각 형식으로 문자열을받을 수 있습니다.

BSON spec에 따라, 이진 데이터 필드가 32 비트 정수 길이로 구성된다 : JS 내의 텍스트 스트링에이 값을 디코딩에 관해서는, 몇 가지 옵션이 , 하위 유형 및 바이트 배열. JS에서 리턴 된 base64 및 16 진 표현은 정수 길이가 앞에 붙은 바이트 배열을 포함합니다. 즉, 값을 디코딩 한 후 처음 4 바이트를 제거해야합니다. 여기에 두 옵션을 모두 사용하는 예제입니다 :

// https://stackoverflow.com/a/3058974/162228 
function decode_base64(s) { 
    var e={},i,k,v=[],r='',w=String.fromCharCode; 
    var n=[[65,91],[97,123],[48,58],[43,44],[47,48]]; 

    for(z in n){for(i=n[z][0];i<n[z][1];i++){v.push(w(i));}} 
    for(i=0;i<64;i++){e[v[i]]=i;} 

    for(i=0;i<s.length;i+=72){ 
     var b=0,c,x,l=0,o=s.substring(i,i+72); 
     for(x=0;x<o.length;x++){ 
      c=e[o.charAt(x)];b=(b<<6)+c;l+=6; 
      while(l>=8){r+=w((b>>>(l-=8))%256);} 
     } 
    } 
    return r; 
} 

// https://stackoverflow.com/a/3745677/162228 
function hex2a(hex) { 
    var str = ''; 
    for (var i = 0; i < hex.length; i += 2) 
     str += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); 
    return str; 
} 

db.segments.find().forEach(function(doc){ 
    print(decode_base64(doc.package.base64())); 
}); 

db.segments.find().forEach(function(doc){ 
    print(hex2a(doc.package.hex())); 
}); 

가 그리고 여기 몇 가지 고정 데이터를 삽입하는 데 사용 작은 PHP 스크립트입니다 : 데이터 세트의 크기에 따라

<?php 

$mongo = new Mongo(); 
$c = $mongo->selectCollection('test', 'segments'); 
$c->drop(); 

$c->save(['package' => new MongoBinData('foo')]); 
$c->save(['package' => new MongoBinData('bar')]); 

foreach ($c->find() as $doc) { 
    printf("%s\n", $doc['bindata']->bin); 
} 

를, 그것은 가능성이 더 합리적 할 수 있어요 PHP의 바이너리 필드 변환. 자바 스크립트를 사용하려면, db.eval() 대신 셸 클라이언트를 통해 스크립트를 실행하는 것이 좋습니다. 따라서 장기 실행 JS 함수로 데이터베이스를 잠그지 마십시오.

+0

감사합니다. 아주 좋은 답변입니다. 나는 PHP 방식을 선택했지만 다른 기능도 훌륭하게 작동합니다. 유일한 방법은, 내 데이터가 "잘려서"(결과는 46.772247 대신에 72247로 시작했기 때문에) 사용 예제에서'.substr (4)'를 제거해야했다. – ceteras

+0

흥미 롭습니다. 사용하고있는 MongoDB의 버전을 물어봐도 될까요? 위의 경우 2.1.0을 실행했습니다. 바이너리 데이터 "foo"를 삽입하고 JS 콘솔에서 바이너리 데이터를 선택하면,'hex()'메소드는'03000000666f6f'를 반환합니다. – jmikola

+0

나는 1.8.2를 사용하고있다 – ceteras

관련 문제