0

So I have this data structure below; it is basically a calendar of events that is set for an institution.

{
    "_id" : ObjectId("58485e8b630c3106ba4af558"),
    "institutionId" : "6z66TRkvmEpCkLsKH",
    "events" : [ 
        {
            "name" : "Christmas Day",
            "date" : ISODate("2016-12-25T21:21:11.874Z"),
            "holiday" : true
        }, 
        {
            "name" : "Independence Day",
            "date" : ISODate("2016-08-04T21:21:11.874Z"),
            "holiday" : true
        }, 
        {
            "name" : "My Birthday",
            "date" : ISODate("2016-06-20T21:21:11.874Z"),
            "holiday" : false
        }
    ],
    "createdAt" : ISODate("2016-12-07T19:10:03.351Z")
}

How do I get the array of just the holidays? (where holiday = true)

[ 
  {
      "name" : "Christmas Day",
      "date" : ISODate("2016-12-25T21:21:11.874Z"),
      "holiday" : true
  }, 
  {
      "name" : "Independence Day",
      "date" : ISODate("2016-08-04T21:21:11.874Z"),
      "holiday" : true
  }
]

Is this even the right approach at storing calendar events for an institution or should I have one event per document?

Thanks!

Chris F.
  • 493
  • 5
  • 17
  • refer this. it's similar - http://stackoverflow.com/questions/40896625/retrieve-field-value-from-array-of-sub-document/40897012?noredirect=1#comment69008123_40897012 – satish chennupati Dec 08 '16 at 15:01

1 Answers1

2

You can do this with aggregation pretty easily, there might also be a way to do it with $elemMatch in your projection.

db.collection.aggregate([
    // Create a separate document for each element in your array
    { $unwind: '$events' },
    // Match only on the holidays
    { $match: { 'events.holiday': true } },
    // Regroup to form the array with only the matching holidays
    { $group: { _id: null, holidays: { $addToSet: '$events' }  } },
    // Return only the holidays array, and not the _id
    { $project: { _id: 0, holidays: 1 } }
]);

Returns:

{ 
    "holidays" : [ 
        { 
            "name" : "Independence Day", 
            "date" : ISODate("2016-08-04T21:21:11.874Z"), 
            "holiday" : true 
        }, 
        { 
            "name" : "Christmas Day", 
            "date" : ISODate("2016-12-25T21:21:11.874Z"), 
            "holiday" : true 
        } 
    ] 
}
dyouberg
  • 2,206
  • 1
  • 11
  • 21
  • Thanks man! That's what I needed! – Chris F. Dec 08 '16 at 15:25
  • If you're unfamiliar with the concepts of aggregation, you should try running that same command with just the unwind, then the unwind and match, then the unwind + match + group, so you can see what each stage is doing. It's pretty cool and useful stuff! – dyouberg Dec 08 '16 at 15:31