MongoError in filter with $elementMatch - node.js

I'm using Mongoose in my NodeJS backend for a chat.
I want to filter all the messages from conversation that the user don't read it in my MongoDB db:
controller
var filter = {
$and:[
{
conversation:req.conversation.id
},
{
$not:
{
readers:
{
$elemMatch:
{
user:req.user.id
}
}
}
}
]
};
Message
.find(filter)
.exec(function(err,messages){
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
console.log(messages);
res.jsonp(true);
}
});
Debugging this code:
messages-> undefined
err-> Error {name: 'MongoError'}
And the filter variable:
I don't understand the error, I think maybe I applied wrong the filter... What is incorrect in my code?
Thank you so much!! I share the Message shema below:
message shema
var MessageSchema = new Schema({
conversation:{
type: Schema.ObjectId,
ref: 'Conversation'
},
created: {
type: Date,
default: Date.now
},
user:{
type: Schema.ObjectId,
ref: 'User'
},
message:{
type: String,
default:''
},
readers:[{
date: {
type: Date,
default: Date.now
},
user:{
type: Schema.ObjectId,
ref: 'User'
}
}]
});

Related

How do I find object based on child populated property on mongoose

I'm new in mongoose.
I have a Schema like this:
const sessionSchema = mongoose.Schema({
createdBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
registers: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Register',
},
],
date: {
type: Date,
default: Date.now,
immutable: true,
},
});
And register model is this one:
const registerSchema = mongoose.Schema({
sets: [
{
weight: {
type: Number,
},
weightUnit: {
type: String,
default: 'kg',
},
repetitions: {
type: Number,
},
duration: {
type: Number,
},
},
],
session: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Session',
},
exercise: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Exercise',
},
creationDate: {
type: Date,
default: Date.now,
immutable: true,
},
});
I want to find all the sessions created by a user and has an register with an specificied exercise id. I tried this:
const result = Session.find({createdBy: userId, 'registers.exercise': exerciseId}).populate('registers');
But doesn't work. ¿Any suggestion?
Thanks :P
Try this:
Session.aggregate([
{
$match: { createdBy: userId }
},
{
$lookup: {
from: 'Register',
localField: 'registers',
foreignField: '_id',
as: 'registers'
}
},
{
$match: { 'registers.exercise': exerciseId }
}
])
.then((result) => {
console.log('Result: ', result);
})
.catch((err) => {
console.log('Error: ', err);
});
If you are not familiar with MongoDB aggregation framework, the query above might be a bit foreign to you. However, for cross collection queries like you described in your question, the aggregation framework is your best shot(for now).
The $match is basically doing what you would do with a Model.find(), while the $lookup is doing what you would do with a Model.<query>.populate()
You can read more about MongoDB aggregation framework here.

How to push objectId to mongodb schema field array of object using findByIdAndUpdate

Everytime I hit api I am getting same error-
I have tried sending value as parameters also but failed. Any help would be appreciated. When i use $set it updates same value everytime the web service is called but it does work but not with $push.
MongoError: The field 'songId' must be an array but is of type objectId in document
{_id: ObjectId('59709590380026118c22dd61')}
My Playlist schema code:-
var PlaylistSchema = new mongoose.Schema({
name: String,
coverphoto: { type: String, default: '' },
userId: {
type: ObjectId,
ref: 'User'
},
songId: [{ type: ObjectId, ref: 'Song' }],
updated_at: { type: Date, default: Date.now },
});
my Song Schema code
var mongoose = require('mongoose');
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
var SongSchema = new mongoose.Schema({
audioName:{type:String,default:''},
title: String,
// coverphoto: { type: String, default: '' },
singer: { type: String, default: '' },
movie: { type: String, default: '' },
album: { type: String, default: '' },
lyricist: { type: String, default: '' },
actors: { type: String, default: '' },
lyrics: { type: String, default: '' },
genre: { type: String, default: 'Random' },
duration: { type: String, default: '' },
size: { type: String, default: '' },
userId: {
type: ObjectId,
ref: 'User'
},
categoryId: {
type: ObjectId,
ref: 'Category'
},
updated_at: { type: Date, default: Date.now },
});
module.exports = mongoose.model('Song', SongSchema);
My Api code
/* post api to add song in playlist */
router.post('/addSongToPlaylist', function (req, res, next) {
Playlist.findOne({ '_id': req.body.playlistId }, function (err, playlist) {
if (err) return next(err);
console.log(playlist)
console.log("req.body.songId", req.body.songId);
if (playlist) {
Playlist.findByIdAndUpdate(
req.body.playlistId,
{ $push: { "songId": req.body.songId } },
{ new: true },
function (err, playlistData) {
if (err) return next(err);
res.json({ message: 'New Song added successfully', playlist: playlistData, success: true });
});
} else if (!Song) {
res.json({ message: 'Failed to add song', success: false });
}
});
});

Accessing object in array of arrays using mongoose

I have the following structure and am trying to remove an object in participants (league.division.participants).
var participantSchema = new mongoose.Schema({
player: { type: mongoose.Schema.Types.ObjectId, ref: 'Player' },
record: { type: mongoose.Schema.Types.ObjectId, ref: 'ParticipantRecord' },
events: [ { type: mongoose.Schema.Types.ObjectId, ref: 'Event' } ]
});
var divisionSchema = new mongoose.Schema({
name: String,
participants: [ participantSchema ]
});
var leagueSchema = new mongoose.Schema({
name: String,
startDate: { type: Date, default: Date.now },
endDate: Date,
locked: Boolean,
leagueType: { type: mongoose.Schema.Types.ObjectId, ref: 'LeagueType' },
game: { type: mongoose.Schema.Types.ObjectId, ref: 'Game' },
divisions: [ divisionSchema ],
});
mongoose.model('League', leagueSchema);
var _RemoveDivisionParticipant = function(participantId)
{
return new Promise((resolve,reject) =>{
Models.League.findOne({'divisions.participants._id':participantId})
.populate('divisions')
.populate('divisions.participants')
.exec((err, league) => {
if (err) {return reject(err)}
league.divisions(XXXXX).participants(participantId).remove();
console.log(league.divisions[0].participants[0])
})
})
}
This is what i have so far, but obviously it returns the league object, and i have no way of getting to the participants since I don't know which division the participant is in (Shown by XXXXX in the sample). Any pointers as to what I should do?
You can use $pull to remove an array element based on a condition :
League.update({
'divisions.participants._id': participantId
}, {
$pull: {
'divisions.$.participants': {
"_id": participantId
}
}
}, { multi: true }, function(err, res) {
console.log(res);
});

Node.js - mongoose. Cannot make a query on an ObjectId

This is my first time asking a question here.
I am using node.js and mongoose and I have the following three schemas:
var CustomerCouponSchema = new Schema({
coupon: { type: Schema.ObjectId, ref: 'Coupon' }
});
var CouponSchema = new Schema({
isActive: { type: Boolean, default: false },
supermarket: { type: Schema.ObjectId, ref: 'Supermarket' }
});
var SupermarketSchema = new Schema({
name: { type: string }
});
When I am trying to perform the following query:
//I have a variable named supermarketId which is an ObjectId
CustomerCoupon.find({ isUsed: false })
.populate({
path: 'coupon',
match: {
supermarket: { $or: [{ $eq: null }, { $eq: supermarketId }] },
isActive: true,
}
}).exec(function(err, data) {
});
I get the following error: Can't use $or with ObjectId.
Any help would be welcome

mongoose save embedded document

I have the following schema:
var StorySchema = new Schema({
title: { type: String, required: true },
users: {
id: { type: Schema.ObjectId, ref: 'Users' },
creator: { type: Boolean }
},
maxlines: { type: Number, default: '10'},
lines: {
text: { type: String },
entered_at: { type: Date },
user: {
id: { type: Schema.ObjectId, ref: 'Users' }
}
},
created_date: { type: Date, default: Date.now },
updated_date: { type: Date, default: Date.now },
})
I want to push data into lines and am trying to do so with the below update:
exports.update = function (req, res) {
Stories
.findOne({ _id: req.params.id }, function (err, story) {
if (err) {
res.json(200, {
success: "false",
message: err.message
})
} else {
story.maxlines = story.maxlines - 1
story.lines.push ({
text : req.body.text,
'user.id' : req.headers.id,
entered_at : new Date().toISOString()
})
story.save(function(err, story) {
if (err) {
res.json(200, {
success: "false",
message: err.message
})
} else if (story) {
res.json({
sucess: "true",
message: story
})
}
})
}
})
}
I get an error of TypeError: Object { user: {} } has no method 'push', not entirely sure how to update the lines and the user associated with the line
Because story.lines is not an Array. You probably need to update the Schema to convert the lines to type Array in this way:
var LineSchema = new Schema({
text: {
type: String
},
entered_at: {
type: Date
},
user: {
id: {
type: Schema.ObjectId,
ref: 'Users'
}
}
});
var StorySchema = new Schema({
title: {
type: String,
required: true
},
users: {
id: {
type: Schema.ObjectId,
ref: 'Users'
},
creator: {
type: Boolean
}
},
maxlines: {
type: Number,
default: '10'
},
lines: [LineSchema],
created_date: {
type: Date,
default: Date.now
},
updated_date: {
type: Date,
default: Date.now
},
})

Resources