How to join 2 collections in mongoose using nodejs - node.js

I want to join two collection using mongoose nodejs but i am stuck,
collection1
collection2
const mongoose = require('mongoose');
const gameSchema = new mongoose.Schema({
providerName:{
type: String
},
gamesSettings :[{
type: mongoose.Schema.Types.ObjectId,
ref: 'games_setting'
}]
});
module.exports = mongoose.model('gamesDetails', gameSchema);
This is the route :
router.get('/', async (req, res)=>{
try {
const gamesDetails1 = await joinCollection.find();
res.json(gamesDetails1);
//res.render('./games/gamesetting', { data: gamesDetails1 });
} catch (e) {
res.json({ message: e });
}
});
I am getting null in response.

I'm not sure that I understood your question correctly but I'm thinking that what you need is to execute a query where you get gameeSetting populated. The answer to that would be:
const details = await gamesDetails.find().populate('gamesSettings');

Related

How to use populate in mongoose?

I have two collections where one holds list of systems and the other holds list of battery attached to the system. I want to use populate method so that when I run the query using system id it shows me the details of battery is also shown.
My schema for system and battery are as follows.
const mongoose = require('mongoose');
const { Schema } = mongoose;
const SystemSchema = new Schema(
{
serialNumber: String,
location: String,
BPIDs: [
{
type: Schema.Types.ObjectId,
ref: 'batteryPack'
}
]
},
{
timestamps: true
}
);
const Systems = mongoose.model('system', SystemSchema);
module.exports = Systems;
My battery model is as follows:
const mongoose = require('mongoose');
const { Schema } = mongoose;
const batteryPackSchema = new Schema(
{
systemSerialNumber: String,
batteryID: Number,
batteryVoltage: Number,
totalCurrent: Number,
stateOfCharge: Number
{
timestamps: true
}
);
const BatteryPacks = mongoose.model('batteryPack', batteryPackSchema);
module.exports = BatteryPacks;
My query route is as follows:
router.get('/details/:id', async (req, res) => {
try {
const deviceDetails = await Systems.findOne({ _id: req.params.id }).populate('batteryPack').lean();
return res.status(200).send({
deviceDetails
});
} catch (error) {
return res.status(500).send(error.stack);
}
});
On running query through postman it shows the following error:
MongooseError: Cannot populate path batteryPack because it is not in your schema. Set the strictPopulate option to
false to override.
at getModelsMapForPopulate
I was passing wrong argument inside populate method. The code is working flawlessly now.
const deviceDetails = await Systems.findOne({ _id: req.params.id }).populate('BPIDs').lean();
const deviceDetails = await Systems.findOne({ _id: req.params.id },{},{
populate: { path: 'BPIDs' },
lean: true,
})

Getting an empty array Mongoose

I can not get data from my MongoDb collection via mongoose - I'm getting an empty array out of my request. It only happens when I'm using a route which I posted below.
Code
router.get("/options", async (req,res) => {
try {
const { animalClass} = req.body;
if (!animalClass) {
const animalClasses = await AnimalClass.find({});
console.log(animalClasses);
return res
.status(200)
.json({animalClasses})
} else {
const animalTypes = await AnimalType.find({class: animalClass});
console.log(animalTypes);
return res
.status(200)
.json({animalTypes})
}
} catch (err) {
res
.status(500)
.json({msg: err})
}
});
Schema
const mongoose = require('mongoose');
const animalClassSchema = new mongoose.Schema({
name: {type: String, required: true}
})
module.exports = AnimalClass = mongoose.model('animalClass',animalClassSchema);
Specify the collection name when creating the schema, like:
const animalClassSchema = new mongoose.Schema({
name: {type: String, required: true}
}, { collection: 'animalClass' });
By default, Mongoose pluralizes your collection name. This option allows you to override that behavior. More info in the docs:
https://mongoosejs.com/docs/guide.html#collection

Mongoose callback does not execute

I am trying to execute a callback after calling .findByIdAndDelete. Which actually does delete my item in the mongodb database, but the callback does not execute.
I've tried several solutions from other posts, but to no avail. How can I fix this?
Here's my code:
Schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const BoardSchema = new Schema({
name: String,
date: {
type: Date,
default: Date.now
}
}, { collection: 'boards' });
module.exports = Board = mongoose.model('board', BoardSchema);
Method Call
router.delete('/delete-board', (req, res) => {
console.log(req.body); // This does print out
var id = req.body.id;
Board.findByIdAndDelete(id, (err, board) => {
if (err) throw err;
console.log('stupid'); // This doesn't print out
return res.send({
message: 'Board has been deleted',
board: board
});
});
})
Check if req.body,id is valid id of any element in your database. If it isn't valid, your program won't execute callback, because it'll be not able to delete any element.

Filter collection on associated field ObjectId

SEE EDIT AT BOTTOM OF QUESTION.
I have a Node.js Express web application using MongoDB and Mongoose with collections for articles and comments. They have a one-to-many association where one article can have many comments.
The mongoose model schema is as follows:
// models/article
const mongoose = require('mongoose');
const articleSchema = new mongoose.Schema({
title: { type: String },
content: { type: String },
}, {timestamps: true});
module.exports = mongoose.model('Article', articleSchema);
and
// models/comment.js
const mongoose = require('mongoose');
const commentSchema = new mongoose.Schema({
content: { type: String },
article: { type: mongoose.Schema.Types.ObjectId, ref: 'Article' },
}, {timestamps: true});
module.exports = mongoose.model('Comment', commentSchema);
I have a route with a parameter for the article id
// routes.js
router.get('/articles/:articleId/comments', commentsController.list);
And a controller with a callback function to query the database and return the comments with the given article id. It uses the mongoose find() method filtering on the article id taken from the route parameter.
// controllers/commentsController.js
exports.list = (req, res, next) => {
Comment.find({ article: req.params.articleId })
.exec((err, comments) => {
res.render('comments/list', { title: 'Comments', comments: comments });
});
};
But this turns up no results. Just experimenting I can see that the req.params.articleId is a string and any comment.article is an object so they match with a loose comparison == but not a strict comparison === unless I convert comment.article.toString(). Anyway, what is the proper way to do such a query. All my attempts have failed.
EDIT: I found the problem. The code above is as it should be. The issue must be related to how I seeded the DB which I did directly in MongoDB. I deleted all those records and just added them from the application and it works with the code above.
One way to approach this is to add the comments to your article model.
const mongoose = require('mongoose');
const articleSchema = new mongoose.Schema({
title: { type: String },
content: { type: String },
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment'
}
]
}, {timestamps: true});
articleSchema.set('toJSON', {
transform: (document, returnedObject) => {
const article = returnedObject
article.id = article._id.toString()
delete article._id
}
})
module.exports = mongoose.model('Article', articleSchema);
Then get the comments in one of these ways:
const router = require('express').Router()
const Article = require('../models/article')
const Comment = require('../models/comment')
// article with comments
router.get('/:id', async (request, response, next) => {
try {
const article = await Article.findById(request.params.id)
.populate(
'comments', {
content: 1
}
)
response.json(article.toJSON())
} catch (err) {
console.log(err)
}
})
// list of comments belonging to an article
router.get('/:id/comments', async (request, response, next) => {
try {
const article = await Article.findById(request.params.id)
if (!article) {
response.status(404).json({ error: 'invalid request' })
}
const comments = await Comment.find({ article: request.params.id })
.populate(
'article', {
title: 1
}
)
response.json(comments.map(comment => comment.toJSON()))
} catch (err) {
console.log(err)
}
})
module.exports = router

Mongoose: find statement not executing

This router get function is entered, the log statement is printed to the console, but the find statement doesn't seem to be executing. Any obvious reasons?
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const Product = require('../models/product');
module.exports = router;
const url = "mongodb://xxxx#ds027425.mlab.com:xxxx/xxxx";
mongoose.Promise = global.Promise;
mongoose.createConnection(url, function(err) {
if(err) {
console.log('Error!!!' + err);
} else {
console.log('Connected to Database!');
}
});
router.get('/product/specialvalue', function(req, res) {
console.log('Get specialvalue called xxxx');
Product.find({'special_value': true})
.sort({'price': 1})
.exec(function(err, products) {
if(err) {
console.error('Error retrieving special value products!');
res.json(err);
} else {
console.log("products = " + JSON.stringify(products));
res.json(products);
}
});
});
This is the Mongoose Model:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ProductSchema = new Schema({
producttype: String,
name: String,
brand: String,
model: String,
price: Number,
list_price: Number,
description: String,
rating: Number,
Continuation of the model: (The system is compelling me to add more detail)
item_no: String,
special_value: Boolean,
warranty: String,
feature: [String],
image: [String],
Continuation of the model:
specification: {
lowes_exclusive : Boolean,
color : String,
high_efficiency : Boolean,
automatic_load_balancing : Boolean,
product_capacity : String,
large_items_cycle : Boolean,
Continuation of the model:
exclusive_cycle : String,
maximum_spin_speed : String,
water_levels : String,
number_of_rinse_cycles : String
}
});
Continuation of the model:
var Product = mongoose.model('Product', ProductSchema, 'product');
module.exports=Product;
Your issue is with how you are connecting the the database. mongoose.createConnection() returns a connection object to the database, but it does not set it to be mongoose's default connection. The reason why the find query is not executing is because Mongoose queues all the DB calls and waits for there to be an open connection before it processes them, instead of throwing an error when there is no connection. Using mongoose.connect() will solve your problem. You can read about it here http://mongoosejs.com/docs/api.html#index_Mongoose-connect
There are some differences when you use .createConnection instead of .connect.
Here's the refactored code that works:
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const url = "mongodb://xxxx#ds027425.mlab.com:xxxx/xxxx";
const Schema = mongoose.Schema;
mongoose.Promise = global.Promise;
const db = mongoose.createConnection(url, function(err) {
if(err) {
console.log('Error!!!' + err);
} else {
console.log('Connected to Database!');
}
});
const ProductSchema = new Schema({
producttype: String,
name: String,
brand: String,
model: String,
...
}
});
const Product = db.model('Product', ProductSchema);
router.get('/product/specialvalue', function(req, res) {
console.log('Get specialvalue called xxxx');
Product.find({'special_value': true})
.sort({'price': 1})
.exec(function(err, products) {
if(err) {
console.error('Error retrieving special value products!');
res.json(err);
} else {
console.log("products = " + JSON.stringify(products));
res.json(products);
}
});
});
Check out this post for a very good explanation on how to use .createConnection

Resources