Delete an object from an array in Express Mongoose - node.js

{
"_id": "608c3d353f94ae40aff1dec4",
"userId": "608425c08a3f8db8845bee84",
"experiences": [
{
"designation": "Manager",
"_id": "609197056bd0ea09eee9429c"
},
{
"designation": "Asst. Manager",
"_id": "608c530de8ade5221b0e6d4e"
},
{
"designation": "Sr. Manager",
"_id": "608c534be8ade5221b0e6d4f"
},
]
}
I want to delete object in array with id 608c530de8ade5221b0e6d4e, here is my code but that gives me error.
This is the controller:
const userId = req.userData.userId;
const id = req.params.id;
Experience.findOneAndUpdate({ userId: userId }, { $pull: { 'experiences': { '_id': id } }}, { multi:true }, function(err, obj) {
// //do something here
});
This is model:
const newExpSchema = new mongoose.Schema({
designation: { type: String, default: ""},
});
const experienceSchema = new mongoose.Schema({
userId: { type: String, required: true },
experiences: [newExpSchema],
});
export default model("experience", experienceSchema);
I am getting below error on { $pull: { 'experiences': { '_id': id } }}
Error:
No overload matches this call.
Overload 1 of 3 .........
.......
The expected type comes from property '$pull' which is declared here on type 'UpdateQuery<Document<any, {}>>'

Can you try this:
Folder.findOneAndUpdate({
"_id": "608c3d353f94ae40aff1dec4"
},
{
$pull: {
"experiences": {
"_id": "608c530de8ade5221b0e6d4e"
}
}
},
{
"multi": false
})
Here is a working example: https://mongoplayground.net/p/YtNGBTr52U9

Related

Mongoose Populate return empty array with joining and generating children from other table

I have looked at all of the cases on StackOverflow but I could not fix this error:
You can find the whole code here :
Link to SandBox
I have 2 collections: "pars" for parents and "chil" for children
pars:
[{
"_id": {
"$oid": "607091fa48ea8376b9398ba7"
},
"name": "ParA"
},{
"_id": {
"$oid": "6070920748ea8376b9398ba8"
},
"name": "ParB"
}]
chil:
[{
"_id": {
"$oid": "6070921648ea8376b9398ba9"
},
"name": "Chil1",
"parRef": {
"$ref": "chils",
"$id": {
"$oid": "6070920748ea8376b9398ba8"
}
},
"parId": "6070920748ea8376b9398ba8"
},{
"_id": {
"$oid": "6070922648ea8376b9398baa"
},
"name": "Chil2",
"parRef": {
"$ref": "chils",
"$id": {
"$oid": "607091fa48ea8376b9398ba7"
}
},
"parId": "607091fa48ea8376b9398ba7"
},{
"_id": {
"$oid": "6070923348ea8376b9398bab"
},
"name": "Chil3",
"parRef": {
"$ref": "chils",
"$id": {
"$oid": "607091fa48ea8376b9398ba7"
}
},
"parId": "607091fa48ea8376b9398ba7"
}]
I am using populate with mongoose but it returns an empty array
Code
const Schema = mongoose.Schema;
const getParChil = async () => {
const schemaPar = new Schema(
{
_id: Schema.Types.ObjectId,
name: String,
chils: [
{
type: Schema.Types.ObjectId,
ref: "modelChil"
}
]
},
{ collection: "pars" }
);
const schemaChil = new Schema(
{
_id: Schema.Types.ObjectId,
name: String,
parId: { type: Schema.Types.ObjectId, ref: "modelPar" }
},
{ collection: "chils" }
);
const modelChil = mongoose.model("modelChil", schemaChil);
const modelPar = mongoose.model("modelPar", schemaPar);
const res = await modelPar.find({}).populate("chil");
console.log("result", res);
};
getParChil();
response:
[
{ chils: [], _id: 607091fa48ea8376b9398ba7, name: 'ParA' },
{ chils: [], _id: 6070920748ea8376b9398ba8, name: 'ParB' }
]
Please advise. I would like to join these two tables and get the result like this:
expected behaviour
[
{
_id: 607091fa48ea8376b9398ba7,
name:"ParA",
chils:[{"name":"Chil2"},{"name":"Chil3"}]
},
{
_id: 6070920748ea8376b9398ba8,
name:"ParB",
chils:[{"name":"Chil1"}]
}
]
You should reference the model name and not the collection name:
const schemaPar = new Schema(
{
_id: Schema.Types.ObjectId,
name: String,
chils: [
{
type: Schema.Types.ObjectId,
ref: "Chil", // change made here
},
],
},
{ collection: "pars" }
);
const schemaChil = new Schema(
{
_id: Schema.Types.ObjectId,
name: String,
parId: {
type: Schema.Types.ObjectId,
ref: "Par" // change made here
},
},
{ collection: "chils" }
);
modelChil=mongoose.model("Chil", schemaChil);
modelPar=mongoose.model("Par", schemaPar);

Mongoose $lookup object returns empty array

I have tried other similar kind of questions available but nothing seems to work for me.
I have two collections:
leads:
const mongoose = require("mongoose");
const id = mongoose.Schema.Types.ObjectId;
const leadsSchema = mongoose.Schema(
{
_id: id,
userId: { type: id, ref: "User", required: true },
leadName: String,
leads: [
{
_id: id,
name: String,
status: { type: String, required: false, default: "New" },
leadActivity: { type: String, required: false, default: "No Campaign Set" },
headline: { type: String, required: false },
location: { type: String, required: false },
leadType: { type: id, ref: "LeadsCategory", required: true },
}
],
campaignAssociated: {type: id, ref: "campaign"},
},
{
timestamps: true
}
);
module.exports = mongoose.model("lead", leadsSchema);
leadCategory
const mongoose = require("mongoose");
const leadsCategorySchema = mongoose.Schema(
{
_id: mongoose.Schema.Types.ObjectId,
name: {
type: String,
required: false,
},
leadsData: [{ type: Array, ref: "lead" }],
},
{ timestamps: true }
);
module.exports = mongoose.model("LeadsCategory", leadsCategorySchema);
I am trying to reference/populate the name of the lead from leadscategory schema into the leads
exports.get_single_lead_info = (req, res) => {
const { userId } = req.user;
const { leadid } = req.body;
let idToSearch = mongoose.Types.ObjectId(leadid);
Lead.aggregate([
{
$lookup: {from: 'leadscategories', localField: 'leadType', foreignField: 'name', as: 'type as'}
},
{
$match: {
userId: mongoose.Types.ObjectId(userId),
},
},
{
$unwind: "$leads",
},
{
$match: {
"leads._id": idToSearch,
},
},
])
.exec(function (err, result) {
if (err) {
return res.status(400).json({ message: "Unable to fetch data", err });
}
if (!result.length) {
res.status(404).json("No result found");
} else {
res.status(200).json({ message: "Lead info found", result });
}
});
};
But it outputs me the lookup result as an empty array everytime:
{
"message": "Lead info found",
"result": [
{
"_id": "5ece11cbac50c434dc4b7f2c",
"leadName": "python",
"leads": {
"status": "New",
"leadActivity": "Campaign Set",
"name": "Hailey",
"headline": "Machine Learning | Python",
"location": "New Delhi Area, India",
"_id": "5ece11cbac50c434dc4b7f29",
"leadType": "5ebce0f81947df2fd4eb1060"
},
"userId": "5eba83d37d4f5533581a7d58",
"createdAt": "2020-05-27T07:07:55.231Z",
"updatedAt": "2020-05-27T10:47:42.098Z",
"__v": 0,
"type as": [] //<--- Need lead type name associated inside this
}
]
}
Input: "leadid": "5ece11cbac50c434dc4b7f29"
Any help appreciated.
[
{
$match: {
userId: mongoose.Types.ObjectId(userId),
},
},
{
$unwind: "$leads",
},
{
$match: {
'leads._id': idToSearch,
},
},
{
$lookup: {
from: 'leadscategories',
localField: 'leads.leadType',
foreignField: '_id',
as: 'type as'
}
},
]

Matching one of two fields with $in and $elemMatch

Combining $in and $elemMatch
I'm trying to find a partial match for an employee's first or last name. I tried using the $or operator, but Mongo doesn't seem to recognize it.
Where am I going wrong?
router.get('/employees', async (req, res, next) => {
if(req.query.name) {
const response = await Companies.find({ employees:
{
$elemMatch: {
$in: [
{ first_name:new RegExp(req.query.name, 'i') },
{ last_name:new RegExp(req.query.name, 'i') }
]
}
}
})
res.json({ response })
}
else { next() }
})
My schema looks like this:
const companies = new mongoose.Schema({
company: [{
name: { type:String, required:true },
contact_email: { type:String, required:true },
employees: [{
first_name:String,
last_name:String,
preferred_name:String,
position: { type:String },
birthday: { type:Date },
email: { type:String },
}],
}]
}, {
timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' }
})
I have some names in there that should match (including just "nna"), but sending a get request to /employees?name=nna just returns an empty response array.
the most convenient way to get employees back would be to unwind and then match like so:
db.Companies.aggregate({
"$unwind": "$employees"
}, {
"$project": {
"employees": "$employees",
"_id": 0
}
}, {
"$match": {
"$or": [
{
"employees.first_name": /anna/i
},
{
"employees.last_name": /anna/i
}
]
}
})
on the other hand, if the goal is to get the companies back, then this would work:
db.Companies.find({
"employees": {
"$elemMatch": {
"$or": [
{
"first_name": /anna/i
},
{
"last_name": /anna/i
}
]
}
}
})

Find duplicate enteries from collection node js?

I want to find out duplicate entries on the basis of field " name " and in the result, I want to fetch " name " and " _id ".
I have tried using aggregate function and it is returning all the result from database as null:
here is my code:
ModelRestaurant.aggregate((
// { "$group": { "_id": "$name", "count": { "$sum": 1 } } },
// { "$match": { "_id": { "$ne": null }, "count": { "$gt": 1 } } },
// { "$project": { "name": "$_id", "_id": 0 } }
{ $group: { "_id": "$name", "name": { $first: "$name" }, "count": { $sum: 1 } } },
{ $match: { "count": { $gt: 1 } } },
{ $project: { "name": 1, "_id": 0 } },
{ $group: { "_id": null, "duplicateNames": { $push: "$name" } } },
{ $project: { "_id": 0, "duplicateNames": 1 } }
), function (err, result) {
if (result) {
console.log(result)
}
})
from above commented code it is giving me all id but now it is giving me null values and all the result json of 6000 with null value.
here is the field of data in collection:
My Schema is :
var mongoose = require('mongoose');
var uniqueValidator = require('mongoose-unique-validator');
var autoIncrement = require('mongoose-auto-increment');
var ModelRestaurant = new mongoose.Schema({
name: String,
ownerName: String, // to be removed by checking code
ownerID: Number,
ownerEmail: String, // to be removed by checking code
city: String,
zipCode: String,
image: [String],
restaurantType: String,
address: String,
landmark: String,
isAddedByCustomer: {
type: Boolean,
default: false
},
location: {
lat: String,
long: String
}
},
{
timestamps: true
});
ModelRestaurant.plugin(autoIncrement.plugin, 'Restaurants');
ModelRestaurant.plugin(uniqueValidator);
mongoose.model('Restaurants', ModelRestaurant);
The following code should print all the duplicates:
db.ModelRestaurant.aggregate([
{$group:{"_id":"$name","name":{$first:"$name"},"count":{$sum:1}}},
{$match:{"count":{$gt:1}}}
])

How can i use MONGODB aggregation framework with nested external document - Mongoose and NodeJS

I have these Mongoose schemes:
// User schema
exports.User = new Schema({
name: {
type: String,
required: true
},
home: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Post'
}]
});
// Post schema
exports.Post = new Schema({
likes: [{
type: Schema.Types.ObjectId,
ref: 'User'
}],
author: {
id: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true
},
name: {
type: String,
required: true
},
shortId: String, // this is User id
},
created: {
type: Date,
default: Date.now,
required: true
}
});
// THE DATA IN THE DATABASE
// User
{"name" : "Mio Nome",
"home" : [
ObjectId("533af14b994c3647c5c97338")
]}
// Post
{ "author" : {
"id" : ObjectId("533af14b994c3647c5c97338"),
"name" : "AutoreDelPost"
},
"likes" : [
ObjectId("533af14b994c3647c5c97337"),
ObjectId("533af14b994c3647c5c97339"),
ObjectId("533af14b994c3647c5c97340")
]
}
And i want to get from users the posts in home field and count how many likehave one user
With this code i can show all posts in home whit populate, but i can't count likes.
req.db.User.find({
_id: req.user._id //req.user is my test user
}, {
home: 1
})
.limit(200)
.populate('home')
.exec(function (err) {
if (!err) {
return res.json(200)
}
return res.json(500, err)
});
// output
[
{
"_id": "533af0ae994c3647c5c97337",
"name" : "Mio Nome"
"home": [
{
"_id": "533b004e6bcb9105d535597e",
"author": {
"id": "533af14b994c3647c5c97338",
"name": "AutoreDelPost"
},
"likes": [] // i can't see like and i can't count they
}
]
I tryed to use aggregate, to count etc but i can't see the posts getting populated but their _id
req.db.User.aggregate({
$match: {
_id: req.user._id
}
}, {
$project: {
home: 1
}
}, {
$unwind: "$home"
}).exec(function (err, home) {
if (!err) {
return res.json(200, home)
}
return res.json(500, err)
});
// output
[
{
"_id": "533af0ae994c3647c5c97337",
"home": "533b004e6bcb9105d535597e"
},
{
"_id": "533af0ae994c3647c5c97337",
"home": "533b004e6bcb9105d5355980"
},
{
"_id": "533af0ae994c3647c5c97337",
"home": "533b004f6bcb9105d5355982"
},
{
"_id": "533af0ae994c3647c5c97337",
"home": "533b004f6bcb9105d5355984"
},
{
"_id": "533af0ae994c3647c5c97337",
"home": "533b00506bcb9105d5355986"
}
]
QUESTION: I want to get from users the posts in home field and count how many like a user has
Perhaps you can store your data more denormalized and add a counter field which is incremented on each new "like". See http://cookbook.mongodb.org/patterns/votes/. Something like:
update = {'$push': {'voters': user_id}, '$inc': {vote_count: 1}}

Resources