Javascript MongoDB 3.6.x在NodeJS驱动程序中更改流编组/解编组

Javascript MongoDB 3.6.x在NodeJS驱动程序中更改流编组/解编组,javascript,node.js,mongodb,Javascript,Node.js,Mongodb,我正在使用MongoDB 3.6.2的变更流(使用Mongo NodeJS驱动程序3.0.1)来尝试将可恢复的数据流实现到浏览器。因此,在我的代码中的某个时刻,我正在对更新期间返回的resume令牌(即来自变更流的更新的_id)执行JSON.stringify。我将此信息通过网络发送到前端应用程序,然后在断开连接并随后重新连接时,将此信息发送回服务器,让它知道从何处恢复。然而,我似乎不能简单地将这个JSON对象提供给要从中恢复的驱动程序,因为我得到了一个无效的恢复令牌类型,这是一个运行时错误 s

我正在使用MongoDB 3.6.2的变更流(使用Mongo NodeJS驱动程序3.0.1)来尝试将可恢复的数据流实现到浏览器。因此,在我的代码中的某个时刻,我正在对更新期间返回的resume令牌(即来自变更流的更新的_id)执行JSON.stringify。我将此信息通过网络发送到前端应用程序,然后在断开连接并随后重新连接时,将此信息发送回服务器,让它知道从何处恢复。然而,我似乎不能简单地将这个JSON对象提供给要从中恢复的驱动程序,因为我得到了一个无效的恢复令牌类型,这是一个运行时错误

stringify的结果示例如下:

{“_data”:“glpeTK8AAAABRmRfaWQAZFoygBEXtikxY6F/zgbaaqkfljhid5pgaldufqd2jmyba==”}

实际的恢复令牌似乎是一个特殊的缓冲区对象,其形式如下:

{
  _data: {
    buffer: Buffer(49),
    position = 49,
    sub_type = 0,
    _bsontype = "Binary"
  }
}
当然,我的问题是,要将字符串返回到实际的简历令牌中。缓冲区(49)本身似乎被转换成base64字符串,然后分配给_数据。我不确定其他领域是什么。我还没有找到太多关于这种令牌编组/解编组的文档,以处理向客户端恢复流数据(考虑到要扩展的多个节点服务器,简单地将令牌保留在服务器上并不是一个好的选择,因为该服务器可能会停机,客户机会尝试重新连接,因此,将令牌与它停止的位置以及它连接到的下一个从那里拾取的服务器相关联是最佳选择)

一般来说,似乎恢复令牌已被开发人员严格锁定,它包含了我可以使用的有价值的信息(我们使用的是什么集合、更新的时间戳等),但这些都没有提供给我(尽管这显然是他们将为3.7添加的功能)。同样,我甚至无法及时获取给定集合当前时刻的恢复令牌(如果我在中读取了集合并且没有任何更新,则非常有用,但如果因为集合没有发生更新而断开/重新连接,则不希望再次完全读取该集合)。但希望随着Mongo意识到其有用性,这些设施中的一些将得到增加


我已经成功地测试了在不涉及编组/解编组的情况下使用恢复令牌恢复流(即令牌作为对象位于服务器上,并且未转换为可接受的形式)。但这在缩放环境中不是很有用。

为了防止其他人有此问题,我想我会发布我当前的解决方案,尽管我仍然邀请更好的解决方案

通过BSON的魔力,我只需序列化恢复令牌,将该缓冲区转换为base64,并将其发送到浏览器。然后,当浏览器在断开/重新连接后将其发送回时,我只需从base64创建一个缓冲区,并使用BSON反序列化该缓冲区。生成的令牌就像一个符咒

即,我对更新令牌的编组如下所示:

b64String = bson.serialize(resumeToken).toString('base64');
token = bson.deserialize(Buffer.from(b64String, 'base64'));
并且,我对断开/重新连接后发送的base64令牌的解组处理如下代码所示:

b64String = bson.serialize(resumeToken).toString('base64');
token = bson.deserialize(Buffer.from(b64String, 'base64'));

或者,您可以使用MongoDB扩展JSON库:对令牌进行字符串化和解析

例如:

const EJSON = require("mongodb-extjson");

resumeToken = EJSON.stringify(changeStreamDoc._id);
及恢复:

changeStream = collection.watch([], { resumeAfter: EJSON.parse(resumeToken) });

mongodb extjson
version 2.1.0和mongodb v3.6.3

上测试,为了清楚起见,我当然会解析传入的字符串化恢复令牌,尽管这只是创建了一个看起来非常像字符串化字符串的JSON对象(数据字段的值为base64字符串,没有其他).Hey,我正在玩更改流,我的resumeToken看起来不一样,我不知道如何使用它?``{u数据:二进制{u bsontype:'Binary',子类型:0,位置:38,缓冲区:}“``我的缓冲区和你的很像,当然只是不同的字节,因为它是不同的集合名称和时间戳。我只是将我的缓冲区总结为缓冲区(49)这意味着它是一个49字节的缓冲区。我相信这个位置似乎表示缓冲区的长度,但如果是这样的话,这是一个奇怪的属性名称。在计算你的字节数时,它确实是38字节。否则,你的对象与我的完全相同。如果你在启动新的change stre时将resumeToken提供给resumeAfter选项,则am,那么您应该会看到在与resumeToken关联的更新之后发生的更新。因此,要测试这一点,您需要使用resumeToken获取更新,然后进行更多更新,然后在再次启动更改流时将resumeToken应用于ResumeTafter选项,您应该会看到后面的更新。谢谢这篇文章很有意义。