How can I find fields with the same values in mongoose? - node.js

I want to find matches with the same match_id but I am unable to solution using mongoose . Any help would be appreciated , thank you. My match_id is type String and I want to check for duplicate matches that are being created .
Match Schema :
const MatchSchema = new mongoose.Schema({
match_id: {
type: String,
},
player1Id: {
type: String,
},
player2Id: {
type: String,
},
player1VideoId: {
type: String,
default: "blank",
},
player2VideoId: {
type: String,
default: "blank",
},
player1Score: {
type: Object,
default:{'noOne':0}
},
player2Score: {
type: Object,
default:{'noOne':0}
},
isWinner:{
type:String,
},
round:{
type: Number,
},
tournamentCategory:{
type:String,
},
tournamentId:{
type:ObjectID,
},
player1Details: {
type: mongoose.Schema.Types.ObjectId,
ref: "Contestant",
},
player2Details: {
type: mongoose.Schema.Types.ObjectId,
ref: "Contestant",
},
});

you should use $group for grouping data based on match_id , and select fields with count > 1, like this
let x = await Model.aggregate([
{
$group:{
_id : "$match_id",
result : {$push:"$$ROOT"},
count: { $sum: 1 }
}
},
{ "$match": { "count": { "$gte": 2 } } }
])

Related

how to insert data into this Mongoose schema

how to insert data in it on create method ? i have the following schema in which i want
to add data i am new and cannot understand that how to achieve this in mongoose please help i am having problrm when i insert the questions field remains empty instead of an array of objects
const { type } = require("express/lib/response");
const mongoose = require("mongoose");
const QuizSchema = mongoose.Schema({
course: {
type: mongoose.Schema.Types.ObjectId,
ref: "course"
},
topic: {
type: mongoose.Schema.Types.ObjectId,
ref: "topic"
},
quiztime: {
type: Date,
require: true,
},
allowedtime: {
type: Date,
require: true,
},
qusetions: [
{
questiontext: {
type: String,
},
correctans: {
type: String,
},
opt1val: {
type: String
},
opt2val: {
type: String
},
opt3val: {
type: String
},
opt4val: {
type: String
},
}
],
students: [
{
student: {
type: mongoose.Schema.Types.ObjectId,
ref: "student"
},
selectedans: [
{
anstext: {
type: String
}
}
]
}
],
},
{
timestamps: true,
});
const Quizmodel = mongoose.model("quiz", QuizSchema);
module.exports = Quizmodel;
and please also how to update if i want to

updateMany and elemMatch in with nested schemas in mongoose (Node.js)

I'm trying to query a MongoDB database via mongoose to updateMany the fields of my database. I suppose that the first request is correct because mongoose doesn't fire any error, but for the nested schemas, I'm getting the following error.
My goal is to delete the occurences of the userTag in friends and remove the friendRequestsSent when userTarget equals userTag, friendRequestsReceived when userRequest equals userTag and notification when data equals userTag.
Here are the schemas of my Model
const NotificationSchema = new Schema({
title: String,
type: Number,
icon: String,
data: String,
createdAt: { type: Date, default: Date.now },
})
const FriendRequestSchema = new Schema({
userRequest: { type: String, required: true },
userTarget: { type: String, required: true },
createdAt: { type: Date, default: Date.now },
})
const UserSchema = new Schema({
tag: { type: String, required: true, unique: true },
friendRequestsSent: { type: [FriendRequestSchema] },
friendRequestsReceived: { type: [FriendRequestSchema] },
friends: { type: [String] },
notifications: { type: [NotificationSchema] },
})
The request
const updateResponse = await User.updateMany(
{
friends: { $elemMatch: { $eq: userTag } },
friendRequestsSent: {
userTarget: {
$elemMatch: { $eq: userTag },
},
},
friendRequestsReceived: {
userRequest: {
$elemMatch: { $eq: userTag },
},
},
notifications: {
data: {
$elemMatch: { $eq: userTag },
},
},
},
{
$pull: {
friends: userTag,
friendRequestsSent: { userTarget: userTag },
friendRequestsReceived: { userRequest: userTag },
notifications: { data: userTag },
},
}
)
The error
Error while deleting the user account: Cast to String failed for value "{ '$elemMatch': { '$eq': '0eQzaAwpt' } }" at path "userRequest" for model "User"
The userRequest field in friendRequestsReceived is type String, not array so $elemMatch will not work. Also, you don't need to use $elemMatch because you specify only a single condition in the $elemMatch expression as it says in the docs:
If you specify only a single condition in the $elemMatch expression, you do not need to use $elemMatch.
In your case, you just need to do something like (details here):
await User.updateMany({
friends: userTag,
"friendRequestsSent.userTarget" : userTag,
"friendRequestsReceived.userRequest": userTag,
"notifications.data": userTag
}...

$pull not removing element from collection

I am trying to make a like/unlike system. and for unlike i need to remove the user from array of likes. but the mongodb $pull doesn't work.
the $inc command works fine but $pull doesn't.
here is my schema
postedBy: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "User"
},
likes: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User"
}
],
likeCount: {
type: Number,
default: 0
},
commentBody: {
type: String
},
contentId: {
type: mongoose.Schema.Types.ObjectId,
refPath: "contentType",
required: true
},
contentType: {
type: String,
required: true,
enum: ["Video", "Comment"]
},
isApproved: {
type: Boolean,
default: true
},
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Comment"
}
],
postedOn: {
type: Date,
default: Date.now()
}
mongodb query
await Video.updateOne(
{ _id: contentId, likeCount: { $gt: 0 } },
{
$pull: {
likes: decoded.id
},
$inc: { likeCount: -1 }
}
);
You should update your query to look like this:
await Video.updateOne(
{ _id: contentId, likeCount: { $gt: 0 } },
{
$pull: {
"likes": { "_id": ObjectId(decoded.id)}
},
$inc: { likeCount: -1 }
}
);
I assume that in devede.id you have string, and string is not the same as ObjectId. Because of that we need to transform it to ObjectId.

Mongoose sub field aggregation with full text search and project

I have a Mongoose model called Session with a field named course (Course model) and I want to perform full text search on sessions with full text search, also I wanna aggregate results using fields from course sub field and to select some fields like course, date, etc.
I tried the following:
Session.aggregate(
[
{
$match: { $text: { $search: 'web' } }
},
{ $unwind: '$course' },
{
$project: {
course: '$course',
date: '$date',
address: '$address',
available: '$available'
}
},
{
$group: {
_id: { title: '$course.title', category: '$course.courseCategory', language: '$course.language' }
}
}
],
function(err, result) {
if (err) {
console.error(err);
} else {
Session.deepPopulate(result, 'course course.trainer
course.courseCategory', function(err, sessions) {
res.json(sessions);
});
}
}
);
My models:
Session
schema = new mongoose.Schema(
{
date: {
type: Date,
required: true
},
course: {
type: mongoose.Schema.Types.ObjectId,
ref: 'course',
required: true
},
palnning: {
type: [Schedule]
},
attachments: {
type: [Attachment]
},
topics: {
type: [Topic]
},
trainer: {
type: mongoose.Schema.Types.ObjectId,
ref: 'trainer'
},
trainingCompany: {
type: mongoose.Schema.Types.ObjectId,
ref: 'training-company'
},
address: {
type: Address
},
quizzes: {
type: [mongoose.Schema.Types.ObjectId],
ref: 'quiz'
},
path: {
type: String
},
limitPlaces: {
type: Number
},
status: {
type: String
},
available: {
type: Boolean,
default: true
},
createdAt: {
type: Date,
default: new Date()
},
updatedAt: {
type: Date
}
},
{
versionKey: false
}
);
Course
let schema = new mongoose.Schema(
{
title: {
type: String,
required: true
},
description: {
type: String
},
shortDescription: {
type: String
},
duration: {
type: Duration
},
slug: {
type: String
},
slugs: {
type: [String]
},
program: {
content: {
type: String
},
file: {
type: String
}
},
audience: [String],
requirements: [String],
language: {
type: String,
enum: languages
},
price: {
type: Number
},
sections: [Section],
attachments: {
type: [Attachment]
},
tags: [String],
courseCategory: {
type: mongoose.Schema.Types.ObjectId,
ref: 'course-category',
required: true
},
trainer: {
type: mongoose.Schema.Types.ObjectId,
ref: 'trainer'
},
trainingCompany: {
type: mongoose.Schema.Types.ObjectId,
ref: 'training-company'
},
status: {
type: String,
default: 'draft',
enum: courseStatus
},
path: {
type: String
},
cover: {
type: String,
required: true
},
duration: {
type: Number,
min: 1
},
createdAt: {
type: Date,
default: Date.now
},
updatedAt: {
type: Date
}
},
{ versionKey: false }
);
I am not sure if what I tried is gonna bring me what I want and I am getting this error concerning the $unwind operator:
MongoError: exception: Value at end of $unwind field path '$course'
must be an Array, but is a OID
Any kind of help will be really appreciated.
You can try below aggregation.
You are missing $lookup required to pull course document by joining on course object id from session document to id in the course document.
$project stage to keep the desired fields in the output.
Session.aggregate([
{
"$match": {
"$text": {
"$search": "web"
}
}
},
{
"$lookup": {
"from": "courses",
"localField": "course",
"foreignField": "_id",
"as": "course"
}
},
{
"$project": {
"course": 1,
"date": 1,
"address": 1,
"available": 1
}
}
])
Course is an array with one course document. You can use the $arrayElemAt to project the document.
"course": {"$arrayElemAt":["$course", 0]}

Node.js with mongoose delete one array element

I am trying to delete one array element when I click delete button on jade view page.
When clicked, it's going to send selected instructor objected as req.body.
At sever side, it will find courses that contain the instructor objectId.
Any idea for me?
Thank you for reading it.
here is my code:
var id = req.body._id;
clist.find({ instructors: { $in: [id] } }).exec(function (err, result) {
result.forEach(function (obj) {
clist.update(
{ _id: new mongoose.Types.ObjectId(obj._id)},
{ $pull: { instructors : [new mongoose.Types.ObjectId(id)] } }
);
console.log(new mongoose.Types.ObjectId(obj._id) + ' was deleted');
});
});
Schema Clist and ilist:
var instructorlist = mongoose.Schema({
name: { type: String, required: true },
age: { type: Number, required: true },
gender: { type: String, required: true },
DOB: { type: Date, required: true, default: Date.now },
email: { type: String, required: true },
phone: { type: Number, required: true },
address: { type: String, required: true },
dateofstart: { type: Date, required: true},
courses: [{
type: mongoose.Schema.Types.ObjectId,
ref: "clist"
}]
});
var courselist = mongoose.Schema({
coursename: { type: String, required: true },
coursenumber: { type: String, required: true },
coursecredit: { type: Number, required: true },
courseroom: { type: String, required: false },
courseregisteddate: {type: Date, default: Date.now},
students: [{
type: mongoose.Schema.Types.ObjectId,
ref: "slist"
}],
instructors: [{
type: mongoose.Schema.Types.ObjectId,
ref: "ilist"
}]
});
one example for mongodb :
{
"_id": {
"$oid": "591a7a3b391a1842e8a69e23"
},
"coursename": "JDKD",
"coursenumber": "COMP4483",
"coursecredit": 4,
"courseroom": "sdaf",
"instructors": [
{
"$oid": "591a374422a3a13d38c0bbe5"
}
],
"students": [],
"courseregisteddate": {
"$date": "2017-05-16T04:04:11.848Z"
},
"__v": 0
}
When I add instructor objectID in Course.
var newcourse = new clist({
'coursename': req.body.coursename, 'coursenumber': req.body.coursenumber, 'coursecredit': req.body.coursecredit
, 'courseroom': req.body.room, 'instructors': instructors._id
});
Use same operation to find and update multiple
clist.update(
{ instructors: { $in: [id] }},
{ $pull: { instructors : { _id : new mongoose.Types.ObjectId(id) } } }, //or{ $pull: { instructors: mongoose.Types.ObjectId(id) } }
{
multi:true
},
function(error, success){
if(error){
console.log("error",error)
}
console.log("success",success)
});

Resources