Why is a session parameter of type ObjectID (MongoDB) converted to a string?

I wrote the following test code to illustrate my problem:

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); } }; 

First, it writes a variable of type ObjectId (from MongoDB native) to the server-side session store. When you refresh the page, a session is used and the parameter type suddenly changes to a string.

In short, if you run the above code, the following will appear:

  • visit /

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

  • visit again /

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

Why is this conversion to string?

+4
source share
1 answer

MongoStore by default converts session data to JSON based on the "stringify" parameter. Here is a link to the corresponding source code . JSON only supports basic JavaScript data types (String, Number, boolean, etc.), and not custom object types such as ObjectId. To change this, pass stringify: false to options when instantiating MongoStore .

Update for subsequent comments in the comments

Is there a flaw in setting stringify: false?

Therefore, keep in mind that JSON supports a fairly rich set of data types for most applications. At the top of JSON, it keeps your code portable for other session storage options, while using a full instance of ObjectId against the string will bind your code to mongodb without any special benefits.

  • Json
    • portable
    • neither JSON nor MongoDB will give you domain objects, so KISS
    • ObjectId strings work correctly with == and === . ObjectId instances require special handling to avoid the scary evaluation of the false trap instance1 === instance2 , even if they represent the same underlying value.
  • MongoDB Document
    • get real dates
    • ObjectId objects (which, in my opinion, are actually less useful than strings, by the way)
    • Probably the best query options

Thus, any of the approaches is viable and there are trade-offs. I would just use the default behavior if / until you need stringify:false .

I think Mongo is capable of storing any object?

Ok, let's be right here. There are pure data objects created from scalar javascript data types, and then there are functions and methods and objects with behavior. Mongodb ObjectId is not just pure data. It represents a binary value that can be stored as a hexadecimal string or binary number, but it completes it in an instance using certain methods and functions associated with it. JavaScript supports a set of types, JSON is a subset of this (no functions, other restrictions, etc.), and mongodb has a different set, similar to JSON, but not identical.

+2
source

Source: https://habr.com/ru/post/1501124/


All Articles