I am trying to create a multitenant DB with node js and MongoDB, and it works fine, I can create a new database with a tag, for example: main database store, tenant: store_fool, and each tenant has their tables (collections).
So, what’s the problem?
I had this model:
const BoardSchema = new Schema<Board, Model<Board>>({
name: {
type: String,
required: true
},
cards: [{
type: SchemaTypes.ObjectId,
ref: 'cards'
}],
color: {
type: String,
default: '#55AC79'
}
})
const BoardModel = async (id: string) => {
try {
const db = await getTenantDb(id);
return db!.model('boards', BoardSchema);
} catch (error) {
console.log(error);
throw error;
}
}
And this is my card model:
const CardSchema = new Schema<Card, Model<Card>>({
name: {
type: String,
required: true
},
description: {
type: String,
required: true
}
})
const CardModel = async (id: string) => {
try {
const db = await getTenantDb(id);
return db!.model('cards', CardSchema)
} catch (error) {
console.log(error);
throw error;
}
}
I tried to get the info on boards with these lines:
const Board = await BoardModel(x_tenant as string);
const data = await Board.find();
And it works fine, if I show the collection on my MongoDB Compass GUI, it sends me the correct collections.
The problem is when I tried to populate cards
const Board = await BoardModel(x_tenant as string);
const data = await Board.find().populate('cards'); //it causes error
I got the following error:
MissingSchemaError: Schema hasn't been registered for model "cards".
But in MongoDB Compass GUI the collection exists, if I don’t populate the prop, it works.
Note
Theid
of cards inboards
collection exists oncards
collection
2
Answers
I think you have to use in your populate statement card as single as by default mongo uses a single name for the model and a plural name for the table
I’m not familiar with some of your syntax for creating your models but the
MissingSchemaError: Schema hasn't been registered for model "cards".
is thrown by mongoose when it can’t find the particular model to use when doing the populate on the field you specified. However, implementing these changes should resolve your issues.The correct format for referencing your
cards
array would be:When you create the Models use the single, title-cased version of your collection names. So this:
With these changes in place it is often the case, depending on your project, that you need to explicitly pass the model name like this:
See mongoose populate and Populate with TypeScript for further reading.