为什么具有ObjectID(MongoDB)types的会话参数转换为string?

我写了下面的testing代码来说明我的问题:

var express = require("express"), MongoStore = require("connect-mongo")(express), mongoose = require("mongoose"), config = require(process.cwd() + "/src/config"); exports.run = function() { console.info("running http server"); //create a new HTTP server var server = express(); //sessions server.use(express.cookieParser(config.sessions.secret)); server.use(express.session({ secret: config.sessions.secret, key: config.sessions.key, proxy: true, cookie: {maxAge: config.sessions.maxAge, signed: true}, store: new MongoStore({ mongoose_connection: mongoose.connection }, onStoreSetup)})); //create a test ObjectID parameter var testObjId = new mongoose.Types.ObjectId("522bb0205a259c636c000006"); server.get("/", function(req, res) { if (req.session && req.session.testObjId) { res.send("req.session.testObjId now has type " + typeof req.session.testObjId + " - WHY A STRING?"); } else { req.session.testObjId = testObjId; req.session.save(function(err) { if (err) throw err; res.send("req.session.testObjId has type " + typeof req.session.testObjId + " - an Object, as expected - NOW REFRESH THIS PAGE"); }); } }); //listen for incoming connections once session store is setup function onStoreSetup() { console.info("mongo session store connected"); server.listen(config.http.port); console.info("http server listening on port %d", config.http.port); } }; 

首先它将一个types为ObjectId(从MongoDB本地)的variables写入服务器端会话存储。 当你刷新页面时,会话被使用,并且参数的types突然变成了一个string。

简而言之,如果您运行上面的代码,将会显示以下内容:

  1. 访问/

    响应: req.session.testObjId has type object - NOW REFRESH THIS PAGE

  2. 再次访问

    响应: req.session.testObjId now has type string - WHY A STRING?

为什么它变成了一个string?

根据“stringify”选项,MongoStore默认将会话数据转换为JSON。 这是一个链接到相关的源代码 。 JSON仅支持基本的JavaScript数据types(string,数字,布尔等),而不是自定义对象types,如ObjectId。 要改变这一点,在实例化MongoStore时在你的options传递stringify: false

更新后续评论

是否有任何缺点设置stringify:false?

所以请记住,JSON支持大多数应用程序的一组足够丰富的数据types。 JSON的优势在于它使您的代码可移植到其他会话存储选项,而依靠完整的ObjectId实例与string将使您的代码与mongodb耦合,而没有太多好处。

  • JSON
    • 手提
    • 无论是JSON还是MongoDB都不会给你域对象,所以KISS
    • ObjectIdstring与=====正确工作。 ObjectId实例需要特殊的处理,以避免糟糕的instance1 === instance2错误陷阱,即使它们表示相同的基础值。
  • MongoDB文档
    • 得到真正的date
    • ObjectId实例(顺便说一句,我认为实际上比string更有用)
    • 可能更好的查询选项

所以任何一种方法都是可行的,并且有折衷。 我只是使用默认的行为,除非/直到你需要stringify:false

我认为Mongo能够存储任何对象?

那么,让我们在这里精确。 有一些由JavaScript标量数据types构成的纯数据对象,然后是具有行为的函数,方法和对象。 一个mongodb的ObjectId不只是纯粹的数据。 它表示一个二进制值,可以存储为hexstring或二进制数字,但是它会将其包含在具有特定方法和function的实例中。 JavaScript支持一组types,JSON是其中的一个子集(没有函数,其他限制等),而mongodb有另外一个与JSON类似但不相同的集合。