0

He guys, storing an customer-Order in the Mongodatabase. Every Order has one or more user-created "drafts" inside, which are subdocuments with their own ID. The idea is to make them available separately without involving the order itself in any way. But I can't figure how to actually search for the single subdocument by id.

My Model looks like this:

var mongoose = require('mongoose');

var orderDraftSchema = mongoose.Schema({
    name: String,
    color: String,
    price: Number,
    attributes: []
});

var orderSchema = mongoose.Schema({
    date: Date,
    value: Number,
    status: String,
    customer: {},
    drafts: [orderDraftSchema]
})

module.exports = mongoose.model('Orders', orderSchema);

How does my search have to look like? And do I need to export the subschema as well? Am I searching for my subschema, or the parentschema?

This feels very cluncy and unperformant, would love to have a more elegant solution:

var Order = require("../models/order.js");

getDraft: function(draftId, cb) {
    Order.find({
        drafts: {
            $elemMatch: {
                _id: {
                    $in: draftId
                }
            }
        }
    }, function(err, results) {
        if (err) {
            cb('No Matching Order found!');
        } else {
            var drafts = results[0].drafts;
            var resultDraft;
            for (i in drafts) {
                if (drafts[i]._id == draftId) {
                    resultDraft = drafts[i];
                }
            }

            console.log(resultDraft);
            cb(resultDraft);
        }
    });
}
Seltsam
  • 854
  • 1
  • 7
  • 27
  • Try `Order.find({drafts: { $elemMatch : {_id: { $in: draftId }}})` assuming draftId is an Array – Molda Mar 12 '16 at 11:28
  • Thanks! Now I get a result, which is nice. But now the whole order is returned. I'd just like to get the single draft, not the whole order. Is it efficient to filter the returned element for the desired draft by id now or is there a more elegant way to solve this? – Seltsam Mar 12 '16 at 12:26
  • In the callback where you get your order you need to extract that draft from drafts array by yourself i'm affraid. You can use lodash for that or simple *for loop* to find your draft. Or look here http://stackoverflow.com/questions/21113543/mongodb-get-subdocument how to use *aggregation framework* to extract one draft, but i don't know about that too much so can't help – Molda Mar 12 '16 at 12:46
  • If you need to query drafts a lot it might be a good idea to save them to a separate collection and use `drafts: [{ type: mongoose.Types.ObjectId, ref: ''}]` – Molda Mar 12 '16 at 12:50
  • Thanks, iterated and returned the specific draft now. That works, but doesnt feel very elegant. What is your last approach? Do you have a link to a documentation maybe? thanks – Seltsam Mar 12 '16 at 15:47
  • Possible dupe of http://stackoverflow.com/questions/3985214/retrieve-only-the-queried-element-in-an-object-array-in-mongodb-collection – JohnnyHK Mar 12 '16 at 16:03
  • @Seltsam if you mean using ref in drafts then have a look here https://alexanderzeitler.com/articles/mongoose-referencing-schema-in-properties-and-arrays/ – Molda Mar 12 '16 at 18:03

0 Answers0