Search code examples
javascriptnode.jsmongodbmongoose

mongoose model, array of strings, array of objects structure


I am trying to design my database model and i dont have clue how to fit array of strings and array of objects into it. My current model is:

const mongoose = require("mongoose");
const Schema = mongoose.Schema;

const schema = new Schema({
    email: { type: String, unique: true, required: true },
    hash: { type: String, required: true },
    createdDate: { type: Date, default: Date.now },
    settings: {
        favorites: { /* ??? */ },
        cart: { /* ??? */ },
        states: {
            favorites: { type: Boolean, default: true },
            search: { type: Boolean, default: false },
            category: { type: Schema.Types.Mixed, default: false }
        }
    }
});

schema.set("toJSON", { virtuals: true });

module.exports = mongoose.model("User", schema);

favorites data structure is ['234', '564', '213', '782']

cart example data structure is:

[
    { quantity: 5, marketId: '234' },
    { quantity: 2, marketId: '564' },
    { quantity: 7, marketId: '213' },
    { quantity: 3, marketId: '782' }
]

How can i add this as configuration to the mongoose model?


Solution

  • Favorites must be an array of String like this: favorites: [String]

    For the cart array we have two main options:

    1. We can define the cart as an array of subdocuments.
    const schema = new Schema({
      email: { type: String, unique: true, required: true },
      hash: { type: String, required: true },
      createdDate: { type: Date, default: Date.now },
      settings: {
        favorites: [String],
        cart: [
          {
            quantity: Number,
            marketId: String
          }
        ],
        states: {
          favorites: { type: Boolean, default: true },
          search: { type: Boolean, default: false },
          category: { type: Schema.Types.Mixed, default: false }
        }
      }
    });
    
    1. Or we can declare cart as an array of schema types.
    const schema = new Schema({
      email: { type: String, unique: true, required: true },
      hash: { type: String, required: true },
      createdDate: { type: Date, default: Date.now },
      settings: {
        favorites: [String],
        cart: [
          new Schema({
            quantity: Number,
            marketId: String
          })
        ],
        states: {
          favorites: { type: Boolean, default: true },
          search: { type: Boolean, default: false },
          category: { type: Schema.Types.Mixed, default: false }
        }
      }
    });
    

    For both of them, when you create a document, it will look like this, note that mongoose added _id field in the card items.

    {
        "settings": {
            "states": {
                "favorites": true,
                "search": false,
                "category": false
            },
            "favorites": [
                "234",
                "564",
                "213",
                "782"
            ],
            "cart": [
                {
                    "_id": "5e6cd0bd53feb32d50699b79",
                    "quantity": 5,
                    "marketId": "234"
                },
                {
                    "_id": "5e6cd0bd53feb32d50699b78",
                    "quantity": 2,
                    "marketId": "564"
                },
                {
                    "_id": "5e6cd0bd53feb32d50699b77",
                    "quantity": 7,
                    "marketId": "213"
                },
                {
                    "_id": "5e6cd0bd53feb32d50699b76",
                    "quantity": 3,
                    "marketId": "782"
                }
            ]
        },
        "_id": "5e6cd0bd53feb32d50699b75",
        "email": "[email protected]",
        "hash": "hash...",
        "createdDate": "2020-03-14T12:40:29.969Z",
        "__v": 0,
        "id": "5e6cd0bd53feb32d50699b75"
    }
    

    If you don't want _id fields in cart array, you can add _id: false option the cart schema like this:

        cart: [
          new Schema(
            {
              quantity: Number,
              marketId: String
            },
            { _id: false }
          )
        ],
    

    Here are some useful docs:

    Arrays

    Subdocuments