如何使用JavaScript中任意多个文档反序列化转储的BSON?
我有一个如何使用JavaScript中任意多个文档反序列化转储的BSON?,javascript,node.js,mongodb,bson,Javascript,Node.js,Mongodb,Bson,我有一个BSON文件,它来自数据库的mongoexport。假设数据库是todo,集合是items。现在我想将数据脱机加载到我的RN应用程序中。由于集合可能包含任意多个文档(假设当前有2个),因此我想使用一种方法来解析文件,不管它包含多少文档 我尝试过以下方法: 使用外部bsondump可执行文件 我们可以使用外部命令将文件转换为JSON bsondump --outFile items.json items.bson 但我正在开发一个移动应用程序,所以在shell命令中调用第三方可执行文件并
BSON
文件,它来自数据库的mongoexport
。假设数据库是todo
,集合是items
。现在我想将数据脱机加载到我的RN应用程序中。由于集合可能包含任意多个文档(假设当前有2个),因此我想使用一种方法来解析文件,不管它包含多少文档
我尝试过以下方法:
bsondump
可执行文件JSON
bsondump --outFile items.json items.bson
但我正在开发一个移动应用程序,所以在shell命令中调用第三方可执行文件并不理想。另外,输出包含几行一行JSON对象,因此从技术上讲,输出不是正确的JSON文件。因此,事后解析并不优雅
js bson
库中使用反序列化
const bson = require('bson')
const fs = require('fs')
bson.deserialize(fs.readFileSync(PATH_HERE))
但这带来了一个错误
Error: buffer length 173 must === bson size 94
加上这个选项,
bson.deserialize(fs.readFileSync(PATH_HERE), {
allowObjectSmallerThanBufferSize: true
})
错误已解决,但只返回第一个文档。因为文档中没有提到这个函数只能解析1-document集合,所以我想知道是否有一些选项支持多文档读取
js bson
bson-stream
库react native fetch blob
而不是fs
,根据他们的文档,stream对象没有pipe
方法,这是在bson stream
doc中演示的唯一方法。因此,尽管这种方法不需要文档数量,但我不知道如何使用它
// fs
const BSONStream = require('bson-stream');
fs.createReadStream(PATH_HERE).pipe(new BSONStream()).on('data', callback);
// RNFetchBlob
const RNFetchBlob = require('react-native-fetch-blob');
RNFetchBlob.fs.readStream(PATH_HERE, ENCODING)
.then(stream => {
stream.open();
stream.can_we_pipe_here(new BSONStream())
stream.onData(callback)
});
另外,我不确定上面的
编码。我已经阅读了js bson
的源代码,并找到了解决问题的方法。我认为最好在这里保存详细记录:
方法1
我们自己分割文档,并将文档逐个提供给解析器
BSON内部格式
假设我们的todo/items.bson
的.json
转储是
{_id: "someid#1", content: "Launch a manned rocket to the sun"}
{_id: "someid#2", content: "Wash my underwear"}
这显然违反了JSON语法,因为没有外部对象将事物包装在一起
内部BSON的形状类似,但似乎BSON允许在一个文件中填充这种多对象
然后,对于每个文档,四个前导字节表示该文档的长度,包括前缀本身和后缀。后缀只是一个0字节
最终的BSON文件类似于
LLLLDDDDDDD0LLLLDDD0LLLLDDDDDDDDDDDDDDDDDDDDDD0...
其中,L
是长度,D
是二进制数据,0
实际上是0
算法
因此,我们可以开发一个简单的算法来获取文档长度,使用allowObjectsSmallerThanBufferSize
进行bson.反序列化
,这将从缓冲区开始获取第一个文档,然后切掉该文档并重复
关于编码
我提到的另一件事是在React本地上下文中进行编码。处理React Native persistent的库似乎都缺乏从文件读取原始缓冲区的支持。我们最接近的选择是base64
,它是任何二进制文件的字符串表示形式。然后我们使用Buffer
将base64
字符串转换为缓冲区,并输入上述算法
代码
反序列化.js
const BSON=require('BSON');
函数_getNextObjectSize(缓冲区){
//这就是BSON的方式
返回缓冲区[0]|(缓冲区[1]反序列化(缓冲区数据))
.then(jsData=>{/*在此处执行任何操作*/})
方法2
上面的方法读取整个文件。有时,当我们有一个非常大的.bson
文件时,应用程序可能会崩溃。当然,可以将上面的readFile
更改为readStream
,并添加各种检查以确定当前区块是否包含文档的结尾。这可能会很麻烦,而且我们实际上是r通过电子方式编写bson-stream
库
因此,我们可以创建一个RNFetchBlob
文件流,以及另一个bson流
解析流。这让我们回到了问题中的尝试4
阅读源代码后,BSON解析流从node.js转换字符串继承而来。我们可以手动将onData
和onEnd
中的块和事件转发到on('data')
和on('end')
由于bson-stream
不支持将选项传递给底层bson
库调用,因此可能需要在自己的项目中稍微调整库源代码
LLLLDDDDDDD0LLLLDDD0LLLLDDDDDDDDDDDDDDDDDDDDDD0...