4

我编写了以下测试代码来说明我的问题:

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 本机)写入服务器端会话存储。然后刷新页面时,使用了会话,参数的类型突然变成了字符串。

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

  1. 访问/

    回复:req.session.testObjId has type object - NOW REFRESH THIS PAGE

  2. /再次访问

    回复:req.session.testObjId now has type string - WHY A STRING?

为什么会变成字符串?

4

1 回答 1

2

MongoStore 默认基于“stringify”选项将会话数据转换为 JSON。这是相关源代码的链接。JSON 仅支持基本的 JavaScript 数据类型(字符串、数字、布尔值等),不支持自定义对象类型,例如 ObjectId。要更改这一点,stringify: falseoptions在实例化您的MongoStore.

更新评论中的后续行动

设置 stringify: false 有什么缺点吗?

因此请记住,对于大多数应用程序,JSON 支持足够丰富的数据类型集。JSON 的优势在于它使您的代码可移植到其他会话存储选项,而依赖完整ObjectId实例与字符串会将您的代码耦合到 mongodb 而没有太多好处。

  • JSON
    • 便携的
    • JSON 和 MongoDB 都不会给你域对象,所以 KISS
    • ObjectId 字符串与==和一起正常工作===。ObjectId 实例需要特殊处理以避免可怕的instance1 === instance2评估错误陷阱,即使它们代表相同的基础值。
  • MongoDB 文档
    • 获取真实日期
    • ObjectId 实例(顺便说一下,我认为它实际上不如字符串有用)
    • 可能更好的查询选项

因此,任何一种方法都是可行的,并且需要权衡取舍。我只会使用默认行为,除非/直到您强烈需要stringify:false.

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

好吧,让我们在这里准确一点。有由 javascript 标量数据类型制成的纯数据对象,然后是具有行为的函数、方法和对象。mongodbObjectId不仅仅是纯数据。它表示一个二进制值,可以存储为十六进制字符串或二进制数,但它使用与其关联的特定方法和函数将其包装在一个实例中。JavaScript 支持一组类型,JSON 是其中的一个子集(没有函数、其他限制等),而 mongodb 有另一组与 JSON 相似但不完全相同。

于 2013-09-08T16:02:41.137 回答