A. L
A. L

Reputation: 12679

mongoose - how to get subdocument to comply with a schema

So I have the following schemas:

var Item_Detail = new Schema(
    {
        content: {
            index: true,
            type: Array
        },
        is_private: {
            default: false,
            index: true,
            type: Boolean
        },
        order: {
            index: true,
            required: true,
            type: Number
        },
        table: {
            default: {},
            type: Object
        },
        title: {
            required: true,
            index: true,
            type: String,
        },
        type: {
            default: "text",
            enum: ["text", "table"],
            index: true,
            type: String
        },
    },
    {
        strict: false
    }
)

const Item = new Schema(
    {
        details: {
            default: [],
            index: true,
            type: [Item_Detail],
        },
        display_name: {
            default: "",
            index: true,
            type: String,
        },
        image: {
            default: "http://via.placeholder.com/700x500/ffffff/000000/?text=No%20Image&",
            type: String
        },
        is_private: {
            default: false,
            index: true,
            type: Boolean
        },
        tags: {
            index: true,
            type: [Tag]
        }
    },
    {
        strict: false
    }
)

Now, Item_Detail is to be a subdocument of Item, but I'm not quite sure how I should enforce the defaults and type restriction. I also don't want Item_Detail to be a collection in its own right, so using create or save probably doesn't fit.

Upvotes: 1

Views: 180

Answers (2)

Akrion
Akrion

Reputation: 18525

Enforcing the type is easy the default value is the tricky one but mongoose allows you to specify a function instead of boolean for default (just like it allows you the same for required).

So you could do something like this (I shortened the schemas for bravity):

const itemDetails = new Schema({
  info: {
    type: String,
    required: true
  }
})

const item = new Schema({
  details: {
    default: function() {
      return [new ItemDetails({ info: 'N/A' })]
    },
    type: [itemDetails],
  }
})

This would allow you to do something like this:

var itm = new Item();

And the saved result would be:

{
  "_id": ObjectId("5b72795d4aa17339b0815b8b"),
  "details": [{
    "_id": ObjectId("5b72795d4aa17339b0815b8c"),
    "info": "N/A"
  }]
}

So this gives you two things:

  1. You cannot put any type in details other than itemDetails since you enforced the type with itemDetails.
  2. You initialize your ItemDetails object with defaults you want in your default custom function.

Hope this helps.

Upvotes: 0

Craques
Craques

Reputation: 1143

I think you can use embedded documents for this so in your item schema you can embed an item_detail:

const Item = new Schema({
    ...
    item_detail: item_detail
})

Then on the server when you want to add an item_detail you can do the following

myItem = new Item({//enter item data here})
//assign item detail here
myItem.item_detail = item_detail ;

then proceed to save it

myItem.save()

Upvotes: 2

Related Questions