updateOne always returning modifiedCount: 0

I’m having an issue where I’m attempting to update my document and the change is not being reflected. I suspect MongoDB is finding that my value is somehow the same even though I’ve changed it

var message = user.messages;

//should be an empty array for right now, can be something like [{ from: 'erin', to: 'erin', content: 'test' }]
//in the future

if (!message[otherPerson]) message[otherPerson] = [];
await message[otherPerson].push(msg);
//where msg is a msg object
//pushes message into new index

//updates messages with new data
const test = await User.updateOne({ usertag: person }, {
$set: { messages: message }
});
console.log(await test);

I’ve tried multiple formats of updating such as

User.updateOne({ usertag: person }, {
messages
});

where the messages variable is called message in the earlier example or

User.updateOne({ usertag: person }, {
$set: { messages }
});

and nothing seems to work

I will also mention that this is some rather old code that used to work pretty well. Has something changed in how MongoDB handles updates or am I doing something wrong?

Hi @Erin_Nyx,

Could you provide some sample documents?

What are the input documents and what are you expecting them to be updated to?

Lastly, you have specified the modifiedCount value to be 0. What is the matchedCount value? e.g.:

myFirstDatabase> db.coll.updateOne({a:2},{$set:{a:1}})
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 0,
  modifiedCount: 0,
  upsertedCount: 0
}

Note: No documents have matched, none have been updated in the above.

Regards,
Jason

Hi!
This will be my first time posting on here so I’m not really sure what format you want the sample document in but I’ll try my best!!

A sample document should look like this:

_id: ObjectID('NUMERICAL_ID')
usertag: 'unique_string'
email: 'unique_email'
displayName: 'string'
password: 'encrypted_pass'
admin: false
auth: false
messages: Array // should just look like var messages = [ ]

And matchedCount was 1. So it found the document with a filter to the unique usertag but didn’t update it.

Could you share the original code? This way we can compare to your

you have tried.

What you are doing is such a basic operation that I do not see

Note that the document is not updated if you supply the same value that was already there.

And reading the messages from the original document, and then using js code to do

following by a $set that sets all the old messages with the new msg you pushed is slow and error prone. A $push directly in the messages is both faster and safer.

2 Likes

Hi! I’m so sorry this thread has been so frustrating for everyone, but I appreciate all your help nonetheless!!

I did actually take your suggestion and use $push instead
It worked immediately and I’m sure the O(n) is MUCH better than what I was trying

If I may, however, I still have one more problem.

And this is my fault, I suppose I should have followed a tutorial or something
But I’d like to know if there’s anyway I can improve my data structure for a better implementation of my code.

See, the way I have it is in the document I have this Messages object
and in that object I will be storing ALL the messages a user has received.

the way I want to grab the messages I want for the user is with the following code
I have otherPerson (always going to be someone else) and user (always going to be user)

const messages = await User.findOne({ usertag: user }).lean().messages;
const res = messages.filter(m => (m.to == user || m.to == otherPerson) && (m.from == user || m.from == otherPerson));

where messages will be ALL the messages the user has ever sent and res will be an array of the messages I want to grab

However, it seems like the time complexity will get MUCH worse as n increases, is there any better way that I could have written my code? I mean, there’s always a better way I suppose but I’d like some tips if anyone’s willing to share :slight_smile: thanks!

  • Erin
3 Likes

Here, I would have done it the other way around. A user has greater control on the messages he sends compared to the messages he receives. So if Message is an object within the User, then I would store the message he sends.

But in both cases, you might end up with a massive array anti-pattern.

The approach to avoid the above would be to use

or

I like the bucket pattern to store old messages (ex: 1 bucket per month per user) and embedded array for recent both sent and received messages. Most of the time a User is more interested in the recent messages he sent and received. You have all that in one document. From time to time, he needs to access old messages, but I am pretty sure most people can tolerate a slower history access compared to current affairs.

I also like to keep messages in both sender and receiver current and history. A sender might want to remove a message from its sent list while the receiver really wants to keep it, or the other way around.

Definitively recommended. The mongodb university gives good and free courses.

3 Likes

Awesome! Thank you so much for all your help, I’ll definitely check those patterns out!

3 Likes

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.