0

Hi there I am having a MongoDB document in users collection:

{
   "_id": ObjectId("51d9534fc469880b338903eb"),
   "inbox": {
      "0": {},
      "1": {} ,
      "2": {} 
           ...
    },

}

According to requirement i need to check inbox every 5 minutes. So I am looking for:

  1. To find the length of inbox.
  2. Imagine my inbox lenght is 4 but 2 new messages came in, how would i get only those new messages.

After a bit of research i found that i can check if there are any new messages in my inbox using db.collection.find({ tags : { $size: 4 }}); , but now my question is how do i find those newly added messages. It would be really great if you can suggest a better way to get around this situation.

Thank you!

troy
  • 997
  • 4
  • 13
  • 27

2 Answers2

0

You should use the $slice operator to skip some items in your array:

db.collection.find({ tags : { $size : 4 } }, { inbox : { $slice : -4 } })

Check if your inbox field is really an array, because on your example it's a document.

Perhaps you should modified the query too, assuming the you have the length of your inbox, fetch for new messages will be:

var len = current_length; // comes from your app
var field = 'inbox.' + len;
// the query will check if the index "len" of inbox array exists
db.collection.find({ field : { $exists: true }, { inbox : { $slice : -len } }}

Check this question for more information about index querying: https://stackoverflow.com/a/15224544/1877296

Community
  • 1
  • 1
Miguel Cartagena
  • 2,576
  • 17
  • 20
0

First off, the best way to design the schema is to not use an object for inbox; you should be using an array.

Second, however, do you know what are new messages (i.e. 2 out of 4 messages are new)? I am going out on a limb stating that there is a read field which will be either true or false.

So what you are actually, most likely, asking is how to get all messages, sorted by send date, where read is false; alternatively you can also use a MongoDate ( http://php.net/manual/en/class.mongodate.php ) lastPullTime to keep track of it storign the value in the $_SESSION.

In this example we are going for the read field. I will also assume you have a sent date in ISODate() format called sent.

For this we can use the aggregation framework like so:

db.collection.aggregate([
    // Let's get our user
    {$match:{_id:ObjectId()}},

    // Now we want to unwind the inbox so we can operate on it
    {$unwind:'$inbox'},

    // Now we want only messages that are not read
    {$match: {'inbox.read':false}},

    // Now lets do our sort by newest
    {$sort: {'inbox.sent':-1}},

    // Now lets group them back up
    {$group: {_id:'$_id', inbox: {$addToSet:'$inbox'}}}
])

Or you can do it in PHP with asort on $doc['inbox']

Sammaye
  • 43,242
  • 7
  • 104
  • 146