How to fetch all data only from mongoose with Nodejs - node.js

I am not able to fetch all the data from mongoose. When I tried to fetch data it create new collection name(signins) with empty, but singin collection already exists.
I don't understand what I am doing wrong here
Index.js File
const express = require("express");
const app = express();
const mongoose = require("mongoose");
mongoose
.connect("mongodb://0.0.0.0:27017/signin")
.then(() => console.log("MongoDB Connected"))
.catch((err) => console.log(err));
const User = require("./models/signin");
app.use("/", (req, res) => {
User.find({}, (err, data) => {
if (err) throw new err();
return res.json(data);
});
});
app.listen(5500, () => console.log("Port Started on 5500"));
signin
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const loginSign = new Schema({
email: { type: String, required: true },
password: { type: String, required: true },
date: { type: Date, default: Date.now },
});
module.exports = Users = mongoose.model("signin", loginSign);

Mongoose will automatically "pluralize" the name of your collection from your model name.
So mongoose.model("signin", loginSign) is creating a collection named "signins".
From the documentation: https://mongoosejs.com/docs/models.html#compiling
The first argument is the singular name of the collection your model is for. Mongoose automatically looks for the plural, lowercased version of your model name.
Providing a third argument will use a collection name you specify, instead of the one mongoose creates. So in your case you could:
mongoose.model("signin", loginSign, "signin");
That said, having plural collection names is the standard, and encouraged.

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

How does mongoose know what collection I am accessing?

I'm having a trouble grasping a concept in Mongoose.
I'm using MongoDB atlas, got a cluster , a database and 2 collections.
users, characters.
Through a guide I've learned that a good way to write your stuff is to have a model (I use the naming schema) as a file, importing it into your Database module/class
and using it there to perform a query...
const mongoose = require("mongoose");
const process = require("./config.env");
db = () => {
return mongoose
.connect(process.env.URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: true,
})
.then((response) => {
console.log(`Connected to Databse : ${response.connection.host}`);
})
.catch((err) => {
console.log("DB_ERROR:", err);
process.exit(1);
});
};
module.exports = db;
const mongoose = require("mongoose");
const UserSchema = new mongoose.Schema({
username: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
});
const User = mongoose.model("User", UserSchema);
module.exports = User;
const User = require("../schemas/User");
const db = require("../config/db");
class Database {
constructor(db, collection) {
this.db = db;
this.collection = collection;
this.User = User;
}
connect() {
return db();
}
}
module.exports = Database;
one file to handle the db connection..another file as the User schema and a third file to handle every function i might use globally...
One thing I cannot wrap my mind around is
how is the findOne() function able to locate the collection I am using without me telling it what collection i want it to search in?
is it somehow translating the
const User = mongoose.model("User", UserSchema);
line and searching for "users" as well? I just can't understand the magic behind this...
what if I want to search specifically in the characters collection...?
Mongoose uses the model name, as passed when it was created: mongoose.model("User", UserSchema), converted to lower case and with an 's' appended.
For the model User it uses the collection users by default. You can change this by explicitly specifying the collection name in the schema.

How to create a document with the data from another collection?

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const CompanySchema = new Schema(
{
companyName: {
type: String,
required: true,
unique: true
},
taxOffice: {
type: String
},
taxNumber: {
type: String
},
},
{
timestamps: true
}
);
const Company = mongoose.model('Company', CompanySchema);
module.exports = Company;
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const DateSchema = new Schema({
name: {
type: String,
unique: true,
required: true
},
companies: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Company' }]
});
const Date = mongoose.model('Date', DateSchema, 'dates');
module.exports = Date;
const router = require('express').Router();
const Date = require('../models/date');
router.route('/').get((req, res) => {
Date.find()
.then(dates => res.json(dates))
.catch(err => res.status(400).json('Error: ' + err));
});
router.route('/add').post((req, res) => {
const name = req.body.name;
const newDate = new Date({ name });
newDate
.save()
.then(() => res.json('Date added!'))
.catch(err => res.status(400).json('Error: ' + err));
});
module.exports = router;
I have 2 collections called Company and Date.
I inserted many data to Company Collection.
But I want that Company data(companies) to copied into Date Collection whenever I create a Date document.
I want to store company data as an array for each Date.
By the way don't know that my schema design is correct for the purpose. What should I do?
I want to have a Date document like:
{
name: "DECEMBER-2019",
companies: ['5e2076236664640d22515f7b', '5e2076236664640d22515f7a']
}
It sounds like you want to take an action whenever you create a new document in the Date collection. If you are using Atlas (MongoDB's fully managed database as a service), you can configure a Trigger to fire whenever a new document is inserted into the Date collection. Another option (regardless of whether you are using Atlas or not) is to use Change Streams to monitor changes in the Date collection. For more on how to configure these, see https://www.mongodb.com/blog/post/node-js-change-streams-and-triggers.
Assuming that only companies present at the time of Date Object creation should be added in Date's companies field, Then you can maintain a cache of companies ObjectIds at any point of time which will be updated for every delete/insert in Company Collection.
You can write your own function of creating a date object which will have parameter name which add the current companies ObjectIds.
Date.statics.getNewDateObject = function(name) {
let companyIds = await getCachedCompanyIds();
return new Date({name: name, companies: companyIds});
}
This will have a document like:
{
name: "TODAY'S DATE",
companies: ['5e2076236664640d22515f7b', '5e2076236664640d22515f7a']
}
If you want to populate the Date object with complete Company Information, You can use the populate method present in mongoose which populates the complete company information into the Date Object.
https://mongoosejs.com/docs/populate.html
I solved it:
router.route('/add').post((req, res) => {
const name = req.body.name;
Company.find().then(companies => {
const newDate = new Date({ name, companies });
newDate
.save()
.then(() => res.json('Date added!'))
.catch(err => res.status(400).json('Error: ' + err));
});
});

How to connect to specific database with Mongoose and node?

I'm learning how to use Mongoose and there's something I don't understand - how can I connect to specific database and collection in my cluster?
I have 5 different databases and each database have few different collections
When I was using pure Mongo client - the way the show it in official documentation, I connected like that:
const MongoClient = require('mongodb').MongoClient;
const uri = process.env.mongo_connection_string;
const client = new MongoClient(uri, { useNewUrlParser: true });
client.connect(err => {
const collection = client.db("database_name").collection("collection_name");
// Do some work here in the selected database and the selected collection
client.close();
});
Now I want to use Mongoose to practice. So in my app.js to establish the connection I do:
mongoose.connect(process.env.mongo_connection_string , {useNewUrlParser: true})
.then( () => console.log("Connection established"))
.catch(err => console.log(err))
Then I have created a schema for one of the objects I want to store in the database.
const mongoose = require('mongoose')
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
}
})
const User = mongoose.model('User', UserSchema)
module.exports = User
How do I associate this model with the database and the collection I need?
To connect to a specific database you can add the name in the options like this:
mongoose
.connect(db_url, {
useNewUrlParser: true,
useUnifiedTopology: true,
dbName: 'MyDatabaseName',
})
.then(() => {
console.log('Connected to the Database.');
})
.catch(err => console.error(err));
Please specify the database name in URI like link (or)
Please get the default client object with mongo URI then get the required database and collection objects.

Filter moongose results by reference field using express

I need filter the products of a collection by category id which is a reference field.
product.js
const restful = require('node-restful')
const mongoose = restful.mongoose
const productSchema = new mongoose.Schema({
name: { type: String, required: true },
category: {type: mongoose.Schema.Types.ObjectId, ref: 'CategoryProduct'}
})
productSchema.pre('find', function () {
this.find().populate('category')
})
module.exports = restful.model('product', productSchema)
routes.js
const express = require('express')
const auth = require('./auth')
module.exports = function (server) {
const protectedApi = express.Router()
server.use('/api', protectedApi)
const Product = require('../api/product/productService')
Product.register(protectedApi, '/products')
}
If I run this on Postman, http://localhost:3003/api/products/?name__regex=/test/i, I can get all products which contains 'test' on name.
So I try get all products by a specific category doing this, http://localhost:3003/api/products/?category=5af3ac4372edc6000468d766.
But as the category is an objectID, I receive this error:
{
"message": "Cast to ObjectId failed for value \"5\" at path \"category\" for model \"SimpleProduct\"",
"name": "CastError",
"stringValue": "\"5\"",
"kind": "ObjectId",
"value": 5,
"path": "category"
}
How do I filter the products by category? I do not know how to treat this parameter correctly and pass to mongoose
Here is my CategoryProduct.js file
const restful = require('node-restful')
const mongoose = restful.mongoose
const categorySchema = new mongoose.Schema({
name: {type: String, required: 'O campo Categoria é obrigatório'},
status: {type: Number, required: true},
updated_at: {type: Date}
})
module.exports = restful.model('CategoryProduct', categorySchema)
you would have to do the following in your route:
const mongoose = require('mongoose');
router.get('/', (req, res, next) => {
const category = req.query.category; // assign the query param for use
// mongoose query now
Product.find({category: mongoose.Types.ObjectId(category)}, (err, result) => {
if (err) {console.log(err)};
if (result) {
res.json(result);
}
});
});
This is just a basic example. Since you are using node-restful you might have to adjust the code but the main idea here is that you require the mongoose module using
const mongoose = require('mongoose')
then pass your category query param to it to convert the string to objectID using:
mongoose.Types.ObjectID(YOUR_CATEGORY_PARAM_HERE)
You can do this anywhere, in the your routes.js or in your express.js, just have to have the string you want to convert :)
hope that helps :).

Resources