mongoose use model/scheme for multiple databases and multiple collections - mongodb

I am looking for a way to use 1 schema for multiple databases and collections. I have 3 different databases and each holds 3 to 4 collections, which use all the same schema. I started just duplicating the schema for each collection and database, but that will add up to the amount of work. then I tried to export a function that returns the schema with set parameter, but I think that creates a new connection each time I call the function and eventually I get error. I can not find how to solve my problem the right way. Please someone can help me out a little.
What I currently try to use.
import mongoose from 'mongoose';
import Config from '../components/config.js';
const {database, localDatabase} = Config();
export default function(dex, network){
const db = mongoose.createConnection(localDatabase);
const transactions = db.useDb(network); // each network gets its own database
const txSchema = new mongoose.Schema({
uniquePoint:{
type: String,
required: true,
index: true,
unique : true,
},
version:{
type: String,
required: true,
},
network:{
type: String,
required: true,
},
},{collection: dex}); // each dex gets own collection
return transactions.model('TX', txSchema);
}
But this seems to give error after a while "MongoNetworkError: connect EADDRNOTAVAIL"

Related

Cannot overwrite mongoose model once compiled with Nextjs

Before you close this question, I have read several forums that have the same question as I have but my issue is way different. Even when Im not trying to do anything, even save a model, it still gives me an error of:
cannot overwrite "mongoose" model once compiled
I have a feeling there is something wrong with my schemas because when it was still simpler, it worked fine but as I tried to make it more complex it started to give me that error. Here is my mongoose code:
import mongoose from 'mongoose'
const flashcardItemSchema = new mongoose.Schema({
term: {
type:String,
required: true,
min:1
},
description: {
type:String,
required:true,
min:1
}
});
const FlashcardItem = mongoose.model("flashcardItem", flashcardItemSchema);
const flashcardSetSchema = new mongoose.Schema({
title: {
type: String,
min: 1,
},
flashcards:[flashcardItemSchema],
})
const FlashcardSet = mongoose.model('flashcardSet', flashcardSetSchema )
export {FlashcardItem, FlashcardSet}
I connect to my database when the server runs, so it doesn't disconnect from time to time.
UPDATE
I realized that I'm using nextjs builtin api, meaning the api directory is inside the page directory. I only get the error once the pages get recompiled.
So it turns out that the error came from nextjs trying to remake the model every render. There is an answer here: Mongoose/NextJS - Model is not defined / Cannot overwrite model once compiled
but I thought the code was too long and all that fixed mine was just a single line. When trying to save a model in nextjs, it should be written like this:
const modelName = mongoose.models.modelName || mongoose.model('modelName', flashcardSetSchema )

Document not expiring in mongodb using mongoose

I am storing my refresh tokens in mongodb database. For testing purposes I want them to expire in 4 minutes. For some reason, this thing is not working for me.
const mongoose = require('mongoose');
let schema = new mongoose.Schema({
token: {
type: String,
required: true
},
username: {
type: String,
required: true
},
email: {
type: String,
required: true
},
});
schema.index({expireAt: 1}, {expiresAfterSeconds: 240}); //4 mins * 60 seconds
let model = mongoose.model('refresh_token', schema);
module.exports = model;
This is the complete code of my file. I am using this to create the refresh tokens. The item is persisting for an hour as of now. Please shed some light on my mistake.
OK, I solved the issue and it was a blunder from my side.
If you are using mongoose and doing the testing, you would most likely be changing the TTL expire time. I was changing it to see if it was working and for different testing purposes but once the document is created in the atlas, requesting a different TTL time won't overwrite the previous one. I changed the time from 30 months to 5 minutes and did a lot of fluctuation for testing purposes.
So keep this in mind that once the model is created, the TTL will be locked and you need to delete the collection and re-build it otherwise you have to change the TTL settings manually in the atlas(I didn't checked this out because my problem was solved with this only and I was in testing mode of my application). Also
thanks to wak786
for proposing to see the documentation again. It clicked when I was reading how indexing works.
My final refresh token file looks like this after I deleted the collection(actually renamed it).
const mongoose = require('mongoose');
let schema = new mongoose.Schema({
token: {
type: String,
required: true
},
username: {
type: String,
required: true
},
email: {
type: String,
required: true
},
createdAt: {
type: Date,
default: new Date()
}
});
schema.index({"createdAt": 1}, {expireAfterSeconds: 2592000}); //30days * 24hours * 60 minutes * 60 seconds
let model = mongoose.model('token', schema);
module.exports = model;
You are trying create index using following command.
schema.index({expireAt: 1}, {expiresAfterSeconds: 240});
But the field expireAt does not exist in your schema. And as per the mongo docs :-
If a document does not contain the indexed field, the document will not expire.
Reference:- https://docs.mongodb.com/manual/core/index-ttl/

Can database references in mongodb reference two databases?

I am using MongoDB via mongooose. Can database references reference two databases at the same time?
field_name: {
type: mongoose.Schema.Types.ObjectId,
ref: 'collectionA',// can I reference collectionA and collectionB too?
required: true,
},
See code above.
The field, field_name, can be an objectId from collectionA or collectionB. How can I reflect that in my mongoose schema?
I guess you are looking for mongoose dynamic reference via refPath.
const someSchema = new Schema({
field_name: {
type: Schema.Types.ObjectId,
required: true,
refPath: 'onCollection'
},
onCollection: {
type: String,
required: true,
enum: ['collectionA', 'collectionB']
}
});
In this case, Instead of a hardcoded model name in ref, refPath means Mongoose
will look at the onCollection property to find the right model.
For example if we have this document:
{
field_name: some_id,
onCollection: 'collectionA'
}
Collection.find().populate('field_name') will populate the field from collectionA. And if the onCollection field was valued with collectionB, it would have populated it from collectionB.
This scenario only works if you want to reference one collection at a time, but the collection is dynamic.
If you need to reference both collections at the same time, there is no mongoose schema design to support array of references as far as I know.
You can just ignore ref in your schema, and pass in the value of ref when you want to populate:
populate({
path: 'field_name',
model: 'collectionA'
})
Then you can have multiple populates. Same applies for $lookup.

How to handle unique indexes with mongoose?

The FAQ section of Mongoose 5 explitily says:
The unique option for schemas is convenient for development and documentation, but mongoose is not an index management solution.
This statement threw me off as I'm relatively new to Mongoose library. I'm making a basic model for User and adding a couple of tests for validation. Specifically validate no duplicate users are there.
The schema is simple
const schema = new Schema({
email: { type: String, required: true, unique: true },
...
Needless to say, my test fail:
const userA = new User({ email: 'a#a.com' });
const dupUserA = new User({ email: 'a#a.com' });
const promiseChain = userA.save().then(() => dupUserA.save());
expect(promiseChain).to.be.rejected // using chai-as-promised here
.then(err => {
// assertions about error message
});
The test fails cause the promise fulfills, meaning the save was successful.
I don't quite understand what Mongoose team means. I realize these schema are no database "migrations", but since the only example there is in the docs is some callback to the 'index' event, I'm lost.
How should I handle unique index? Is there a solution not to do them directly to the MongoDB through shell? Something that can reside in the codebase, equivalent to migrations?

How to check if old model or schema exists in mongoose mongodb

Is there any way to identify whether schema or model is old in mongoose or mongoDB.
for Ex:
I have a schema like this
const UserSchema = new Schema({
Addresfrom: {
type: Number,
unique: true
},
Addressto: {
type: Number,
unique: true
}
})
I have to drop the indexes if the schema or model is old.
Please suggest any ideas !
Thanks
did you checked mongoose-history. you may download that plugin. and either use it or study it.