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"
  }
]
Daga Arihant
  • 464
  • 4
  • 19
  • 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? – Asya Kamsky Feb 04 '17 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. – Daga Arihant Feb 05 '17 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. – Asya Kamsky Feb 05 '17 at 19:34
  • Thanks @AsyaKamsky, can you help me with aggregate query, i tried to write but it did not work. – Daga Arihant Feb 06 '17 at 05:04
  • Your schema won't scale if you keep all events inside an array so aggregation would just delay the issue. – Asya Kamsky Feb 06 '17 at 13:02

2 Answers2

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
          }
        }
      }
    }
  }
})
The F
  • 3,647
  • 1
  • 20
  • 28
  • 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 } ] – Daga Arihant Feb 04 '17 at 05:43
  • 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. – Daga Arihant Feb 04 '17 at 05:43
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"}
                }},
Community
  • 1
  • 1
Daga Arihant
  • 464
  • 4
  • 19