mongodb error no documents found - node.js

Here is my code to find winners of a contest :
var date = moment().subtract('days', 1).format("YYYY-MM-DD");
console.log(date)
Contest.findOne({date: date}, function(err, contest){
if(!err){
if(contest){
Participant.find({ questionID : contest._id, random : { $near : [Math.random(), 0] } }).limit(5).exec(function(err, participants){
async.map(participants, function(participant, callback) {
contest.winners.push(participant)
contest.save(function(err) {
callback(err);
})
}, function(err) {
if (!err) {
console.log("Added winners to contest")
} else
console.log(err)
});
});
}
else{
console.log("No contest found")
}
}
else{
console.log(err)
}
})
Schema :
var ContestSchema = new Schema(
{
question:{
type: String,
trim: true
},
answers:[{
option: {type: String},
correct: {type: Boolean, default : false}
}],
date: {
type: String,
trim: true
},
priority: {
type: Number,
trim: true,
default : 0
},
winners : [{
type: Schema.Types.ObjectId,
ref: 'Participant'
}]
})
/*
*Participant Schema
*/
var ParticipantSchema = new Schema(
{
questionID:{
type: String,
trim: true
},
userID:{
type: String,
trim: true
},
name:{
type: String,
trim: true
},
email:{
type: String,
trim: true
},
mobile:{
type: String,
trim: true
},
address:{
type: String,
trim: true
},
landmark:{
type: String,
trim: true
},
city:{
type: String,
trim: true
},
state:{
type: String,
trim: true
},
random:{
type: [Number],
default : [Math.random(), 0],
index: '2d'
}
})
mongoose.model('Contest', ContestSchema)
mongoose.model('Participant', ParticipantSchema)
While saving winners to the contest, it saves the winners, but I am getting error :
{
"status": {
"error": 1,
"message": {
"message": "No matching document found.",
"name": "VersionError"
}
}
}
What is this error and how can I solve this ?

I would try rewriting the async.map operation. This would result in a single call to contest.save and you don't have to fear any race conditions.
async.map(participants, function(participant, callback) {
contest.winners.push(participant)
callback();
}, function(err) {
contest.save(function(err) {
if (!err) {
console.log("Added winners to contest")
} else {
console.log(err)
}
});
});

Related

Find one and Update mongoose in Node js

I have following code for a chat application based on socket io.
const query={ chatID: chatId }
const update= {
$push: {
messages:{
message: message,
sendBy: sendById,
sendTo: sendTo
}
}
}
const options={upsert: true, new:true}
Chat.findOneAndUpdate(query, update, options, function(error, result) {
if (error){
console.log("error: "+error.message);
return;
}
io.emit("message", result.messages)
}).clone();
now if the chat id doesn't exists it creates new with query and update. But i want it like,
if the query doesnt exist, i have some more params to add to the document. How can i achieve that.
if i add the whole params in query , it wont find the document.
the foloowing is my schema
const ChatSchema = mongoose.Schema({
chatID: { type: String, required: true, unique: true },
participants: [
{ senderId: { type: mongoose.Types.ObjectId, unique: true, required: true } },
{ receiverId: { type: mongoose.Types.ObjectId, unique: true, required: true } }
],
messages: [
{
message: { type: String, required: true },
sendBy: { type: String, required: true },
sendTo: { type: String, required: true },
seen: { type: Boolean, default: false },
date: { type: Date, default: Date.now() }
},
],
})

How to correctly save references to mongodb from request

I want to save data and references of child document into parent document from request, I have managed to achieve that, but I am not sure is this correct way of doing it.
I have found in stackoverflow that first we have to save child document. so we can save references of child document into parent document
This is my structure of request
"category": "movie",
"overview": "This is overview",
"poster_path": "https://image.tmdb.org/t/p/w500/aWeKITRFbbwY8txG5uCj4rMCfSP.jpg",
"release_date": "2021-12-01",
"title": "Sing 2",
"vote_average": 8.2,
"cast": [
{
"name": "Matthew McConaughey",
"profile_path": "wJiGedOCZhwMx9DezY8uwbNxmAY.jpg"
},
{
"name": "Reese Witherspoon",
"profile_path": "6Pp3BrY2JbJg77Po8NOBO6zOA8m.jpg"
}
]}
//Show Schema
const showSchema = new Schema({
title: {
type: String,
unique: true,
required: [true, 'Title can not be empty.'],
trim: true,
text: true
},
slug: String,
poster_path: {
type: String,
required: [true, 'Cover can not be empty.'],
trim: true
},
overview: {
type: String,
required: [true, 'Description can not be empty.'],
trim: true,
text: true
},
release_date: {
type: Date,
default: Date.now(),
required: [true, 'Release date can not be empty.']
},
category: {
type: String,
trim: true,
required: [true, 'Please provide category']
},
vote_average: {
type: Number,
min: [1, 'Rating must be 1 or above 1'],
max: [10, 'Rating must be 10 or below 10']
},
vote_count: {
type: Number,
default: 0
},
cast: [
{
type: mongoose.Schema.ObjectId,
ref: 'Cast'
}
]
})
//Create slug
showSchema.pre('save', function(next) {
this.slug = slugify(this.title, {lower: true})
next()
})
showSchema.pre(/^find/, function (next) {
this.populate({
path: 'cast',
select: '-__v'
})
next()
})
//Cast Schema
const castSchema = new Schema({
name: {
type: String,
trim: true,
text: true,
unique: true,
required: [true, 'Please provide name of actor']
},
profile_path: {
type: String
}
})
And this is how I did it
exports.add = async (req, res) => {
const show = {
category: req.body.category,
overview: req.body.overview,
poster_path: req.body.poster_path,
release_date: req.body.release_date,
title: req.body.title,
vote_average: req.body.vote_average,
}
try {
Cast.insertMany(req.body.cast, function(error, createdCast){
if(error){
console.log('Cast', error)
return
}
Show.create(show, function(error, createdShow){
if(error){
console.log('Show', error)
return
}
createdCast.forEach(element => {
createdShow.cast.push(element._id)
});
createdShow.save(function(error, show){
if(error){
return
}
console.log('saved Show', show)
})
})
})
} catch (error) {
console.log(error)
res.status(400).json({
message: 'fail',
error: error
})
}
}

How to automatically update a blog post after X amount of time has passed? Node.js Express Mongoose

I want to update the priority of a blog post if its older than say 2-3 days and i am not sure how to achieve this. In my route i try to identify if the blog post is older than 2 days, and if that was the case, it would change the priority from 'high' to ''. So far no luck and from what i read online, it seems that there may be npm packages that can achieve this for me.
Mongoose Schema
var blogSchema = new mongoose.Schema({
image: {
type: String,
trim: true
},
priority: {
type: String,
default: "",
trim: true
},
title: {
type: String,
trim: true
},
content: {
type: String,
trim: true
},
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
trim: true
},
username: {
type: String,
trim: true
},
name: {
type: String,
trim: true
},
},
slug: {
type: String,
unique: true,
trim: true
},
status: {
type: String,
trim: true
},
viewCount: {
type: Array,
timestamps: {
createdAt: 'createdAt',
updatedAt: 'updatedAt',
trim: true
}
},
category: {
type: String,
trim: true
},
categorySlug: {
type: String,
trim: true
},
tags: {
type: String,
trim: true
},
updated: {
type: Boolean,
default: false,
},
date: { type: Date, default: Date.now , trim: true},
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment',
trim: true
},
],
},{
timestamps: {
createdAt: 'createdAt',
updatedAt: 'updatedAt'
}
});
My Route
router.get('/', function (req, res) {
blog.find({ priority: ['high'] })
.sort({date: -1})
.limit(1)
.exec(function(err, high) {
if (err || !high) {
console.log(err);
req.flash('Troubleshooting Error')
redirect('/');
} else {
if(high && Date.now() > high.createdAt + 86400000 ) {
var priority = {slug: 'slug', priority: 'high'}
var newPriority = '';
blog.findOneAndUpdate(priority, newPriority,function(err, updated){
if(err) {
console.log(err);
} else {
console.log('Successfully updated priority');
}
});
}
};
});

Mongodb, search for text and geolocation in different collections

I have 3 collections: business, sevice, employee.
I need search by service (without fulltext), by employee and by the geolocation of each business, and should show only business.
var BusinessSchema = new Schema({
business_id: {
type: String,
required: true,
unique:true
},
name: {
type: String,
required: true
},
email: {
type: String,
},
description:{
type: String
},
location:{
country:{
type:String,
},
city:{
type:String
},
coord:[Number]
}
services:[{
type: Schema.Types.ObjectId,
ref: 'Service'
}]
},
{
timestamps: true
});
var ServiceSchema = new Schema({
business:{
type: Schema.Types.ObjectId,
ref: 'Business'
},
category:{
type: Schema.Types.ObjectId,
ref: 'Category',
index:true
},
name: {
type: String,
required: true,
index:true
},
employee: [{
type: Schema.Types.ObjectId,
ref: 'User'
}],
{
timestamps: true
});
var UserSchema = new Schema({
birthday:Date,
first_name: {
type: String,
required: true
},
last_name: {
type: String,
required: true
},
email: {
type: String,
unique: true,
match: [/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/, 'Please fill a valid email address'],
required: true
},
password:{
type: String
},
{
timestamps: true
});
What changes should i make collections to optimize the query?
Service.distinct('business',filter_services)
.exec(function (err, business) {
if (err) {
return cb({ status: 400, message: err }, null);
} else {
if(business.length > 0){
var filter_business = [{is_active:true},{is_approved:true}]
filter_business.push({_id:{$in:business}})
filter_business.push({location.coord:input_coord}})
filter_business = {$and:filter_business}
Business.find(filter_business)
.select('name services')
.exec(function (err,result){
if(err){
return cb({ status: 400, message: err }, null);
}
else{
if(result.length > 0){
var total = result.length;
}
return cb(null, result);
}
})
}
// si no hay business en el primer query, se retorna [].
else{
return cb(null, business);
}
}
});
Could geo filter by text and at the same time to get closer to a point?
For now, i am not using the Employee collection, but, if i would search by business name, employee name and service name simultaneously, what changes should make.
Your business model should be
var BusinessSchema = new Schema({
business_id: {
type: String,
required: true,
unique:true
},
name: {
type: String,
required: true
},
email: {
type: String,
},
description:{
type: String
},
address:{
country:{
type:String,
},
city:{
type:String
}
},
location : {
type: [Number],
index: '2dsphere'
},
services:[{
type: Schema.Types.ObjectId,
ref: 'Service'
}],
employees:[{
type: Schema.Types.ObjectId,
ref: 'User'
}]
},
{
timestamps: true
});
The change in schema is you have to create index on location, and for find business based on employee have to add employees id in business schema.Then you can you geo near query of mongodb.

mongoosejs findByIdAndUpdate a best way

I'm wondering if there a best way to do this:
/**
* Article Schema
*/
var PostSchema = new Schema({
title: {
type: String,
required: true,
trim: true
},
author:{
type: String,
required: true,
default: 'whisher'
},
slug: {
type: String,
index: { unique: true }
},
body: {
type: String,
required: true,
trim: true
},
avatar:{
type: String,
required: true
},
status: {
type: String,
required: true,
trim: true
},
created: {
type: Date,
required: true,
default: Date.now
},
published: {
type: Date,
required: true
},
categories: {
type: [String]
},
tags: {
type: [String],
required: true,
index: true
},
comment: {
type: Schema.Types.ObjectId,
ref: 'CommentSchema'
},
meta: {
votes: {
type: Number,
default: 0
},
comments: {
type: Number,
default: 0
}
}
});
/**
* Comment Schema
*/
var CommentSchema = new Schema({
post_id: {
type: Schema.Types.ObjectId,
ref: 'Post',
required: true
},
author:{
type: String,
required: true
},
email:{
type: String,
required: true
},
web:{
type: String
},
body: {
type: String,
required: true,
trim: true
},
status: {
type: String,
required: true,
default: 'pending'
},
created: {
type: Date,
required: true,
default: Date.now
},
meta: {
votes: Number
}
});
/**
* Create a comment
*/
exports.create = function(req, res) {
var comment = new Comment(req.body);
comment.save(function(err) {
if (err) {
return res.jsonp(500,{ error: 'Cannot save the comment' });
}
Post.findById(comment.post_id).exec(function(err, post) {
if (err) {
return res.jsonp(404,{ error: 'Failed to load post with id ' + comment.post_id });
}
if (!post) {
return res.jsonp(404,{ error: 'Failed to load post with id ' + comment.post_id });
}
post.meta.comments = post.meta.comments++;
post.save(function(err) {
if (err) {
return res.jsonp(500,{ error: 'Cannot update the post' });
}
res.jsonp(200,comment);
});
});
});
};
Btw I just looking at http://mongoosejs.com/docs/api.html#model_Model.findByIdAndUpdate
but like this:
Model.findByIdAndUpdate(comment.post_id, { post.meta.comments: post.meta.comments++ })
doesnt work
I think you need to use the $inc operator to increment the comment count like this...
Post.findByIdAndUpdate(comment.post_id, { $inc: {"meta.comments" : 1} }, callback);

Resources