Search code examples
node.jsmongodbmongoosemongodb-querymongoose-schema

Mongoose Query with Dynamic Key that also contains the "and" operator


So I'm trying to query my MongoDB database using mongoose to fetch documents that have a specific family AND a specific analysis ID at the same time. Here is an example of the document structure:

_id: ObjectId("62b2fb397fda9ba6fe24aa5c")
day: 1
family: "AUTOMOTIVE"
prediction: -233.99999999999892
analysis: ObjectId("629c86fc67cfee013c5bf147")

The problem I face in this case is that the name of the key of the family field is set dynamically and could therefore have any other name such as "product_family", "category", etc. This is why, in order to fetch documents with a dynamic key name, I have to use the where() and equals() operators like so:

// Get the key of the field that is set dyncamically.
let dynamicKey = req.body.dynamicKey;

// Perform a query using a dynamic key.
documents = await Model.find().where(dynamicKey).equals(req.body.value);

HOWEVER, my goal here is NOT to just fetch all the documents with the dynamic key, but rather to fetch the documents that have BOTH the dynamic key name AND ALSO a specific analysis Id.

Had the family field NOT been dynamic, I could have simply used a query like so:

documents = await Model.find({ 
   $and: [{analysis: req.body.analysis_id}, {family: req.body.value}] 
});

but this does not seem possible in this case since the keys inside the find() operator are mere text strings and not variables. I also tried using the following queries with no luck:

documents = await Model.find().where(dynamicKey).equals(req.body.value).where('analysis').equals(req.body.analysis_id);

documents = await Model.find().where(dynamicKey).equals(req.body.value).where('analysis').equals(req.body.analysis_id);

Can somebody please help?


Solution

  • As @rickhg12hs mentioned in the comments, part of the answer is to use the [] brackets to specify your dynamic key like so:

    await Model.find({[dynamicKey]: req.body.value, analysis: req.body.analysis_id});

    I also found out that another query that can work is this:

    await Model.find({analysis:req.body.analysis_id}).where(dynamicKey).equals(req.body.value);

    However, it seems that for either of these solutions to work you also need to set your schema's strict mode to "false", since we are working with a dynamic key value.

    Example:

    var predictionSchema = new mongoose.Schema({   
        day: {
            type: Number,
            required: true
        },
        prediction: {
            type: Number,
            required: true
        },
        analysis: {
            type: mongoose.Schema.Types.ObjectId, 
            ref: 'Analysis', // Reference the Analysis Schema
            required: true
        }
    }, { strict: false });