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

cet*_*ras 0 text mongodb

我有一个由第三方制作的大量数据集,它包含一个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() }}
  );
});
Run Code Online (Sandbox Code Playgroud)

我将查找限制在一个文档中,直到我做对了.不幸的是toString没有做我期望的魔术.

另外,我试过这个:

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

结果更糟.

如果我用php读取文档,$response = $db->execute('return db.segments.findOne()');那么print_r($response),我可以验证数据是否正确存储,如base64.

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

jmi*_*ola 8

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

根据BSON规范,二进制数据字段由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()));
});
Run Code Online (Sandbox Code Playgroud)

这是一个我用来插入一些夹具数据的小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);
}
Run Code Online (Sandbox Code Playgroud)

根据数据集的大小,在PHP中进行二进制字段转换可能更合理.如果您确实想使用JavaScript,我肯定建议您通过shell客户端执行脚本而不是db.eval(),因此您不会使用长时间运行的JS函数锁定数据库.