2

In setting up a sessionStore via MongoDB for express-session, I'm having a little trouble using the findOne() function to verify that a user's information is valid and recent.

var session = require('express-session');
var mongoStore = require('connect-mongo')(session);
var mongoose = require('mongoose');

var Schema = mongoose.Schema;
var Session = mongoose.model('session', new Schema({
    sid : String,
    username : String,
    email : String
}));

...

The trick is, however, that express-session and connect-mongo are responsible for managing the writes to the database.

app.use(session({
    secret: 'secretsquirrel',
    resave: true,
    saveUninitialized: true,
    store: new mongoStore({
        mongoseConnection: mongoose.connection,
        host: '127.0.0.1',
        port: '27017',
        db: 'testdb',
        collection: 'collectionName'
    })
}));

Now, this appears to be working as it should, as documents are entered into the collection I have specified. Returning data from the collection yields the following:

{  
   "_id":"sdBYsdflAsdfyWPPneV-hrC2xsXP",
   "session":"
   {
       \"cookie\":
       {
        \"originalMaxAge\":null,\"expires\":null,\"httpOnly\":true,\"path\":\"/\"
       },
       \"email\":\"testuser@email.com\",
       \"username\":\"testuser\",
       \"sid\":\"f59106e845e11df8c3413b5f1f80ee01e876526bc3c0d05\",
   }",
   "expires":   ISODate(DateHere)
}

Where the problem appears to be that in the database, or via Mongoose, it doesn't seem to matter how I attempt to query for the SID, I return no results using any of the following:

Via Mongo:

db.collectionName.findOne({ session.sid: "sid" })
db.collectionName.findOne({ "session.sid": "sid" })
db.collectionName.findOne({ "session": { "\"sid\"": "sid" } })

Via Mongoose (NodeJS)

Session.findOne({ sid: req.session.sid }, function(err, data) {...});
Session.findOne({ "sid": req.session.sid }, function(err, data) {...});
Session.findOne({ "\"sid"\"": "\"" + req.session.sid + "\"" }, function(err, data) {...});

The stumper is, how is it in both instances I am unable to return any data that I have verified is in the collection? Do I need to account for the escaped quotes returned in the document as I have been trying to do, or is that merely output via the mongo shell?

Are there any steps I am missing for searching this data correctly? A fresh set of eyes would be greatly appreciated!

Solution:

vinagreti pointed out that the data being saved to my collections were not Objects, but rather plaintext.

By referring to connect-mongo's documentation, there is an extra option for stringify. This setting stringify's and serializes the data saved from the session into the database. Considering that express-session already produces a JSON object, using stringify() makes it unsearchable within the collection.

All that was needed was to add stringify: false to my mongoStore settings like so:

store: new mongoStore({
        mongoseConnection: mongoose.connection,
        host: '127.0.0.1',
        port: '27017',
        db: 'testdb',
        collection: 'collectionName',
        stringify: false
    })

And then voila! Everything saved to the collection is now an object and searchable! Thank you vinagreti for helping point out the problem! Please upvote his answer!

Signus
  • 1,056
  • 13
  • 41

1 Answers1

4

You are saving your session object as plain text. because of that you cannot search as an object.

Ensure that the schema of the "father" collection have the session field as type '{}' (Object) like: Father = {session: { type: {} }}

If it not work, you can try the folowing:

You can change the way you are saving the session object, saving it as an object and not as an plain text.

Or, you can search the session with a regex, trying to find the sid on the session field like:

db.user.findOne({session: /.*f59106e845e11df8c3413b5f1f80ee01e876526bc3c0d05.*/});
Bruno João
  • 3,983
  • 2
  • 18
  • 25
  • How might I go about saving the session object as an object? Does the Mongoose schema not take care of saving like so, or is it that each item within the object is plaintext? – Signus Jun 12 '15 at 19:30
  • The mongoose take care of this for you. Check if you are passing a real object to the mongoose. Maybe you are passing a string. Try to use JSON.parse(jsonString); to turn the session string in an object before save. – Bruno João Jun 12 '15 at 19:35
  • Well the items of the schema are strings, however the trick is that `express-session` and `connect-mongo` together are responsible for writing the schema to the database. – Signus Jun 12 '15 at 19:44
  • Can you show your schema for the object that have the session field? In my example, I've used "user". I think your schema should have {} as type or a ref to the session schema like: { type : Schema.Types.ObjectId, ref: 'Session' } – Bruno João Jun 12 '15 at 19:51
  • The collection that I have is 'sessions' so I call it like `db.sessions.find()`, and the field within the document is called session, as shown above. That's why my examples I refer to `session.sid` as I'm trying to refer to nested objects (although as you mention they may be purely strings). – Signus Jun 12 '15 at 19:55
  • So, in your sessionS schema, the session field must be: sessioS = {session: {type: {}}}. So the schema will accept an object as the session value. – Bruno João Jun 12 '15 at 20:00
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/80429/discussion-between-vinagreti-and-signus). – Bruno João Jun 12 '15 at 20:02
  • 1
    It looks like I found the problem! It turns out that `connect-mongo` automatically stringify's and serializes the data, which makes it return as shown above. When adding `stringify: false` to my mongoStore settings, it leaves the data as it was - an object. – Signus Jun 12 '15 at 20:09