Error adding on post a doc to a database. My app is connected to 2 DB. Help!

Hi guys, I created a small project to learn. I created a connection to 2 DB, and I have 2 schemas with the same name. I can add multiples docs on the first DB but only one on the second because I got the error

MongoServerError: E11000 duplicate key error collection: DB1.questions index: themes_1 dup key: { themes: null }

I created 2 Schemas, 1 per DB and they are different

Schema 1

const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const conn = require('../../config/mongooseSetup');

const questionShema = new Schema({
  question: { type: String, required: true, unique: true },
  lang: { type: String, default: "en" }
});

module.exports = conn.DB1.model("question", questionShema);

Schema 2

const questionShema = new Schema({
  question: { type: String, required: true },
  lang: { type: String, default: "en" },
  themes: [
    { type: Schema.Types.ObjectId, ref: "theme", required: true },
  ]
});

module.exports = conn.DB2.model("question", questionShema);

Is this possible in MongoDB?, if I use a different schema name on DB2 works like a charm

I do not think this is a MongoDB issue.

Most likely it is a mongoose limitation or bug since:

and MongoDB is not aware of your new Schema.

Yes the issue manifest as a MongoServerError on DB1.questions with a duplicate key (value null) on the index themes_1.

But your mongoose schema for DB1 has no mention of the themes. This may also point to an error from your part. You define the unique index themes_1 on DB1 and you forgot to add it to your mongoose schema.

However

seems to indicate that you try to insert documents in DB2 but the error is on DB1. This looks like mongoose tries to insert your DB2 question model into the Mongo’s DB1 database but collection questions. I do not know moogoose, because I am avoiding abstraction layers, so I wonder how the question in mongoose becomes questions with an s in MongoDB. I would hate mongoose even more if it mangles the schema name into the collection name by adding an s.

What worry me is that the inconsistency you between your DB1.model where you do not mentioned the field themes yet you have a unique index themes_1 on DB1.questions.

I think that the only reason why it works when you change the DB2 schema name it is because you do not have the unique index themes_1 on the DB1 collection with the other name.

If you insert with conn.DB2 and you got an error on DB1 then you did not initialized conn.DB2 correctly.

If you insert with conn.DB1 and you get a unique index error on themes_1, the it means you defined the unique index on the wrong collection because conn.DB1 model has no field themes.

I would be surprised if mongoose let you insert on conn.DB2 without themes or with themes:null since it is marked as required.

In your schema code, you shared the require(“mongoose”) part for conn.DB1 but not for conn.DB2. Are both module.exports = … in the same file? Or you simply did not shared the require lines for conn.DB2?

Yes both are on the same file

I tried removing also the unique: true attribute and I also got an error.

I made a mistake in my explanation. The first test I did was with Shema 1 (this is the one that includes Theme) and everything worked perfectly. Then I added a Shema 2 for the DB 2 without Themes.

My problem is, inserting documents in DB 2 using Shema 2 (the one without Themes)

// CONNECT TO DATABASES (mongooseSetup.js file)
mongoose.DB1= mongoose.createConnection(mongoDb1, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
}, (err) => {
  if (err) {
    console.log('Error DB1!!!', err);
  } else {
    console.log('Connection succefull to DB1!!!');
  }
});

mongoose.DB2 = mongoose.createConnection(mongoDb2, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
}, (err) => {
  if (err) {
    console.log('Connection error', err);
  } else {
    console.log('Connection succefull to DB2!!!');
  }
});

module.exports = mongoose;

Shema for DB1

const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const conn = require('../config/mongooseSetup');

const questionShema = new Schema({
  question: { type: String, required: true },
  lang: { type: String, default: "en" },
  themes: [
    { type: Schema.Types.ObjectId, ref: "theme", required: true },
  ]
});

module.exports = conn.DB1.model("question", questionShema);

Shema for DB2

const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const conn = require('../../config/mongooseSetup');

const questionShema = new Schema({
  question: { type: String, required: true, unique: true },
  lang: { type: String, default: "en" }
});

module.exports = conn.DB2.model("question", questionShema);

So I can continue inserting questions using Shema 1, that’s is fine, but I can only insert 1 doc on Db2 using Shema 2, on the second attempt I got the error :frowning:

Removing unique:true on the mongoose model does not remove the unique index themes_1 in the MongoDB collection.

We are still missing some code.

How do you initialize mongoDb1 and mongoDb2?

Just to make sure I understand correctly.

  1. conn.DB1 is initialized with mongoDb1
  2. conn.DB2 is initialized with mongoDb2
  3. conn.DB1 has a themes field
  4. you can insert as much as you wish with conn.DB1
  5. you can insert only one document with conn.DB2 and the error message is **duplicate key error on the collection DB1.questions on the index themes_1
  6. when you change “question” for something else you can now insert with conn.DB2 many documents without the duplicate key error

Point 5 and point 6 are strong indication that mongoDb1 and mongoDb2 are NOT initialized correctly because inserting with mongoose’s conn.DB2 results to an insert in mongo’s DB1.

When you change question to something else for DB2, it works because it is not inserting in DB1.questions which has the unique index, but it inserts into another DB1 collection that does not have a unique index. That is what I meant by:

Using mongosh, please share the output of the commands:

use DB1
db.getCollectionNames()
db.questions.getIndexes()
use DB2
db.getCollectionNames()
db.questions.getIndexes()

But I think the issue is

Can you really have multiple module.exports in the same file? Yes but only the last one is really exported.

bash> cat Test.js
module.exports = "foo"
module.exports = "bar"
bash> node
node> test = require( "./Test" )
'bar'
node> test
'bar'

The answer is then that you can but only the last one is really exported.

Please share your insert code?

I also have an answer to

This is what it does when you do not explicitly specify a collection name.

This comment solved my problem, thank you very much. What happened was that I had created the Schema some time ago, and I had added documents to it and then I continued adding attributes to the schema, as is the case of “unique: true”. I thought that when I compiled the application everything was re-built, but it was not. I deleted the table Questions on both DB and voila, now I can send data without problems :smiling_face_with_three_hearts:.

2 Likes

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.