Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing site config as Mongoose model

I have website configuration (currently stored as JSON file), and I would like to move it to MongoDB and probably use Mongoose to handle read-write operations and perform validation through schemas.

Configuration is an object with limited amount of keys, similar to that:

{
  siteOffline: false,
  storeOffline: false,
  priceMultipliers: {
    a1: 0.96
    a2: 0.85
  },
  ...
}

Should it be made a collection with key-value entries? Not sure how to enforce Mongoose schema in this case.

Should it be made a collection with a single document? Not sure how to guarantee that there is only one document at a time.

Any other options?

like image 797
Estus Flask Avatar asked Nov 30 '16 07:11

Estus Flask


People also ask

What is the difference between a Mongoose schema and model?

Mongoose Schema vs. Model. A Mongoose model is a wrapper on the Mongoose schema. A Mongoose schema defines the structure of the document, default values, validators, etc., whereas a Mongoose model provides an interface to the database for creating, querying, updating, deleting records, etc.

What is virtuals in Mongoose?

In Mongoose, a virtual is a property that is not stored in MongoDB. Virtuals are typically used for computed properties on documents.

What does $Set do in Mongoose?

Mongoose getters and setters allow you to execute custom logic when getting or setting a property on a Mongoose document. Getters let you transform data in MongoDB into a more user friendly form, and setters let you transform user data before it gets to MongoDB.

Why we use Mongoose instead of MongoDB?

Using mongoose , a user can define the schema for the documents in a particular collection. It provides a lot of convenience in the creation and management of data in MongoDB. On the downside, learning mongoose can take some time, and has some limitations in handling schemas that are quite complex.


2 Answers

Ok, one thing at a time :

if you want to use mongoose, you should have your full config as one document :

var siteConfig = new Schema({
  siteOffline: Boolean,
  storeOffline: Boolean,
  priceMultipliers: {
    a1: Number
    a2: Number
  } 
});

Then, if you want a one document only collection, you can use MongoDB capped collections

I suggest you go through the multiple options that Mongoose allows, here

The Schema for your one-doc collection would be something like :

   var config = new Schema({
      siteOffline: Boolean,
      storeOffline: Boolean,
      priceMultipliers: {
        a1: Number
        a2: Number
      } 
    }, { 
      collection:'config',
      capped: { size: 1024, max: 1} 
    });

There's some irony in having a "collection" of only one document though :)

Another "hack" solution that could work better for you is to use a secured field (of which you cannot change the value), and add a unique index on that field. Read this for more info The field could be present in the document but not in the model (virtual). Again, this is hacky, but your use case is a bit strange anyway :)

like image 200
xShirase Avatar answered Oct 12 '22 23:10

xShirase


The capped approach works but it doesn't allow updating fields. There is a better solution using the immutable field property (>= mongoose v5.6).

In addition, you can add the collection option to your schema to prevent mongoose from pluralize the name of the collection

let configSchema = new Schema(
    {
        _immutable: {
            type: Boolean,
            default: true,
            required: true,
            unique : true,
            immutable: true,
        },

        siteOffline: Boolean,
        storeOffline: Boolean,
        priceMultipliers: {
            a1: Number
            a2: Number
        },
    },
    {
        collection:'config',
    }
);

var Config = mongoose.model( 'config', configSchema );
Config.updateOne( {}, { siteOffline: false });

I hope it will help

like image 36
Raphael Deiana Avatar answered Oct 12 '22 23:10

Raphael Deiana