MongoDB : mongoose findbyidandupdate condition not working - javascript

I want to update an array in a document where array is array of user object.
The problem is i don't want to add duplicates in this array ( not the same user more than one time).
what i do :
const updatedTopic = await Topic.findByIdAndUpdate(
// #ts-ignore
{ _id: id, 'votes.user': { $ne: req.user?._id.valueOf() } },
// #ts-ignore
{ $push: { votes: { year, comment, user: req.user } } },
{ new: true }
);
But this isn't working as you can see below :
{
"name": "Argomento 1",
"exam": {
"$oid": "62b71b9dcaf3e92ac568c729"
},
"slug": "argomento-1",
"user": {
"$oid": "62534e5798a11bcba35464f6"
},
"votes": [
{
"year": 2022,
"comment": "",
"user": {
"$oid": "62b22fd314c40b9067f84cc2" -> same user
},
"_id": {
"$oid": "62b8bbcf876b2d27570fdf86"
}
},
{
"year": 2022,
"comment": "",
"user": {
"$oid": "62b22fd314c40b9067f84cc2" -> same user
},
"_id": {
"$oid": "62b8bbd5876b2d27570fdf89"
}
}
],
"createdAt": {
"$date": {
"$numberLong": "1656168790097"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1656274729989"
}
},
"__v": 0
}

I don't know why but changing findByIdAndUpdate to findOneAndUpdate works fine.
Probably findByIdAndUpdate checks only the id condition.

Related

how to update a document use $ operator in mongodb

I'm trying to update a document, this is my code
I'm new to the mongodb I'm trying to update a nested array of object this is my query please tell me what is wrong with this query
Full data link ---> link
I tried below code but it's modifying entire seat_staus
db.seats.updateOne({"show_seats.showByDate.shows.showSeats._id" :ObjectId("62b16d9ff48ce9a5a15a79d3")}, {$set:{'show_seats.$[].showByDate.shows.$[].showSeats.$[].seat_status': true }})
db.seats.updateOne(
{ 'show_seats.$.showByDate.shows.$.showSeats.$._id': new ObjectId('62b0d1a72f155a7ad94cc831')},
{ $set:{
'show_seats.$[].showByDate.shows.$[].showSeats.$[].seat_status': false
}
}
)
and this is my data look like
{
"_id": {
"$oid": "62b0c3342f155a7ad94cc81c"
},
"totalShowByDay": "2",
"totalShowDays": 4,
"movieId": {
"$oid": "62b04c782828dd04f0d1c1ad"
},
"screenId": {
"$oid": "62b04b8e2828dd04f0d1c1ac"
},
"createdAt": 1655751476553,
"showId": {
"$oid": "62b0c3342f155a7ad94cc6db"
},
"show_seats": [{
"showByDate": {
"ShowDate": "2022-06-20",
"shows": [{
"showTime": "2022-06-20T10:00",
"showSeats": [{
"_id": {
"$oid": "62b0c3342f155a7ad94cc6dc"
},
"seat_number": "1",
"tag_name": "A",
"seat_status": false,
"user_id": false,
"price": "110",
"seats_category": "CLASSIC",
"show_time": "2022-06-20T10:00"
}, {
"_id": {
"$oid": "62b0c3342f155a7ad94cc6dd"
},
"seat_number": "2",
"tag_name": "A",
"seat_status": false,
"user_id": false,
"price": "110",
"seats_category": "CLASSIC",
"show_time": "2022-06-20T10:00"
finally I found the answer It's been two day that I stuck with this problem
db.seats.updateOne({"show_seats.showByDate.shows.showSeats._id" :ObjectId("62b16d9ff48ce9a5a15a79d6")},{$set:{"show_seats.$[].showByDate.shows.$[].showSeats.$[elem].seat_status":"my name is hrithik"}},{arrayFilters:[{"elem._id":ObjectId("62b16d9ff48ce9a5a15a79d6")}]})

How to change fields in object in array by id in mongoose partially?

How to change partially fields in an object in the array by id in mongoose?
I need to change the question and answer in one object 'cards'. How can I do that?
my strange attempt:
const game = await Game.findOneAndUpdate({ _id: cardId, cards._id: itemQuestionId }, { $set: {
cards.$.question: questionEdit,
cards.$.answer: answerEdit
}
}).lean()
Document structure -
{
"theme": "Игра престолов",
"cards": [{
"_id": {
"$oid": "60ae1e78956ee2a72057c87f"
},
"question": "Мастера монет Лорда Петра Баелиша также знали под каким именем?",
"answer": "Мизинец",
"points": 100
}, {
"_id": {
"$oid": "60ae1e78956ee2a72057c880"
},
"question": "Что изображено на гербе Ланнистеров?",
"answer": "Лев",
"points": 200
}, {
"_id": {
"$oid": "60ae1e78956ee2a72057c881"
},
"question": "Как зовут Лютоволка Джона Сноу?",
"answer": "Призрак",
"points": 300
}, {
"_id": {
"$oid": "60ae1e78956ee2a72057c882"
},
"question": "Кто был ответственным за создание Ночного Короля?",
"answer": "дети леса",
"points": 400
}, {
"_id": {
"$oid": "60ae1e78956ee2a72057c883"
},
"question": "Чёрно-белый дом служит ещё и храмом. А кому там поклоняются?",
"answer": "Многоликому",
"points": 500
}],
"__v": 0
}
On the internet I found solutions only for MongoDB, I need for Mongoose
I did it
app.patch("/api/v1/games/", async (req, res, next) => {
const {questionEdit, answerEdit, itemQuestionId, cardId} = req.body;
const game = await Game.findOneAndUpdate(
{_id: cardId},
{$set: {"cards.$[el].question": questionEdit } },
{
arrayFilters: [{ "el._id": itemQuestionId}],
new: true
}
)
.........................rest code
});

sort documents by their children in mongoose

I have a mongodb collection as follows:
[
{
"_id": { "$oid": "609b8f06a28f6728d19b486d" },
"user1": "609952c2b112741634d27d89",
"user2": "609b8202b5a389099cae3ce6",
"messages": [
{
"body": "Hello user 2",
"user": "609952c2b112741634d27d89",
"readed": true,
"created": { "$date": "2021-05-13T01:38:07.502Z" }
},
{
"body": "How old are you?",
"user": "609952c2b112741634d27d89",
"readed": false,
"created": "2021-05-13T01:40:07.502Z"
},
{
"body": "I am fine. Are you ready?",
"user": "609b8202b5a389099cae3ce6",
"readed": false,
"created": "2021-05-13T01:42:07.502Z"
},
{
"body": "Yes. Lighgui start",
"user": "609952c2b112741634d27d89",
"readed": false,
"created": "2021-05-13T01:38:50.502Z"
}
]
}
]
I want to sort chats that have messages up first how do I do that?
also if possible i would like to get the latest message of each chat and the number of messages with readed=false
You can use
$unwind to destructure the array
$sort to sort the array based on created of messages
$group to restructure the array
Here is the code
db.collection.aggregate([
{
$unwind: {
path: "$messages",
preserveNullAndEmptyArrays: true
}
},
{
"$sort": {"messages.created": 1 }
},
{
"$group": {
"_id": "$_id",
user1: { $first: "$user1" },
user2: { $first: "$user2" },
"messages": { "$push": "$messages" }
}
}
])
Working Mongo playground

MongoDb return both matched results and matched results on subdocument

Hello i am trying to get my database to return both matched and empty results on a sub-document.
I am joining two tables using aggregate and lookup, below is the code
db.collection.aggregate([
{
$addFields: {
cut_off_date: { $toDate: "$shipment_cutoff_date" },
},
},
{
$lookup: {
from: "updates",
localField: "_id",
foreignField: "shipment_id",
as: "updates",
},
},
{
$match: {
"updates.description": { $ne: "All updates completed" },
},
},
]);
Challenge is i am trying to get All rows where all updates have been completed as well as all empty updates. If i remove the match parameters i get all the results including where the updates have been completed and i am trying to avoid doing a foreach after getting all my results.
Here is a snippet of the result without the match
{
"_id": "609927e31233700004370cfb",
"title": "Hello World",
"createdAt": "2021-05-10T12:32:35.799Z",
"updatedAt": "2021-05-10T15:58:59.149Z",
"updates": []
},
{
"_id": "60940ad73ced476b2d0b3626",
"createdAt": "2021-05-06T15:27:19.814Z",
"updatedAt": "2021-05-10T12:49:08.167Z",
"updates": [
{
"_id": "60952c0ed31c6283f302eb23",
"post_id": "60940ad73ced476b2d0b3626",
"description": "This is an update description",
"createdAt": "2021-05-07T12:01:18.815Z",
"updatedAt": "2021-05-07T12:01:18.815Z",
},
]
},
{
"_id": "60940ad73ced476b2d0b3626",
"createdAt": "2021-05-06T15:27:19.814Z",
"updatedAt": "2021-05-10T12:49:08.167Z",
"updates": [
{
"_id": "60952c0ed31c6283f302eb23",
"post_id": "60940ad73ced476b2d0b3626",
"description": "All updates completed",
"createdAt": "2021-05-07T12:01:18.815Z",
"updatedAt": "2021-05-07T12:01:18.815Z",
},
]
}
Here is a snippet of what i will like to achieve after the match
{
"_id": "609927e31233700004370cfb",
"title": "Hello World",
"createdAt": "2021-05-10T12:32:35.799Z",
"updatedAt": "2021-05-10T15:58:59.149Z",
"updates": []
},
{
"_id": "60940ad73ced476b2d0b3626",
"createdAt": "2021-05-06T15:27:19.814Z",
"updatedAt": "2021-05-10T12:49:08.167Z",
"updates": [
{
"_id": "60952c0ed31c6283f302eb23",
"post_id": "60940ad73ced476b2d0b3626",
"description": "This is an update description",
"createdAt": "2021-05-07T12:01:18.815Z",
"updatedAt": "2021-05-07T12:01:18.815Z",
},
]
},
I am trying to get the results without the section where update description is not "All updates completed
Any help here please, MondoDb version is 4+
You can use $filter
$facet to categorize incoming doucment into two. 1. updates == empty array and 2. update != empty array
$redact use to keep or eliminate the document based on the condition we give
$concatArray to combined to both arrays which were produced after $facet
$unwind to deconstruct the array
$replaceRoot to make to root
He is the script
db.collection.aggregate([
{
"$facet": {
"emptyUpdates": [
{
"$match": {
$expr: { $eq: [ "$updates", [] ] }
}
}
],
"withoutUpdate": [
{
"$match": {
$expr: { $ne: [ "$updates", [] ] }
}
},
{
"$redact": {
"$cond": [
{
"$anyElementTrue": {
"$filter": {
"input": "$updates",
"cond": {
$eq: [ "$$this.description","All updates completed" ]
}
}
}
},
"$$PRUNE",
"$$KEEP",
]
}
}
]
}
},
{
"$project": {
combined: {
"$concatArrays": ["$emptyUpdates", "$withoutUpdate" ]
}
}
},
{ "$unwind": "$combined" },
{
"$replaceRoot": {"newRoot": "$combined" }
}
])
Working Mongo playground
Let me know anything goes wrong

how to filter data based on range of date in mongodb

[{
"_id": {
"$oid": "5d7a76c94c3c8c05618cef58"
},
"title": "hello",
"date": {
"$date": "2019-06-07T07:22:00.000Z"
},
"__v": 0
}, {
"_id": {
"$oid": "5d7a7809ef31980615ed3756"
},
"title": "hello",
"date": {
"$date": "2019-06-08T07:22:00.000Z"
},
"__v": 0
}, {
"_id": {
"$oid": "5d7a78e712c75706a3fdb025"
},
"title": "hello6",
"date": {
"$date": "2019-07-19T08:22:00.000Z"
},
"__v": 0
}, {
"_id": {
"$oid": "5d7a78e712c75706a3fdb025"
},
"title": "hello7",
"date": {
"$date": "2019-07-03T08:22:00.000Z"
},
"__v": 0
}]
I am storing my data in mongodb using mongoose like this I am trying to filter my data using mongoose
I want all document from date 2019-07-01 to 2019-07-31.can we do this filter on mongoose in mongoDB
expected output
[
{
"_id": {
"$oid": "5d7a78e712c75706a3fdb025"
},
"title": "hello6",
"date": {
"$date": "2019-07-19T08:22:00.000Z"
},
"__v": 0
}, {
"_id": {
"$oid": "5d7a78e712c75706a3fdb025"
},
"title": "hello7",
"date": {
"$date": "2019-07-03T08:22:00.000Z"
},
"__v": 0
}
]
here is my code
https://codesandbox.io/s/lively-tree-hd0fo
app.get("/saveData", async () => {
try {
var blog = new BlogPostModel({
title: "hello6",
date: "19-Jul-2019 08:22"
});
console.log("before save");
let saveBlog = await blog.save(); //when fail its goes to catch
console.log(saveBlog); //when success it print.
console.log("saveBlog save");
} catch (error) {
console.log(error);
}
});
You can use MongoDB's $gte (greater than or equal to) and $lte (lower than or equal to):
blog.find({ date: { $gte: '2019-07-01', $lte: '2019-07-31' } });

Categories