G. Deward
G. Deward

Reputation: 1592

How to find parent doc by querying subdocument using Mongoose?

In the example below, how can I find the Account (parent) docs where a specific member ID has a Membership (subdocument)? I have tried using both $elemMatch and direct query objects.

Note: Both schemas have a deleted flag field (dd). If this field is set then the record has been deleted and should not be returned:

var mongoose    = require('mongoose')

var membershipSchema = new mongoose.Schema({

    m : { type: mongoose.Schema.ObjectId, ref: 'member' },      // Member
    b : { type: Date, required: true },                         // Begin Date
    e : { type: Date },                                         // End Date

    dd  : { type: Date },                                       // Deleted Date
    dm  : { type: mongoose.Schema.ObjectId, ref: 'member' }     // Deleted By Member
});

var accountSchema = new mongoose.Schema({

    n   : { type: String, trim: true },                         // Display Name

    m   : [ membershipSchema ],                                 // Membership List

    dd  : { type: Date },                                       // Deleted Date
    dm  : { type: mongoose.Schema.ObjectId, ref: 'member' }     // Deleted By Member
});

var accountModel = mongoose.model('account', accountSchema);

module.exports = accountModel;

I would like to return all Account documents, either with or without the Membership subdocuments. However, I will not know anything about the Account when the query is executed.

This is what I was trying:

var query = {
    m : {
        $elemMatch: {
            m  : req.appData.member.id,
            dd : { $exists: false }
        }
    },
    dd : { $exists: false }
};

Account.find(query, function (err, accounts) {
    // Do something
});

Upvotes: 2

Views: 1387

Answers (1)

Fred Lackey
Fred Lackey

Reputation: 2391

I've tested it several times and the syntax above is correct. Using the query object as shown will cause all top-level Account objects to be returned where the Member's ID exists in a subdocument. And, by checking for the existence (or lack thereof) of the dd field (your delete flag), only objects that are NOT marked as "deleted" will be returned.

Just in case you need to tweak your original question. Here is the correct syntax we are discussing:

var query = {
    m : {
        $elemMatch: {
            m  : req.appData.member.id,
            dd : { $exists: false }
        }
    },
    dd : { $exists: false }
};

Account.find(query, function (err, accounts) {
    // accounts will contain an array of valid
    // items and will be populated with the
    // subdocuments.
});

Upvotes: 1

Related Questions