0

I have my document structure in this way. Where i am storing all the events based occured with timestamps. My document look like this

[
  {
    "_id": {
      "$oid": "589341cff92be305c034cb5a"
    },
    "__v": 0,
    "name": "TV",
    "switch_event": [
      {
        "timestamp": 1486186277826,
        "event_type": "on"
      },
      {
        "timestamp": 1486272677826,
        "event_type": "off"
      },
      {
        "timestamp": 1486099877826,
        "event_type": "off"
      },
      {
        "timestamp": 1486186277826,
        "event_type": "on"
      },
      {
        "timestamp": 1486272677826,
        "event_type": "off"
      },
      {
        "timestamp": 1486099877826,
        "event_type": "off"
      }
    ]
  }
]

Now while querying for this document i am interested in only the events which occured today. So after querying for this i am writing projection query like this (for testing i kept timestamp > 0, which should give all events) -

SwitchAppliance.find({_id:"589341cff92be305c034cb5a"},{
                name:1,
                switch_event:{$elemMatch: {
                    timestamp: {
                                $gt:0
                    }
                }}
         },(err,results)=>{
            if(err) {console.log(err);return next({message: "Internal Server Error"});}
            return res.json(results);
        } ); 

But when i am getting result i am only getting one event object in the switch_event array- like this -

[
  {
    "_id": "589341cff92be305c034cb5a",
    "switch_event": [
      {
        "_id": "589567251c653a0890b8b1ef",
        "event_type": "on",
        "timestamp": 1486186277826
      }
    ],
    "name": "TV"
  }
]
5
  • Query projection $elemMatch only returns first matching element. You need to use aggregation to get all the matching elements. The schema doesn't seem optima for this use case though - just how big can these arrays get? Commented Feb 4, 2017 at 23:23
  • Real big.. i mean i am going to store every event occuring.Can u suggst something optimum, as in what else i should use. Commented Feb 5, 2017 at 18:29
  • That's a discussion more suited for MongoDB-user Google group but you can google the issues with storing ever-growing arrays inside a single document with MongoDB there are lots of write ups on this. Commented Feb 5, 2017 at 19:34
  • Thanks @AsyaKamsky, can you help me with aggregate query, i tried to write but it did not work. Commented Feb 6, 2017 at 5:04
  • Your schema won't scale if you keep all events inside an array so aggregation would just delay the issue. Commented Feb 6, 2017 at 13:02

2 Answers 2

0

You are querying Date.now() (timestamp or number) against new Date() (date object). A quick console test shows the following:

> typeof Date.now()
=> "number"
> typeof new Date()
=> "object"

So first off, I would change

var today = new Date();

to

var today = Date.now();

Then you are missing that "timestamp" does not hold a date value, but another Object with one Item with the key $date and a date as a value. Therefore your query should probably look similar to something like this:

var today = Date.now();
Item1.find({}).populate({
  path:"item1",
  select: {
    name:1,
    event:{
      $elemMatch: {
        timestamp: {
          date: {
            $gte:today
          }
        }
      }
    }
  }
})
Sign up to request clarification or add additional context in comments.

2 Comments

I appreciate it, but it does not work. i changed today to Date.now(), and also used your query(after replacing 'date' by '$date' ). But looks like these things are automatically understtod by mongoose and we need not do them. Anyway, point is, even after this query i am getting the same result, i am getting only one object appended in events array. like this - "event": [ { "_id": "589567251c653a0890b8b1ed", "event_type": "off", "timestamp": 1486099877826 } ]
I tried changing timestamp filed to number type then its only matter of comparison of numbers. it's still returning only one object in result document. Which is the last object.
0

Finally, found the key here.

Unwind empty array in mongodb

here @ivan.srb 's answers came handy. Finally ended up doing something like this -

SwitchAppliance.aggregate([
                {$match:{_id:{$in : switch_appliances_array}}},

                {$project:{
                   switch_no:1,switch_name:1,switch_type:1,appliance_type:1,sboard_id:1,current_status:1,
                   switch_event : { $cond : [ { $eq : [ "$switch_event", [] ] }, [ { timestamp : 0 , event_type:"off"} ], '$switch_event' ] } 
                }},
                {$unwind:"$switch_event"},

                {$match:{$or: [{"switch_event.timestamp":{$gt:now}},{ "switch_event.timestamp":0} ]}},

                {$group:{
                    _id:"$_id",
                    switch_no:{$first:"$switch_no"},
                    switch_type:{$first:"$switch_type"},
                    switch_name:{$first:"$switch_name"},
                    appliance_type:{$first:"$appliance_type"},
                    current_status:{$first:"$current_status"},
                    switch_events:{$push:"$switch_event"}
                }},

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.