1

In one nodeJS (node1) application I created a businessSchema:

import mongoose from "mongoose";
const Schema = mongoose.Schema;

const businessSchema = new Schema({
    name: {
        type: String,
        required: true
    }
},
{timestamps: true});

const Businesses = mongoose.model<BusinessModel>("Businesses", businessSchema);

export default Businesses;

In the other nodejs application (node2) I created campaignSchema that has ref to the Businesses schema:

import mongoose from "mongoose";
const Schema = mongoose.Schema;

const campaignSchema = new Schema({
    promotion: {
        type: String,
        required: true
    },
    business: {
        type: Schema.Types.ObjectId,
        required: false,
        ref: "Businesses"
    },
},
{timestamps: true});

const Campaigns = mongoose.model<CampaignModel>("Campaigns", campaignSchema);
export default Campaigns;

when I tried to fetch the campaign (from node2)

async findById(id: string) {
        const campaign = Campaigns.findOne({ _id: id })
        .populate("business")
        .exec();
        return campaign;
    }

I get this error: MissingSchemaError: Schema hasn't been registered for model "Businesses". Use mongoose.model(name, schema)

This error has not occurred when used monolith (one application) Also, this error obviously has not occurred when removing the populate()

I looked here:https://stackoverflow.com/a/47038544/3083605 which did not help because it is multiple connections from the same application and the models and schema declared in the same connection or process which is not my case

dang
  • 1,549
  • 1
  • 20
  • 25

1 Answers1

3

You need to pull your schemas out into an external dependency if you want to use them with both applications. Application 2 has no idea what a "Businesses" model is, because node.js needs to have that schema parsed as part of application 2. Application 1 is running in a different process, so they are independent of each other.

You can take your mongoose models, and any of the files that you're importing to be used by the models, and put them in a separate directory. Then you can set that directory up to be an npm module, hosted from git or bitbucket, and add it to the package.json for both applications.

djheru
  • 3,525
  • 2
  • 20
  • 20
  • Interesting. thanks for your suggestion. I ended up with custom populate (API call to the other application (await) and then combined to the client. so for the client is it transparent. I thought it is a better approach when trying to keep the MS stateless. (without the need to remember to update the model npm... – dang Apr 08 '19 at 13:53
  • Can you share with me how you did this? – Skeeith22 Mar 20 '22 at 11:56
  • @Skeeith22 I'm afraid I can't show you because it's for work, but basically just imagine that you have your schemas in a subdirectory in your node1 and node2 codebases called "models", You could take those files from both projects and move them into a single separate git repository. Then, in your node1 and node2 projects, you install the models using something like `npm i https://github.com/username/shared-models`. Or, you could package them up and install from an npm registry, like NPM or GitHub. The idea is to pull the code that's needed by more than one thing into a separate package. – djheru Mar 20 '22 at 19:28
  • I prefer using aggregation for such cases... creating a private db npm module sounds interesting, will like to try it sometimes. – Mithun Das May 23 '23 at 08:53