how to update the specific field in mongoose - node.js

the present Object is :-
{
_id: "abc12344",
renderId: '123456789',
concernTo: [{
name: 'vijay 4',
id: 'snhdkjn786786',
commons: []
},
{
name: 'ak',
id: 'sdkfg787877',
commons: []
}
]
}
Output needs to be like:
{
_id: "abc12344",
renderId: '123456789',
concernTo: [{
name: 'vijay 4',
id: 'snhdkjn786786',
commons: [{to: "xyz", from:"abc"}, {to: "xyz", from:"abc"}]
},
{
name: 'ak',
id: 'sdkfg787877',
commons: []
}
]
}
So need to push data in concernTo in commons field
In query i'm trying to search by renderId and id in "concernTo" array field and trying to update the object.
Query for that:---
let obj = { to: "xyz", from: "abc" };
let filter = {
renderId: "123456789",
"concernTo.id": "snhdkjn786786",
};
let update = {
$push: {
"concernTo.id.$": { subComment: obj },
},
};
let doc = await blogsCommentModel.findOneAndUpdate(filter, update, {
returnOriginal: false,
});
console.log(doc);

You want to be using arrayFilters for this, like so:
let doc = blogsCommentModel.findOneAndUpdate(filter,
{
"$push": {
"concernTo.$[elem].commons": obj
}
},
{
arrayFilters: [
{
"elem.id": "snhdkjn786786"
}
]
})
Mongo Playground

Related

Mongoose get documents where id does NOT exist inside nested object

I am trying to query a list of documents where a userid DOES NOT exist inside an array of objects.
The database (documents) looks like this:
[
{
title: 'object 1',
description: 'description 1',
members: [
{ profile: { id: '123', ...}, data: {} },
{ profile: { id: 'abc', ...}, data: {} },
{ profile: { id: 'def', ...}, data: {} },
]
},
{
title: 'object 2',
description: 'description 3',
members: [
{ profile: { id: 'aaa', ...}, data: {} },
{ profile: { id: 'bbb', ...}, data: {} },
{ profile: { id: 'ccc', ...}, data: {} },
]
},
]
Given that my userid is 'aaa' I am trying to query all documents where I am NOT a member.
I can successfully query all documents where my userid exists using this code:
await this._repository.findManyByQuery(
{
members: {
$elemMatch: {
"profile.id": "aaa",
},
},
},
)
However I am looking to query all objects where my ID DOES NOT exist. I have tried using $ne however it still returns the documents where the user id exists
members: {
$elemMatch: {
"profile.id": { $ne: "aaa" },
},
},
I guess I am looking for the opposite of $elemMatch but for querying inside an arry
You can use $not to negate the $elemMatch like this:
await this._repository.findManyByQuery({
members: {
"$not": {
$elemMatch: {
"profile.id": "aaa"
}
}
}
})
Example here

mongodb insert data into the array of objects and update it

I need to make a vote, it looks like an array of objects, look like the user’s ID and the value that he set.
If the user has already voted, but changed his value, you need to change the value of the rate in the array of objects for this user.
I need to make an array of objects into which data will be inserted like this {rate: 3, user: "asdr2r24f2f42f24"} and if the user has already voted in this array, then you need to change the value rate of the given user
I already tried to do something, but it seems to me you can write something better, can you help?
JSON https://jsoneditoronline.org/?id=442f1dae0b2d4997ac69d44614e55aa6
router.post('/rating', (req, res) => {
console.log(req.body)
// { id: 'f58482b1-ae3a-4d8a-b53b-ede80fe1e225',
// rating: 5,
// user: '5e094d988ddbe02020e13879' }
Habalka.find({
_id: req.body.id
})
.then(habalka => {
// here I need to check whether the user has already voted or not, and from this whether to add an object with it or update the number
Habalka.updateOne(
{_id: req.body.id},
{$push: {rating: {rate: req.body.rating, user: req.body.user}}}
)
.then(e => {
console.log(e)
})
});
});
Schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const HabalkaSchema = new Schema({
_id: {
type: String
},
bio: {
firstname: String,
lastname: String,
middlename: String,
company: String
},
rating: [
],
files: [
{
_id: {
type: String
},
destination: {
type: String
},
filename: {
type: String
},
path: {
type: String
},
folder: {
type: String
},
info: {
size: {
type: Number
},
mimetype: {
type: String
},
encoding: {
type: String
},
originalname: {
type: String
},
fieldname: {
type: String
},
},
date: {
type: Date,
default: Date.now
},
bio: {
type: Object
},
userId: String,
guessId: {},
}
],
date: {
type: Date,
default: Date.now
}
});
module.exports = Habalka = mongoose.model('habalka', HabalkaSchema);
This is an aggregation query which inserts a new user or updates the rating of existing user in the rating array:
The req.body.id, req.body.user and req.body.rating are set as follows for the example code:
var ID = 1, INPUT_USER = "new user", INPUT_RATE = 5;
const matchStage = { $match: { _id: ID } };
const facetStage = {
$facet: {
new_user: [
{ $match: { "rating.user": { $not: { $eq: INPUT_USER } } } },
{ $addFields: { rating: { $concatArrays: [ "$rating", [ { user: "new user", rate: INPUT_RATE } ] ] } } },
],
user: [
{ $match: { "rating.user": INPUT_USER } },
{ $addFields: {
rating: {
$map: {
input: "$rating",
as: "r",
in: {
$cond: [ { $eq: [ "$$r.user", INPUT_USER ] },
{ user: "$$r.user", rate: { $add: [ "$$r.rate", INPUT_RATE ] } },
"$$r"
]
}
}
}
} }
]
}
};
const projectStage = {
$project: {
result: { $arrayElemAt: [ { $concatArrays: [ "$user", "$new_user" ] }, 0 ] }
}
};
const queryPipeline = [
matchStage,
facetStage,
projectStage
];
// Run the aggregation query and get the modified document
// after applying the user and rate data in the rating array.
// The result of the aggregation is used to update the collection.
col.aggregate(queryPipeline).toArray( ( err, docs ) => {
console.log("Aggregation output:");
console.log( JSON.stringify( docs[0] ) );
// Update the aggregate result to the collection.
col.updateOne( { _id: docs[0].result._id },
{ $set: { rating: docs[0].result.rating } },
( err, updateResult ) => {
console.log( 'Updated count: ', updateResult.matchedCount );
}
);
callback(docs);
} );
Example collection document:
{ "_id" : 1, "rating" : [ { "user" : "user1", "rate" : 2 } ] }
If the input is var ID = 1, INPUT_USER = "new user", INPUT_RATE = 5; the updated document will be:
{ "_id" : 1, "rating" : [ { "user" : "user1", "rate" : 2 }, { "user" : "new user", "rate" : 5 } ] }
If the input is var ID = 1, INPUT_USER = "user1", INPUT_RATE = 5; the updated document will be:
{ "_id" : 1, "rating" : [ { "user" : "user1", "rate" : 7 } ] }

How to remove objects from an array within a mongoose model

I am trying to remove multiple objects that are in an array in mongoose. My Workout model look like this:
{
_id: 5e04068491a2d433007026cd,
exercises: [
{ _id: 5e0401b9dda7ea28a70e99ed, reps: '1', sets: '3' },
{ _id: 5e0401cadda7ea28a70e99ee, reps: '1', sets: '3' },
{ _id: 5e0401dbdda7ea28a70e99ef, reps: '1', sets: '3' }
]
}
I have an array of id's, named deletedExercises, these are the ids of the objects that I want removed from the exercise list. I am trying to loop through deletedExercise and remove any exercises that match the id of the deletedExercise item.
router.put("/:workoutId", (req, res)=>{
deletedOnes = req.body.exerciseId
deletedExercises = []
if(typeof deletedOnes === 'object'){
deletedOnes.forEach(item => {
deletedExercises.push(item)
})
} else {
deletedExercises.push(deletedOnes)
}
deletedExercises.forEach(item => {
Workout.findByIdAndUpdate( req.params.workoutId,
{ $pull: { exercises: { _id: item} } } )
});
You can simply delete exercises using the $in operator inside $pull like this:
router.put("/:workoutId", (req, res) => {
console.log(req.body.exerciseId); //[ '5e05c5306e964f0a549469b8', '5e05c5306e964f0a549469b6' ]
Workout.findByIdAndUpdate(
req.params.workoutId,
{
$pull: {
exercises: {
_id: {$in: req.body.exerciseId}
}
}
},
{ new: true }
)
.then(doc => {
res.send(doc);
})
.catch(err => {
console.log(err);
res.status(500).send("Error");
});
});
Let's say we have this workout with 3 exercises:
{
"_id": "5e05c5306e964f0a549469b5",
"exercises": [
{
"_id": "5e05c5306e964f0a549469b8",
"reps": 8,
"sets": 4
},
{
"_id": "5e05c5306e964f0a549469b7",
"reps": 10,
"sets": 3
},
{
"_id": "5e05c5306e964f0a549469b6",
"reps": 12,
"sets": 2
}
],
}
If we want to remove the exercises 5e05c5306e964f0a549469b8 and 5e05c5306e964f0a549469b6 for this 5e05c5306e964f0a549469b5 workout, we can send a PUT request with this body: (url must end something like this http://.../5e05c5306e964f0a549469b5)
{
"exerciseId": [
"5e05c5306e964f0a549469b8",
"5e05c5306e964f0a549469b6"
]
}
The response will be:
{
"_id": "5e05c5306e964f0a549469b5",
"exercises": [
{
"_id": "5e05c5306e964f0a549469b7",
"reps": 10,
"sets": 3
}
]
}
Hard to tell considering you're not saying what error you are getting, but my guess from looking at it is that you are comparing an ObjectId with a String, try to replace this line:
{ $pull: { exercises: { _id: item} } } )
with this:
{ $pull: { exercises: { _id: new ObjectId(item)} } } )
** EDIT **
you probably need to also convert the main ID you are searching for to an ObjectId:
Workout.findByIdAndUpdate( new ObjectId(req.params.workoutId),
{ $pull: { exercises: { _id: new ObjectId(item)} } } )

mongoose query array, with id array

I need to query entries in an array, the document looks like this:
{
"_id":"5d7b4ef6f691b71b5097e9cb",
"name":"1568362230828",
"commands":[
{
"_id":"5d7b4ef6f691b71b5097e9d1",
"name":"Command - 0"
},
{
"_id":"5d7b4ef6f691b71b5097e9d0",
"name":"Command - 1"
},
{
"_id":"5d7b4ef6f691b71b5097e9cf",
"name":"Command - 2"
},
{
"_id":"5d7b4ef6f691b71b5097e9ce",
"name":"Command - 3"
},
{
"_id":"5d7b4ef6f691b71b5097e9cd",
"name":"Command - 4"
},
{
"_id":"5d7b4ef6f691b71b5097e9cc",
"name":"Command - 5"
}
],
"__v":0
}
now i want to get all commands by there id:
model.find({
commands: {
_id: ["5d7b4ef6f691b71b5097e9cf", "5d7b4ef6f691b71b5097e9cf"] }})
Pseudo query, this does not work!
How must my query looks like ?!
const schema = new mongoose.Schema({
name: String,
commands: [{
name: String
}]
});
const model = mongoose.model('Endpoints', schema);
If you want to un-filter comments in comments only document then use this query
Endpoints.find({
commands: {
$elemMatch: {
_id: { $in: ["5d7b4ef6f691b71b5097e9cf", "5d7b4ef6f691b71b5097e9cf"] }
}
}
});
If you want to filter comments in comments
Endpoints.aggregate([
{
$project: {
items: {
$filter: {
input: "$commands",
as: "item",
cond: {
$in: [
"$$item._id",
["5d7b4ef6f691b71b5097e9cf", "5d7b4ef6f691b71b5097e9cf"]
]
}
}
}
}
}
])
or without aggregation
Endpoints.find(
{ commands:
{$elemMatch: {"_id": { $in: ["5d7b4ef6f691b71b5097e9d1"]}}}
},
{ 'commands.$': 1 }
)

Find object id in object ids array returns empty array using Mongoose

I have two Mongoose schemas:
var EmployeeSchema = new Schema({
name: String,
servicesProvided: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Service'
}]
});
var ServiceSchema = new Schema({
name: String
});
I'm trying to find employees who provide a specified service with the service ID I send into the http request. This is my code:
Employee
.find({
servicesProvided: req.params.service_id
})
.exec(function(err, employees) {
if (err) {
console.log(err);
res.send(err);
} else {
res.json(employees);
}
});
The problem is that this code returns an empty array and I don't know why. I've tried a lot of things like casting the service id to mongoose.Schema.Types.ObjectId but it doesn't work.
Any idea? I'm using Mongoose 3.8.39. Thanks!
In your EmployeeSchema, servicesProvided is an array, to filter employees by that field you should use $in operator:
var services = [req.params.service_id];
Employee.find({
servicesProvided: {
$in: services
}
}, ...
I think you need $elemMatch! From docs:
{ _id: 1, results: [ { product: "abc", score: 10 }, { product: "xyz", score: 5 } ] },
{ _id: 2, results: [ { product: "abc", score: 8 }, { product: "xyz", score: 7 } ] },
{ _id: 3, results: [ { product: "abc", score: 7 }, { product: "xyz", score: 8 } ] }
Search like:
db.survey.find({ results: { $elemMatch: { product: "xyz", score: { $gte: 8 } } } })
Results in:
{ "_id" : 3, "results" : [ { "product" : "abc", "score" : 7 }, { "product" : "xyz", "score" : 8 } ] }
But since you're doing a single query condition (look at the docs again) you can replace
db.survey.find(
{ results: { $elemMatch: { product: "xyz" } } }
)
with
db.survey.find(
{ "results.product": "xyz" }
)
So in your case it should be something like:
find({
'servicesProvided': ObjectId(req.params.service_id)
})

Resources