我有一个非常大的数据集合,由第三方制作,它包含一个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。
我无法在任何地方找到解决方案,也许是因为没有人需要做像这样愚蠢的事情。
答案 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函数锁定数据库。