Mongoose is not connecting to local database - node.js

This is my app.js file. Please help me out to connect it with my local database. Sometimes it gets connected to the database and logs to the console but it doesn't add any collection to the local database.
const mongoose = require('mongoose')
main().catch(err=>console.log(err))
async function main() {
await mongoose.connect("mongodb://localhost:27017/fruitsDB", {
useNewUrlParser: true,
useUnifiedTopology: true
});
//Creating new schema
const fruitSchema = new mongoose.Schema({
name: String,
rating: Number,
review: String
});
const Fruit = mongoose.model("Fruit", fruitSchema);
const fruit = new Fruit ({
name: "Apple",
rating: 7,
review: "Pretty solid"
});
await fruit.save()
}

Insist localhost use 127.0.0.1:27017 This will work for sure.
OR
This happened probably because the MongoDB service isn't started. Follow the below steps to start it:
Go to Control Panel and click on Administrative Tools.
Double-click on Services. A new window opens up.
Search MongoDB.exe. Right-click on it and select Start
The server will start. Now execute npm start again and the code might work this time.

You can use mongo connection like this in typescript for ES6.
Schema like below
import mongoose from "mongoose"
export const RequestLogsSchema = new mongoose.Schema(
{
request_id: String,
...
},
{
collection: "request_logs"
}
)
example connection like below
import mongoose from 'mongoose'
import { RequestLogsSchema } from './mongo-schemas/RequestLogsSchema'
export class MongoClient {
mongodb: any
constructor(private host: string) { }
async MongoConnect() {
return new Promise(async (resolve, _reject): Promise<void> => {
console.log('🟡 MongoDB Connecting !')
this.mongodb = await mongoose.connect(this.host).then(() => {
console.log('🟢 MongoDB Connected !')
resolve(true)
}).catch((err) => console.log(err))
})
}
}
export const schemas = {
RequestLogsModal: mongoose.model("RequestLogs", RequestLogsSchema),
...
}
new MongoClient('mongodb://username:password#localhost:27017/db_name?authSource=db_name').MongoConnect()
To save your data like
import { schemas } from '../connections/mongo'
const saver = (data) => {
const request_logs = new schemas.RequestLogsModal({
request_id: data.request_id,
...
})
await request_logs.save()
}

Related

Why am I not able query ( User.findOne() ) my mongoDB after setting up a Schema?

I can't seem to query my MongoDB after setting up the MongoDB schema. I don't understand where I am going wrong with my MongoDB schema, any help is appreciated!
I WAS earlier successful in querying my mongodb before creating a schema, using queries like this:
const uri = process.env.MONGODB_URI;
const client = new MongoClient(uri);
const result = await client.db("inride_adverts").collection("adverts").findOne({OrgEmail: OrgEmailToSignIn});
However, according to a YouTube tutorial am following (10:40 mins), after setting up a mongodb schema, I am NOT successful in using the following query to interact with my mongodb:
User.findOne( {OrgEmail: signUpEmail} ).exec();
Find below my simple User Schema:
./models/User.js
import { mongoose} from 'mongoose';
const UserSchema = new mongoose.Schema({
OrgName: {
type: String,
required: true
},
OrgEmail: {
type: String,
required: true
},
OrgPwd: {
type: String,
required: true
}
}, { collection: 'adverts' });
export const User = mongoose.model('User', UserSchema);
Also, find below my server.js file
./server.js
import express from 'express';
import { User } from './models/User.js';
import mongodb from 'mongodb';
import { mongoose} from 'mongoose';
mongoose.connect(db, { useNewUrlParser: true })
mongoose.connect(db, { useNewUrlParser: true })
.then( () => console.log("MongoDB Connected..." ))
.catch(error => console.log(err))
app.route('/advertiserRegister')
.post( async (req, res) => {
let formData = req.body;
let signUpName = formData.signUpName;
let signUpEmail = formData.signUpEmail;
let signUpPwd = formData.signUpPwd;
console.log("signUpName: " +signUpName);
console.log("signUpEmail: " +signUpEmail);
console.log("signUpPwd: " +signUpPwd);
if(signUpPwd !== signUpPwdConfirm){
console.log("Passwords arent EQUAL!");
return 0;
} else {
try{
console.log("signUpEmail>>> : " + signUpEmail );
// Validation passed!
const testing = await User.findOne( {OrgEmail: signUpEmail} ).exec();
console.log("testing >>> : " ,testing );
res.redirect('/advertiserLogin')
} catch {
//console.error('error', code);
console.log("Error logging in ");
res.redirect('/advertiserRegister')
};
}
});
The server.js file yields:
MongoDB Connected...
signUpName: Merc Enterprise LTD
signUpEmail: hundredcent.a#gmail.com
signUpPwd: 555
signUpEmail>>> : hundredcent.a#gmail.com
testing >>> : **null**
Error logging in
Turns out that the reason I was NOT able to query my collection was due to the fact that I was unknowingly querying the incorrect collection being: adverts under the incorrect database being: inride_adverts.
I came to understand and realise that In my ./models/User.js, the mongoose.model('User', UserSchema); code creates a new database in Atlas MongoDB called test and creates a totally new collection called User.
Having understood this, I am able to populate and query this collection successfully!

Mongoose document _id is null, so when I try to save I get MongooseError: document must have and id before saving

I'm making a discord bot to scrape prices from Amazon. Im using a mongoDB database to store links users give to the bot to track the price of the item the link leads to.
My issue is when I run my code and use the add command, my console reads...
Starting...
Online! Logged in as Amazon Price Tracker#6927
Connected to Database
null
MongooseError: document must have an _id before saving
at C:\Users\logic\Documents\Disc Bot\node_modules\mongoose\lib\model.js:291:18
at processTicksAndRejections (node:internal/process/task_queues:78:11)
Disconnected from Database
I've read the doc's and my understanding is mongoose generates a unique id automatically. I am aware that you can override this my defining an id in your schema, but I haven't done this so I don't know why console.log(a) prints null, and the .save() errors out.
My add.js file
//add function using mongoose for mongodb
const { SlashCommandBuilder } = require("#discordjs/builders");
const mongoose = require("mongoose");
const { MongoDBurl } = require("../config.json");
const Link = require("../Schemas/Link.js");
module.exports = {
//Build the slash command
data: new SlashCommandBuilder()
.setName("add")
.setDescription("add a url to watch list")
.addStringOption(option =>
option.setName("url")
.setDescription("url to add to watch list")
.setRequired(true),
),
//Function that runs when the command is used
async execute (interaction) {
const URL = interaction.options.getString("url");
const user = interaction.user.username;
await interaction.reply(`On it! Adding ${URL} to your watch list`)
//Connect to the database, throws an error if it can't connect
await mongoose.connect(MongoDBurl)
.then( () => console.log("Connected to Database"))
.catch(err => console.log(err));
//Check if the link is already in the database
var exists = await Link.exists({ link: URL}).exec()
.catch(err => console.log(err))
if (exists) {
console.log("This Document Already Exists")
interaction.editReply(`Oops! That link is already in my database.`)
} else {
//If the link dosen't exist, create a document and save it to the database
var newLink = new Link({ user: user }, { link: URL }, { price: "N/A" })
// Debuging variable
var a = newLink.id;
console.log(a)
await newLink.save()
.then( () => {
console.log("Document Saved")
interaction.editReply(`All done! I have saved ${URL} to your watch list.`)
})
.catch(err => {
console.log(err)
interaction.editReply("Oops! Something went wrong, I wasen't able to save this link.")
})
}
//Close the connection when we finish
await mongoose.connection.close()
.then( () => console.log("Disconnected from Database"))
}
};
My Link.js file
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const LinkSchema = new Schema({
user: {
type: String,
requiered: true
},
link: {
type: String,
requiered: true
},
price: {
type: String,
requiered: true
},
})
module.exports = mongoose.model("Link", LinkSchema);
When creating a new modal, the options must be within the same pair of curly braces, however when updating, its separate since you are changing multiple elements.
That's why the error was occurring. You have already shared a working piece of code so I'm guessing you no longer need one.
So I found my issue. I changed this line
var newLink = new Link({ user: user }, { link: URL }, { price: "N/A" })
To
const newLink = new Link({ user: user, link: URL, price: "N/A" });
I don't know why this fixed it, I don't think its because I changed var -> const, and looking at the documentation I thought the first line was the correct way to do this
The line I originally used from the documentation
Tank.updateOne({ size: 'large' }, { name: 'T-90' }, function(err, res) {
// Updated at most one doc, `res.nModified` contains the number
// of docs that MongoDB updated
});
Is this an error in the documentation? or a possible bug? either way the issue is now resolved.

Mongoose query doesn't work with the filter

I'm testing a nodejs snippet to do iteration with my example mongodb collection users. But the query never worked. The full users collection are printed.
The standalone mongodb is setup in EKS cluster.
Why the query {name: "Baker one"} didn't work?
The code is:
const mongoose = require("mongoose");
const url = "mongodb://xxxxxx:27017/demo";
main().catch(error => console.error(error.stack));
async function main() {
// Connect to DB
const db = await mongoose.connect(url);
console.log("Database connected!");
const { Schema } = mongoose;
// Init Model
const Users = mongoose.model("Users", {}, "users");
const users = await Users.find({name: "Baker one"}).exec();
// Iterate
for await (const doc of users) {
console.log(doc);
console.log("users...");
}
console.log("about to close...");
db.disconnect();
}
The users collection:
The execution result:
$ node modify.js
Database connected!
{ _id: new ObjectId("610f512c52fa99dcd04aa743"), name: 'Baker one' }
users...
{ _id: new ObjectId("61193ed9b8af50d530576af6"), name: 'Bill S' }
users...
about to close...
This line could be the culprit (note that the schema has been defined with no fields like Joe pointed out in the comments).
const Users = mongoose.model("Users", {}, "users");
In this case, I had to add StrictQuery option in the Schema constructor to make it work, like so:
const userSchema = new Schema({}, { collection: "Users", strictQuery : false });

Mongoose - multiple database connections

I want to understand how to switch between databases within mongoose global promise connection.
My current connection is established this way app.ts
import * as mongoose from 'mongoose';
...
try {
await mongoose.createConnection(`mongodb://localhost:27017/db1`, {
useNewUrlParser: true,
})
console.log("Connected")
} catch (error) {
console.log(error)
}
And then I am accessing it in different files some.model.ts
import { Schema, Document, model } from 'mongoose';
const SomeSchema: Schema = new Schema({
name: { type: String, required: true },
owner: { type: string, required: true }
});
export default model('Some', SomeSchema);
According to documentation.
So far we've seen how to connect to MongoDB using Mongoose's default connection. At times we may need multiple connections open to Mongo, each with different read/write settings, or maybe just to different databases for example. In these cases we can utilize mongoose.createConnection() which accepts all the arguments already discussed and returns a fresh connection for you.
const conn = mongoose.createConnection('mongodb://[username:password#]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]', options);
I can create multiple database connections like this
try {
const db1 = await mongoose.createConnection(`mongodb://localhost:27017/db1`, {
useNewUrlParser: true,
})
const db2 = await mongoose.createConnection(`mongodb://localhost:27017/db2`, {
useNewUrlParser: true,
})
console.log("Connected")
} catch (error) {
console.log(error)
}
I can see both connection in console.log(mongoose.connections)
But how can I specify what database should be used for the Model in some.model.ts?
import { Schema, Document, model } from 'mongoose';
const SomeSchema: Schema = new Schema({
name: { type: String, required: true },
owner: { type: string, required: true }
});
export default SPECIFY_DATABASE.model('Some', SomeSchema);
I have found other questions like this but there are connections created "localy", I need to use mongoose connection across many different files.
Thank you for answers, if you need more explanation please let me now.
You need to actually return the connection, and then register a given model to each of the connections. To clarify, you need:
something to create a (named, specific) connection
schemas
you create models by registering schemas to the given connections,
you also need something to orchestrate it.
Example, lets have a "db.js" file (I call mine "repo.js" usually) with a single export, a function that returns the initialized database Promise.
You'd use it by importing the function and awaiting for the db.
I have a bit of a longer example, so error handling etc is ommited for brevity.
import { createConnections } from './create-connections';
import { UsersSchema } from './users-schema';
import { PostsSchema } from './posts-schema';
let db: any;
export function getDatabase(): Promise<any> {
if (this.db) return Promise.resolve(db);
return createDatabases();
}
async function createDatabases() {
const { db1, db2 } = await createConnections('mongodb://localhost/db1', 'mongodb://localhost/db2');
const UserModel = db1.model('users', UserSchema);
const PostModel = db2.model('posts', PostSchema);
db = {
UserModel,
PostModel,
// also if you need this
connections: {
db1,
db2,
}
}
return db;
}
Now, I've used './create-connections' here, which is almost what you have:
// create-connection.js
const { createConnection } = require('mongoose');
// You create connections by calling this function and giving it the URL to the server
export function createConnections(url1, url2) {
const db1 = await createConnection(url1);
const db2 = await createConnection(url2);
return {
db1,
db2
}
}
Now, let's say you have two models: users and posts, let's have their schemas.
// users schema
import { Schema, Document } from 'mongoose';
export const UserSchema: Schema = new Schema({
name: { type: String, required: true },
});
// posts schema
import { Schema, Document } from 'mongoose';
export const PostSchema: Schema = new Schema({
text: { type: String, required: true },
owner: { type: SchemaID, required: true }
});
So now you need to bind it all in that fdirst file.
But how to use it? As I've said, since it's async, you always import it and use it as a simple async getDB:
// some controller, route handler, service etc.
import { getDatabase } from './get-database';
router.get('/users', async (req, res) => {
const User = await getDatabase().UserModel;
const users = await User.find();
return res.json(users);
});
router.post('/posts', async (req, res) {
const { text } = req.body;
const owner = req.user.id;
const Post = await getDatabase().PostModel;
const post = await Post.create({ text, owner });
return res.json(post);
});

Mongoose: handling multiple databases when working with one model

What I want is to have arbitrary databases (50 for example) with the same collections (same schemas, exact models, different data) and 1 nodejs (expressjs + mongoose) web app.
Example simplified case:
I have:
a single web application (expressjs + mongoose) with User model.
50 domains 50 databases with users collection.
What behaviour I want to achieve:
GET /api/users/ http request is coming to one of domains (test-domain-39.myapp.com)
app gets the requested domain name (test-domain-39) and somehow mongoose understands that it wants to query database-39 when I just do User.find({isActive: true}) in users.controller
So I just want an abstraction. I pass db name to mongoose and continue to work with the User model (as we all usually do when having single DB connection) and mongoose, if needed, creates connection (if it's the first request to the specific db), keeps it alive for next requests in connection pool and etc.
What's the most simple and efficient way to accomplish that?
Thank's in advance!
IMHO, while this is possible with MongoDB, I wouldn't advise maintaining a separate database for each domain, especially if you are expecting to have a huge number of them. Have you considered a multi-tenant model instead?
The sample code below adds user 'Alex' into two different databases, "domainOne" and "domainTwo". Hope this helps
var mongoose = require('mongoose');
var personSchema = { name: String, domain : String };
var baseUri = 'mongodb://localhost/';
domains.forEach((domain) => {
var conn = mongoose.createConnection(baseUri + domain, (error) => {
if(error){
console.log('Ups! Database connection failed!');
return;
}
//Use the connection object to create your models,
//instead the mongoose object
//so that our data is saved into the database
//associated with this connection
var Person = conn.model('Person', personSchema);
//Lets add user 'Alex' into the database
(new Person({name : 'Alex', domain : domain })).save((error) => {
if(error){
console.log('Ups! Could not save person');
} else {
conn.close();
}
});
});
});
This is how I implemented my project:
// config/db.ts
import {createConnection} from 'mongoose'
const MONGO_URI = process.env.MONGO_URI
if (!MONGO_URI)
throw new Error(
'Please define the MONGO_URI environment variable inside .env'
)
const connections: any = {}
async function db(dbName: string) {
if (connections[dbName]) {
return connections[dbName]
} else {
connections[dbName] = createConnection(`${MONGO_URI}/${dbName}`)
return connections[dbName]
}
}
export default db
// models/Test.ts
import { Schema } from 'mongoose'
export interface ITest {
_id: Schema.Types.ObjectId
name: string
createdAt?: Date
}
const testSchema = new Schema<ITest>(
{
name: { type: String, required: true },
},
{ timestamps: true }
)
export default testSchema
// pages/api/test.ts
import nc from 'next-connect'
import db from '../../config/db'
import testSchema from '../../models/Test'
const handler = nc()
handler.get(
async (req: NextApiRequestExtended, res: NextApiResponseExtended) => {
try {
const conn = await db(req.headers['x-db-key'])
const model = await conn.model('Test', testSchema)
const data = await model.find({})
res.send(data)
} catch (error: any) {
res.status(500).json({ error: error.message })
}
}
)
export default handler

Resources