Beginner Issue with Mongoose and MongoDB - node.js

I'm new to Node, along with Mongoose and MongoDB. I'm trying to test inserting data into one of the collections in a database on MongoDB Atlas. However, the code somehow inserts the data into the wrong database. I intend to insert data into the 'test' collection in the 'quizzard' database. However, a new collection called 'tests' was created within quizzard where the data was placed. When I tried it again, it started inserting data into another database called 'test' and created a collection called 'tests', where the data is still being placed.
var link = "mongodb+srv://<user>:<password>#quizzard-dp0b2.mongodb.net/test?retryWrites=true&w=majority";
// changed to <user> and <password> for privacy reasons
mongoose.connect(link, {
useNewUrlParser: true,
useUnifiedTopology: true
});
mongoose.connection.on('connected', () => {
console.log('Connected');
});
const Schema = mongoose.Schema;
const TestSchema = new Schema({
_id: Number,
data: String
});
//TestSchema.set('database', 'test');
//TestSchema.set('collection', 'test');
const Test = mongoose.model('Test', TestSchema);
const data = {
_id: 11,
data: "why???"
};
const newTest = new Test(data);
newTest.save((error) => {
if(error){
console.log("An error has occured");
} else {
console.log("Action performed");
}
});

You need to change the link; after the first slash, you choose which DB you want to use.
Examples
// DB NAME youinsertinheredbname
var link = "mongodb+srv://<user>:<password>#quizzard-dp0b2.mongodb.net/youinsertinheredbname?retryWrites=true&w=majority";
// DB NAME stackoverflow
var link = "mongodb+srv://<user>:<password>#quizzard-dp0b2.mongodb.net/stackoverflow?retryWrites=true&w=majority";

Related

Nodejs: not getting any data while fetching data from MongoDB?

I am trying to fetch data from MongoDB by a field name - pubdate, but data is not showing neither I am getting any error!
I have field in the collection - _id, article, headline, pubdate all are String type except _id which is Objectid.
When I tried this query in Mongo query browser like - compass and studio 3t I got data -
{ pubdate: { '$gte': '2022-12-01', '$lte': '2022-12-31' } }
I am using postman to fetch data, in raw option sending POST request in JSON form.
{"fdate":"2022-12-31","tdate":"2022-12-31"}
const express = require("express");
const app = express();
const port = 3005;
const mongoose = require("mongoose");
// Connect to MongoDB using Mongoose
const url =
"mongodb://localhost:2701/db";
mongoose.connect(url, { useUnifiedTopology: true, useNewUrlParser: true });
const db = mongoose.connection;
db.on("error", console.error.bind(console, "MongoDB connection error:"));
// Define the Article schema
const articleSchema = new mongoose.Schema({
headline: String,
fulltext: String,
pubdate: String,
article_type: String,
});
const Article = mongoose.model("collectioname", articleSchema);
// Route for retrieving articles based on fromdate and todate
app.post("/articles2", (req, res) => {
let _fDate = req.body.fdate;
let _tDate = req.body.tdate;
Article.find({
pubdate: { $gte: _fDate, $lte: _tDate },
}).exec((err, articles) => {
if (err) {
console.error(err);
res.status(500).send("Error retrieving articles");
return;
}
res.send(articles);
});
});
// Start the server
app.listen(port, () => {
console.log(`Server listening at http://localhost:${port}`);
});
How Will I pass the value in Postman to get the record, I am clueless as of now?
I tried map function too but no output-
let _articles = articles.map((x) => x.articleid); res.send(_articles);
Your issue is caused by Mongoose, by default, lowercasing and pluralizing the name that you pass when creating the model to determine the name of the collection it will use for the model.
In other words, when you use mongoose.model('User', UserSchema), Mongoose will take the name (User) and lowercase and pluralize it, so the collection becomes users.
If you want Mongoose to use an existing collection, or if you want to have full control of the collection name, you need to use the collection option in your schema:
const articleSchema = new mongoose.Schema({
headline: String,
fulltext: String,
pubdate: String,
article_type: String,
}, {
collection : 'article_fulltext' // the collection to use for this schema
});
const Article = mongoose.model("Article", articleSchema);
Without this option, and assume that you used article_fulltext as the model name, Mongoose would have used a collection named article_fulltexts.
Can you try logging what articles return in exec callback?
One possible issue could be that variables _fDate and _tDate are not seen as Dates by mongoose.So try wrapping them with new Date?
Article.find({
pubdate: { $gte: new Date(_fDate), $lte: new Date(_tDate) },
})

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 });

Create multiple database in node.js [duplicate]

I'm doing a Node.js project that contains sub projects. One sub project will have one Mongodb database and Mongoose will be use for wrapping and querying db. But the problem is
Mongoose doesn't allow to use multiple databases in single mongoose instance as the models are build on one connection.
To use multiple mongoose instances, Node.js doesn't allow multiple module instances as it has caching system in require(). I know disable module caching in Node.js but I think it is not the good solution as it is only need for mongoose.
I've tried to use createConnection() and openSet() in mongoose, but it was not the solution.
I've tried to deep copy the mongoose instance (http://blog.imaginea.com/deep-copy-in-javascript/) to pass new mongoose instances to the sub project, but it throwing RangeError: Maximum call stack size exceeded.
I want to know is there anyways to use multiple database with mongoose or any workaround for this problem? Because I think mongoose is quite easy and fast. Or any other modules as recommendations?
According to the fine manual, createConnection() can be used to connect to multiple databases.
However, you need to create separate models for each connection/database:
var conn = mongoose.createConnection('mongodb://localhost/testA');
var conn2 = mongoose.createConnection('mongodb://localhost/testB');
// stored in 'testA' database
var ModelA = conn.model('Model', new mongoose.Schema({
title : { type : String, default : 'model in testA database' }
}));
// stored in 'testB' database
var ModelB = conn2.model('Model', new mongoose.Schema({
title : { type : String, default : 'model in testB database' }
}));
I'm pretty sure that you can share the schema between them, but you have to check to make sure.
Pretty late but this might help someone. The current answers assumes you are using the same file for your connections and models.
In real life, there is a high chance that you are splitting your models into different files. You can use something like this in your main file:
mongoose.connect('mongodb://localhost/default');
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', () => {
console.log('connected');
});
which is just how it is described in the docs. And then in your model files, do something like the following:
import mongoose, { Schema } from 'mongoose';
const userInfoSchema = new Schema({
createdAt: {
type: Date,
required: true,
default: new Date(),
},
// ...other fields
});
const myDB = mongoose.connection.useDb('myDB');
const UserInfo = myDB.model('userInfo', userInfoSchema);
export default UserInfo;
Where myDB is your database name.
One thing you can do is, you might have subfolders for each projects. So, install mongoose in that subfolders and require() mongoose from own folders in each sub applications. Not from the project root or from global. So one sub project, one mongoose installation and one mongoose instance.
-app_root/
--foo_app/
---db_access.js
---foo_db_connect.js
---node_modules/
----mongoose/
--bar_app/
---db_access.js
---bar_db_connect.js
---node_modules/
----mongoose/
In foo_db_connect.js
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/foo_db');
module.exports = exports = mongoose;
In bar_db_connect.js
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/bar_db');
module.exports = exports = mongoose;
In db_access.js files
var mongoose = require("./foo_db_connect.js"); // bar_db_connect.js for bar app
Now, you can access multiple databases with mongoose.
As an alternative approach, Mongoose does export a constructor for a new instance on the default instance. So something like this is possible.
var Mongoose = require('mongoose').Mongoose;
var instance1 = new Mongoose();
instance1.connect('foo');
var instance2 = new Mongoose();
instance2.connect('bar');
This is very useful when working with separate data sources, and also when you want to have a separate database context for each user or request. You will need to be careful, as it is possible to create a LOT of connections when doing this. Make sure to call disconnect() when instances are not needed, and also to limit the pool size created by each instance.
Mongoose and multiple database in single node.js project
use useDb to solve this issue
example
//product databse
const myDB = mongoose.connection.useDb('product');
module.exports = myDB.model("Snack", snackSchema);
//user databse
const myDB = mongoose.connection.useDb('user');
module.exports = myDB.model("User", userSchema);
A bit optimized(for me atleast) solution. write this to a file db.js and require this to wherever required and call it with a function call and you are good to go.
const MongoClient = require('mongodb').MongoClient;
async function getConnections(url,db){
return new Promise((resolve,reject)=>{
MongoClient.connect(url, { useUnifiedTopology: true },function(err, client) {
if(err) { console.error(err)
resolve(false);
}
else{
resolve(client.db(db));
}
})
});
}
module.exports = async function(){
let dbs = [];
dbs['db1'] = await getConnections('mongodb://localhost:27017/','db1');
dbs['db2'] = await getConnections('mongodb://localhost:27017/','db2');
return dbs;
};
I have been using this method and it works great for me until now.
const mongoose = require('mongoose');
function makeNewConnection(uri) {
const db = mongoose.createConnection(uri, {
useNewUrlParser: true,
useUnifiedTopology: true
});
db.on('error', function (error) {
console.log(`MongoDB :: connection ${this.name} ${JSON.stringify(error)}`);
db.close().catch(() => console.log(`MongoDB :: failed to close connection ${this.name}`));
});
db.on('connected', function () {
mongoose.set('debug', function (col, method, query, doc) {
console.log(`MongoDB :: ${this.conn.name} ${col}.${method}(${JSON.stringify(query)},${JSON.stringify(doc)})`);
});
console.log(`MongoDB :: connected ${this.name}`);
});
db.on('disconnected', function () {
console.log(`MongoDB :: disconnected ${this.name}`);
});
return db;
}
// Use
const db1 = makeNewConnection(MONGO_URI_DB1);
const db2 = makeNewConnection(MONGO_URI_DB2);
module.exports = {
db1,
db2
}

Mongoose findById is returning null

So I have this schema:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var TreeSchema = new Schema({
}, { collection: 'treeLocations' });
var TreeDetailsSchema = new Schema({
}, { collection: 'treeInfo' });
module.exports = mongoose.model('Tree', TreeSchema);
module.exports = mongoose.model('TreeDetail', TreeDetailsSchema, "treeInfo");
And I am calling by ID like this:
var TreeDetails = require('./app/models/tree').model('TreeDetail');
router.route('/api/trees/:tree_id')
.get(function(req, res) {
TreeDetails.findById(req.params.tree_id, function(err, treedetail) {
if (err)
res.send(err);
res.json(treedetail);
});
});
For some reason - http://localhost:3000/api/trees/5498517ab68ca1ede0612d0a which is a real tree, is returning null
Something that might help you help me:
I was following this tutorial: https://scotch.io/tutorials/build-a-restful-api-using-node-and-express-4
The only thing I can think of that changed is that I have a collection name. Might that be it?
The step that I don't see is how you actually connect to MongoDB and after that, how you get the Model from the connection.
// connect to MongoDB
var db = mongoose.createConnection('mongodb://user:pass#host:port/database');
// now obtain the model through db, which is the MongoDB connection
TreeDetails = db.model('TreeDetails');
This last step is how you associate your model with the connected mongo database.
More info on Mongoose.model
There are several ways to establish a connection to MongoDB with mongoose, the tutorial uses:
mongoose.connect('mongodb://node:node#novus.modulusmongo.net:27017/Iganiq8o');
(Personally I prefer the more explicit mongoose.createConnection as shown in the example)
(I used mongoose 4.3.1 for this example)
My steps to reproduce, in order to provide a working example (without creating a webservice for it):
var mongoose = require('mongoose'),
TreeDetails, db;
// create the model schema
mongoose.model('TreeDetails', mongoose.Schema({
// .. your field definitions
}, {collection: 'treeInfo'}));
db = mongoose.createConnection('mongodb://user:pass#host/example');
TreeDetails = db.model('TreeDetails');
TreeDetails.findById('5671ac9217fb1730bb69e8bd', function(error, document) {
if (error) {
throw new Error(error);
}
console.log(document);
});
Instead of:
var TreeDetails = require('./app/models/tree').model('TreeDetail');
try:
var mongoose = require('mongoose'),
TreeDetails = mongoose.model('TreeDetail');
Defining the collection name shouldn't give you any issues. It's just what the collection will be called in the database / when using the mongo shell.
And just to be sure, try logging req.params.tree_id before calling findById to make sure it's coming through as you suspect.

mongodb + mongoose: query not entering .find function

I am getting start with mongodb and mongoose but am having problems querying a database. There are a number of tutorials online for what I am trying to do but it just doesn't seem to work for me. My problem is that the .find() function is not even being called and the collection is not being displayed. I have a collection called Subjects in which I know there are some values (I manually entered them in the mongodb command line). I only tried including pertinent code but let me know if anything else is needed. Thanks in advance.
app.js file
require('./models/model.js');
var conn = mongoose.createConnection('mongodb://localhost/test');
var Subject = mongoose.model('Subjects');
Subject.find( { }, function (err, subjects) {
if(err) console.log("Error"); // There is no "Error"
console.log("Made it"); // There is no "Made it"
console.log(subjects);
});
model.js file
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var SubjectsSchema = new Schema ({
subject: { type: String }
});
module.exports = mongoose.model('Subjects', SubjectsSchema);
Call mongoose.connect instead of mongoose.createConnnection to open the default connection pool that will be used by models created using mongoose.model:
mongoose.connect('mongodb://localhost/test');

Resources