我写了以下测试代码来说明我的问题:
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);
}
};
首先,它将类型为ObjectId的变量(来自MongoDB native)写入服务器端会话存储.然后,当您刷新页面时,将使用会话,并且参数的类型突然变为字符串.
简而言之,如果运行上面的代码,将显示以下内容:
>访问/
响应:req.session.testObjId有类型对象 – NOW REFRESH THIS PAGE
>再次访问/
响应:req.session.testObjId现在有类型字符串 – 为什么是STRING?
为什么它变换为字符串?
最佳答案 默认情况下,MongoStore会根据“stringify”选项将会话数据转换为JSON.
Here’s a link to the relevant source code. JSON仅支持基本的JavaScript数据类型(String,Number,boolean等),而不支持ObjectId等自定义对象类型.要更改此设置,请在实例化MongoStore时在选项中传递stringify:false.
更新评论中的后续行动
is there any downside to setting stringify: false?
所以请记住,JSON支持大多数应用程序的足够丰富的数据类型集. JSON的优势在于它可以使代码可移植到其他会话存储选项,而依赖完整的ObjectId实例和字符串会将代码耦合到mongodb而没有太多好处.
> JSON
>便携式
>无论如何,JSON和MongoDB都不会给你域名对象,所以KISS
> ObjectId字符串与==和===一起正常工作. ObjectId实例需要特殊处理以避免可怕的instance1 === instance2评估为false陷阱,即使它们表示相同的基础值.
> MongoDB文档
>获得真实的约会
> ObjectId实例(顺便说一句,我认为它实际上不如字符串有用)
>可能更好的查询选项
因此,任何一种方法都是可行的,并且需要权衡利弊.我会使用默认行为,除非/直到你强烈需要stringify:false.
I think Mongo is capable of storing any object?
好吧,让我们准确一点.存在由javascript标量数据类型构成的纯数据对象,然后存在具有行为的函数,方法和对象. mongodb ObjectId不仅仅是纯数据.它表示二进制值,可以存储为十六进制字符串或二进制数,但它将其包装在具有与之关联的特定方法和功能的实例中. JavaScript支持一组类型,JSON是其中的一个子集(没有函数,其他限制等),而mongodb有另一个类似于JSON但不相同的集合.