Search code examples
node.jsmongodbmongoose

Query all user records in another collection using array object id


Please I have a Customers and Orders collections, the Orders collection has a reference object_id in the Customers collection as an array;

See code below :

***Customers Model

const {Schema, model, Types} = require("mongoose");

const customerSchema = new Schema({
    Fullname: {
        type: String,        
        trim: true
    },   
    username: {
        type: String,
        unique: true,
        required: true,
        trim: true
    },
    email: {
        type: String,
        unique: true,
        required: true,
        match: [/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/, "Please enter a valid email address",]
    },    
    PhoneNo: {
        type: String,
        //unique: true,
        //required: true,        
    },    
    CreatedAt: {
        type: Date,                
    },
    LastVisitDate: {
        type: Date,                
    },
    orders: [
        {
            type: Schema.Types.ObjectId,
            ref: "Order"
        },
    ],
    {
    toJSON: {
        virtuals: true,
        getters: true
    },
    id: false
});

***Order Model

const {Schema, model, Types} = require("mongoose");

const productSchema = new Schema(
    {
      productCode: {
        type: Schema.Types.ObjectId,
        default: () => new Types.ObjectId(),
      },
      productDescription: {
        type: String,
        required: true,
        maxlength: 350,
      },
       productMediaType: {
        type: String,
        enum: ['Photo', 'Video']                
      },
       productMediaFile: {
        type: String,        
        maxlength: 80,
      },
      username: {
        type: String,        
      },
      createdAt: {
        type: Date,
        default: Date.now,        
      },
    },
    {
      toJSON: {
        getters: true,
      },
    }
  );

const orderSchema = new Schema(
    {
      orderCode: {
        type: String,
        //required: true,
        maxlength: 280,
      },
      orderDescription: {
        type: String,
        required: true,
        maxlength: 350,
      },      
      createdAt: {
        type: Date,
        default: Date.now,        
      },
      username: {
        type: String,        
      },
      products: [productSchema],      
    },
    {
      toJSON: {
        virtuals: true,
        getters: true,
      },
      id: false,
    }
  );

const Order = model("Order", orderSchema);

***Expectations

a) Please how do I select all Orders that is created by a specific Customer using mongoose? Say I have a Customer that created 20 Orders in the Orders collection, I have each Order object_id in the Customers collection as a reference but how do I find all Orders by a specific Customers?

b) How do I as well find all Products that is available in Orders collection since I have the Product object _id as a ref in the Orders collection?

Thank you and have a blessed week ahead.


Solution

  • To select all Orders that have been made by a specific Customer you can use populate. You have correctly set up a reference to each Order in your Customer schema. I can't tell you how many developers miss that step. Below is an example of how to do it in a GET route. This will return the Customer with all their orders embedded in the document i.e it replaces the array of ObjectIds with their full document:

    // The :id will be the Customer ObjectId
    app.get('/orders/customer/:id', async (req, res, next) => {
        try {
            const customer = await CustomerModel.findById(req.params.id).populate({ 
               path: 'orders', 
               model: OrderModel 
            });
            res.status(200).json({
                customer : customer
            });
        } catch(err) {
           console.log(err)
           //Handle error
        }
    });
    

    With regards to your second question you have adopted a different approach in your Orders schema in relation to the Products. In your orderSchema each object in products is essentially a subdocument that is embedded in the top-level document. In contrast, within in your customerSchema, each orders is a referenced document and are separate top-level documents. I suspect you don't have a products collection on MongoDB so you can't do references. On the flip-side when you select all Orders each document will contain the full Product as it's an embedded document.