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

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).

Related

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

$set operator mongo deletes non existing keys?

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.

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.

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).

Resolving a ref inside of a MongoDB aggregate

I have a Product model object that has the following field in its schema:
category : { type: ObjectId, turnOn: false, ref: "category" }
It references a category model that has a title field in it:
var categorySchema = Schema({
title : { type: String }
});
I'm using the product.category property (which is of type ObjectId as shown above) in a MongoDB aggregate but really want the category.title property from the category model rather than _id in the final resultset.
The following code gets the job done, but you'll see that I'm having to do some looping at the end to "resolve" the title field for the given product.category (ObjectId). Is there anyway to do all of that within the aggregate? In other words, is there a way to get the category model object's title field in the groups that are returned rather than having to do the extra looping work? Based on posts I've researched I don't see a built-in way but wanted to double-check.
getProductsGroupedByCategory = function(callback) {
Category.find(function(err, cats) {
var aggregate = [
{
$group: {
_id: "$category",
products: {
$push: {
title: "$title",
authors: "$authors",
publishDate: "$publishDate",
description: "$description"
}
}
}
},
{
$sort: {
"_id": 1
}
}
];
Product.aggregate(aggregate, function(err, catProducts) {
//Grab name of category and associate with each group
//since we only have the category_id at this point
for (var i = 0; i<catProducts.length;i++) {
var catProduct = catProducts[i];
for (var j=0;j<cats.length;j++) {
if (catProduct._id.toString() === cats[j]._id.toString()) {
catProduct.category = cats[j].title;
}
}
};
callback(err, catProducts);
});
});
}, //more code follows
An example datum would be helpful along with what you need out of it. From What I understand you are looking to get the title in to the grouping criteria and that should be doing by having a compound grouping criteria i.e.
_id: {category: "$category", title: "$title"}
If the title is within an array, you should do unwind, group and then wind again to achieve the result.