$set operator mongo deletes non existing keys? - mongodb

When I run this command:
var news = {
_id: req.body.newsItemId,
images: {
_id: new ObjectId(),
src: result
}
}
Shop.findOneAndUpdate({
_id: ObjectId(req.body.shopId),
'news._id': ObjectId(req.body.newsItemId)},
{"$set": {
"news.$": news
}
}).exec(function(err, shop){
console.log(err, shop);
})
The non existing field from the news object are overwritten with empty values, so they are removed from the document.
news is a subdocument from shops. So a document looks like:
name: 'test shop',
email: 'email#shop',
products: [],
news: [
{
name: 'test news',
content: 'lorum ipsum....',
summary: 'lorum',
images: [
{
src: 'news/image_1.jpg',
}
]
}
]
After running the command above the news contains only a id and 1 image. I want only to overwrite the images array and leave the other properties alone. I have tried it with only images in the set, but then I get this error Mongoose update 'cannot use the part (..) to traverse the element , that is where the $ comes from.

Solved this by changing the code to this:
var images = [{
src: result
}]
Shop.findOneAndUpdate({
_id: ObjectId(req.body.shopId),
'news._id': ObjectId(req.body.newsItemId)},
{"$set": {
"news.$.images" : images
}
}).exec(function(err, shop){
console.log(err, shop);
return res.status(200).json({message: 'OK'});
})
So only the images object is overwritten now, and that is what I want.

Related

Prisma - adding new object into existing array and sorting it afterwards

I'm using Prisma in combination with MongoDB and this is how I currently update existing document:
await prisma.H2H.update({
where: { id: existingH2HDocument.id },
data: {
matches: {
push: {
matchId: editInput.matchId,
leagueId: editInput.leagueId,
date: editInput.date,
season: editInput.season,
},
},
},
})
Basically my model of the document looks like this:
id: 1234
matches: [
{
object1
},
{
object2
}
...
]
I'm adding new objects into the matches array, is there a way how to sort it during the update?
Using push adds them to the bottom but I need the newly added objects on the top(so basically an unshift).

Can't remove object in array using Mongoose

This has been extensively covered here, but none of the solutions seems to be working for me. I'm attempting to remove an object from an array using that object's id. Currently, my Schema is:
const scheduleSchema = new Schema({
//unrelated
_id: ObjectId
shifts: [
{
_id: Types.ObjectId,
name: String,
shift_start: Date,
shift_end: Date,
},
],
});
I've tried almost every variation of something like this:
.findOneAndUpdate(
{ _id: req.params.id },
{
$pull: {
shifts: { _id: new Types.ObjectId(req.params.id) },
},
}
);
Database:
Database Format
Within these variations, the usual response I've gotten has been either an empty array or null.
I was able slightly find a way around this and accomplish the deletion by utilizing the main _id of the Schema (instead of the nested one:
.findOneAndUpdate(
{ _id: <main _id> },
{ $pull: { shifts: { _id: new Types.ObjectId(<nested _id>) } } },
{ new: true }
);
But I was hoping to figure out a way to do this by just using the nested _id. Any suggestions?
The problem you are having currently is you are using the same _id.
Using mongo, update method allows three objects: query, update and options.
query object is the object into collection which will be updated.
update is the action to do into the object (add, change value...).
options different options to add.
Then, assuming you have this collection:
[
{
"_id": 1,
"shifts": [
{
"_id": 2
},
{
"_id": 3
}
]
}
]
If you try to look for a document which _id is 2, obviously response will be empty (example).
Then, if none document has been found, none document will be updated.
What happens if we look for a document using shifts._id:2?
This tells mongo "search a document where shifts field has an object with _id equals to 2". This query works ok (example) but be careful, this returns the WHOLE document, not only the array which match the _id.
This not return:
[
{
"_id": 1,
"shifts": [
{
"_id": 2
}
]
}
]
Using this query mongo returns the ENTIRE document where exists a field called shifts that contains an object with an _id with value 2. This also include the whole array.
So, with tat, you know why find object works. Now adding this to an update query you can create the query:
This one to remove all shifts._id which are equal to 2.
db.collection.update({
"shifts._id": 2
},
{
$pull: {
shifts: {
_id: 2
}
}
})
Example
Or this one to remove shifts._id if parent _id is equal to 1
db.collection.update({
"_id": 1
},
{
$pull: {
shifts: {
_id: 2
}
}
})
Example

What is the better implementation? MongoDb Query

I need some help with MongoDb. I need to check if an object exists in the database. If it's true, then I need to check if this object has a specific element into array (Products). If not, I need to create this object(Order) with this element(Cookie) in to array(Products).
Example data:
Order {
_id: ObjectId("580bc55f54101f1d18152d88"),
code: "AVG223424",
products: [
{
name: "Cookie"
},
{
name: "Soda"
}
]
}
Finally, what is the better implementation?
Assuming you are using a collection with the name 'Orders'
db
.Orders
.update({
code: "12345"
}, {
$addToSet: {
products: {
name: "Cookie"
}
},
$setOnInsert: {
code: "12345"
}
}, {
upsert: true
});
This query looks for a document with the same 'code,' and if found, will add the object '{name: "Cookie"}' if there is no other Object with the same key/val pairs. If the document does not exist, the '$setOnInsert' command will set the specified fields only if a new document is created.

fetching documents based on nested subdoc array value

I'm trying to get all documents in a collection based on a subdocument array values. This is my data structure in the collection i'm seeking:
{
_id: ObjectId('...'),
name: "my event",
members:
[
{
_id: ObjectId('...'),
name: "family",
users: [ObjectId('...'),ObjectId('...'),ObjectId('...')]
},
{
_id: ObjectId('...'),
name: "work",
users: [ObjectId('...'),ObjectId('...'),ObjectId('...')]
}
]
}
I should point out that the schema of these objects are defined like so:
Events:
{
name: { type: String },
members: {type: [{ type: ObjectId, ref: 'MemberGroup' }], default:[] }
}
MemberGroup:
{
name: { type: String },
users: [{type: mongoose.Schema.Types.ObjectId, ref: 'User'}]
}
and of course User is just an arbitrary object with an id.
What i'm trying to fetch: i want to retrieve all events which has a specific user id in its member.users field.
i'm not sure if its event possible in a single call but here is what i've tried:
var userId = new mongoose.Schema.ObjectId('57d9503ef10d5ffc08d6b8cc');
events.find({members: { $elemMatch : { users: { $in: [userId]} } }})
this syntax work but return no elements even though i know there are matching elements (using robomongo to visualize the db)
So after a long search in stackoverflow i came across the good answare here:
MongoDB: How to find out if an array field contains an element?
my query changed to the following which gave me my desired result:
var userId = new mongoose.Schema.ObjectId('57d9503ef10d5ffc08d6b8cc');
events.find({}, {members: { $elemMatch : { users: { $eq: userId} } }})
notice the use of the second find parameter to specify the query limit instead of the first one (which is odd)

Mongoose Update Instance from Nested Array

In Mongoose, lets say I have a User object pulled from MongoDB and that user has an array of Interests. Now I get an instance of one of that user's Interests.
var user = ...
var interest = ...
... //Make some changes to interest.
How do I update that Interest object (after making some changes to it) within the User array in the DB?
Edit
Here is my current code. It doesn't work and doesn't give an error.
User.update(
{
'_id': user._id,
'interests._id': interest._id
},
{
'$set': {
'interests.$.xyzProperty': interest.xyzProperty
}
},
function(err,obj){//some error checking}
);
If you set an if for each interest, you can access the interest by the $ operator.
user document
{
_id: ObectId('54b568531ef35a7c348f21f2'),
interests: [
{
_id: 12345,
title: 'Tacos',
description: 'I Love tacos'
},
{...},
{...},
]
}
If I know which interest sub document I want to update, I simply query it like so:
UserModel.find({_id: ObectId('54b568531ef35a7c348f21f2'), 'interests.i_d': 12345}).lean().exec(function (err, user) {
var interest = ... //find specific interest
interest.description = 'I love tacos... Like, a lot'.
UserModel.update(
{
_id: user._id,
'interests._id': interest._id
},
{
$set: {
'interests.$.description': interest.description
}
},
function (err, update) {
console.log(err, update);
}
);
});
This uses the $ positional operator and updates the specific sub document(or item in an array).