导出存储为mindodb中的Bindata的文本

时间:2012-07-10 09:16:10

标签: mongodb text

我有一个非常大的数据集合,由第三方制作,它包含一个Bindata“包”列,其中实际存储了普通ASCII。 我的意思是,他们可以将文本存储为字符串。

我必须以csv格式导出此集合,这与mongoexport非常有效,但输出包含“package”列的base64编码值。我需要该列中的实际文本,而不是BinData(0,\"NDYuN.....==")

到目前为止我尝试过的是使用新列“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)阅读文档,我可以验证数据是否正确存储,如base64。

我无法在任何地方找到解决方案,也许是因为没有人需要做像这样愚蠢的事情。

1 个答案:

答案 0 :(得分:8)

JavaScript BinData对象具有base64()hex()方法,您可以使用这些方法以相应的格式接收字符串。至于将这些值解码为JS中的文本字符串,您有一些选择:

根据BSON spec,二进制数据字段由32位整数长度,子类型和字节数组组成。 JS中返回的base64和十六进制表示包含前缀为整数长度的字节数组。这意味着在解码值之后,我们将要剥离前四个字节。以下是使用这两个选项的示例:

// 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中进行二进制字段转换可能更合理。如果您确实想使用JavaScript,我肯定建议您通过shell客户端而不是db.eval()执行脚本,因此您不会使用长时间运行的JS函数锁定数据库。