0

I'm working on a simple login system for my NodeJS application. For this I have created a structure where one object, a "corporation", holds an array of users. I've done because I plan to use the corporation object to store application session data.

{
    "name": "My Corporation",
    "prefix": "MYCORP",
    "users": [
        {
            "username": "[email protected]",
            "password": "974dae09cd5869958c19e1742117c2f8",
            "name": "Freddly the User"
        },
        {
            "username": "[email protected]",
            "password": "974dae09cd5869958c19e1742117c2f8",
            "name": "Max the Admin"
        }
    ]
}

The problem is when querying after a user (in a log-in scenario) the query, as expected, returns the entire corporation object. Thus I'm exposing all users even though I only want one. As far as security is concerned I guess it isn't a big deal, but I'm more worried about performance. Below is the current query and a very ugly way to delete all users but the one requested.

Ignore the different asserts. Code is very much work-in-progress .. :)

db.collection('kat_corp', function (err, collection) {
    try {
        assert.equal(null, err);

        collection.findOne({
            users: {
                $elemMatch: {
                    username: user.username
                }
            }
        }, function (err, result) {
            if (err) callback(err, false);

            // Delete all other users from the to-be session object
            for (var i = 0; i < result.users.length; i++) {
                if (result.users[i].username != user.username) {
                    delete result.users[i];
                }
            }
            // Will be replaced with success callback
            console.log(result);
        });

    } catch (err) {
        callback(err, false);
    }
});
6
  • 1
    Can you not add a bunch of users to the database, each having a reference to a 'corporation'? Commented May 25, 2013 at 11:24
  • 1
    I think that mongoose would help you quite a bit here! You can make a query and select the fields you want exclude in the result Commented May 25, 2013 at 11:29
  • While it might be possible using the aggregation framework, it would be far more efficient to split the users into a unique collection, one document per user, with a field for corporation-id. Commented May 25, 2013 at 11:51
  • Yes, but that sounds an awful lot like a relation based structure? At least it would be a weak link which could be a problem on changes in the corporation collection. Another (small) problem with that approach is that I would have to fetch the corporation in a separate query. Commented May 25, 2013 at 12:18
  • @KGChristensen perhaps this post is useful. It explains the pros and cons of nesting vs separate documents/collections. Commented May 25, 2013 at 14:04

1 Answer 1

2

If you're using MongoDB 2.2 or greater you can just use the "$" positional operator.

The following query worked for me :

db.collection('kat_corp', function (err, collection){
    collection.findOne({"users.username":user.username}, {'name':1,'users.$': 1}, console.log) 
});

Although I would agree with the other comments that you should probably reconsider your schema...

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, that worked. However I think I'll redesign the schema as suggested in the comments.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.