Search code examples
javascriptnode.jsexpressmongoosemongoose-schema

How to mongoose model based on dynamic schema passed as parameter?


I am new on mongoose and for expressjs

I want to retrieve a collection based on the doc and model. I have multiple schema that inherits a common schema.

const extendSchema = (schema: mongoose.Schema<any>, definition: any): Schema<any> => {
  return new mongoose.Schema({ ...schema.obj, ...definition, ...{ strict: false }});
};

const CommonSchema = new mongoose.Schema({ ... });

const OtherSchema = extendSchema(CommonSchema, { ... });

const OtherOtherSchema = extendSchema(CommonSchema, { ... });

Then, I want to retrieve the collection from the mongoose

const getCollectionObject = (collection: string, schema: Schema) => {
  return collection.model(collection, schema);
};


// get the first collection
export const getOtherCollection = async (name: string, id: string) => {
  try {
    const model = getCollectionObject(name, OtherSchema);
    const document = await model.findById(mongoose.Types.ObjectId(id)).lean();
    return document;
  } catch (error) {
    return error;
  }
};


// get the second collection
export const getOtherOtherCollection = async (name: string, id: string) => {
  try {
    const model = getCollectionObject(name, OtherOtherSchema);
    const document = await model.findById(mongoose.Types.ObjectId(id)).lean();
    return document;
  } catch (error) {
    return error;
  }
};

I've got an error below enter image description here

Is it possible? Thank you in advance!

PS: I've already saw other posts which the solution is to make the properties optional.


Solution

  • This solved my issue.

    Create a common schema plus the other schema

    const CommonSchema = new mongoose.Schema({ ... });
    const OtherSchema = { ... };
    const OtherOtherSchema = { ... };
    
    

    Then, I declared my based model.

    const Base = mongoose.model('collection-name', CommonSchema);
    

    Next, I created my other models based on the base model using discriminator

    const OtherModel = Base.discriminator("Other", new mongoose.Schema(OtherSchema));
    const OtherOtherModel = Base.discriminator("OtherOther", new mongoose.Schema(OtherOtherSchema));
    

    You can now use the model on any scoped function, you may export it if you want to.

    Other.create({ ... });
    Other.findById()
    
    OtherOther.create();
    OtherOther.findById();
    

    please let me know if this right approach or you have any other suggestions

    Thanks!