2

I'm not well-versed with Mongo, so please excuse any ignorance here!

I want to add a seenMessages object to each user to determine which messages the user has read or not, as determined by the presence (or absence) of the message's unique ID, similar to something like:

// key in user object

seenMessages: {
  i3d4Fh87: 'i3d4Fh87',
  hfy7FDE9: 'hfy7FDE9',
}

The idea is to check the object for that key and, if unable to locate, the message is then considered 'unseen'. Upon viewing the message, the message ID is then added to the seenMessages object, at which point it will then be considered 'seen'.

Is there a way to achieve this in Mongo? Namely in the update stage as well as just creating a field as an empty object, Schema.Types.Mixed just seems to produce an array containing null.

S Q
  • 129
  • 7

2 Answers2

1

I'd use an array to store messages rather than an Object. Mongo has a ton of operators that work on arrays and adding a multikey index will make those operations speedy

  • to add an unseen message, you'd do something like db.myColl.update(query, {$addToSet: "seenMessages": messageId}}) (as long as the named field doesn't already exist, mongo will create it as an array)
  • to mark a message as read, you'd use $pull -- https://docs.mongodb.com/manual/reference/operator/update/pull/
  • and if you wanted to query for users who hadn't seen a message, you could have an index on user.seenMessages to make querying snappy

I know this doesn't exactly answer the original question, but using arbitrary keys in objects is a pattern that mongo doesn't have good tools to support. See MongoDB Query Help - query on values of any key in a sub-object for some more details

klhr
  • 3,300
  • 1
  • 11
  • 25
  • Thank you! I did end up going with an array because trying to use an object was too difficult, like you mentioned, but I'll go back through and update with recommendations to make it a faster lookup. Thanks again! – S Q Feb 15 '19 at 22:49
1

He's right and i'd upvote him if i had the rep lol. If you go through this with objects you can do it in the method from the last link in @willis's post, but it would be easier to use a findOne on an array and push up the id's as they are read, the value will not be in the checkIfRead: {type: Array} for example until it is put there with the findOneAndUpdate method. and you can put any logic you want for if the findOne comes up with no result because it doesnt exist.