@@ -59,6 +59,7 @@ func Upload(inDir string, replace bool) {
5959 }
6060 }
6161
62+ buildEvents (client , ctx )
6263}
6364
6465// Generic upload function to upload parsed JSON data to the Mongo database
@@ -167,3 +168,158 @@ func UploadData[T any](client *mongo.Client, ctx context.Context, fptr *os.File,
167168
168169 defer fptr .Close ()
169170}
171+
172+ // MongoDB aggregation run only when sections changes, instead of as a view where it's run for each query
173+ func buildEvents (client * mongo.Client , ctx context.Context ) {
174+ sections := getCollection (client , "sections" )
175+
176+ pipeline := mongo.Pipeline {
177+ //separate each meeting
178+ {{Key : "$unwind" , Value : "$meetings" }},
179+ //remove bad data
180+ {{Key : "$match" , Value : bson.D {
181+ {Key : "meetings.location.building" , Value : bson.D {{Key : "$ne" , Value : "No" }}},
182+ }}},
183+ //remove time from meeting start date
184+ {{Key : "$addFields" , Value : bson.D {
185+ {Key : "meetings.start_date" , Value : bson.D {
186+ {Key : "$dateTrunc" , Value : bson.D {
187+ {Key : "date" , Value : "$meetings.start_date" },
188+ {Key : "unit" , Value : "day" },
189+ }},
190+ }},
191+ }}},
192+ //add a field thats a list of all days the class occurs
193+ //by generating all days in semester and removing those that don't match MW for example
194+ {{Key : "$addFields" , Value : bson.D {
195+ {Key : "meeting_dates" , Value : bson.D {
196+ {Key : "$filter" , Value : bson.D {
197+ {Key : "input" , Value : bson.D {
198+ {Key : "$map" , Value : bson.D {
199+ {Key : "input" , Value : bson.D {
200+ {Key : "$range" , Value : bson.A {
201+ 0 ,
202+ bson.D {{Key : "$dateDiff" , Value : bson.D {
203+ {Key : "startDate" , Value : bson.D {{Key : "$toDate" , Value : "$meetings.start_date" }}},
204+ {Key : "endDate" , Value : bson.D {{Key : "$toDate" , Value : "$meetings.end_date" }}},
205+ {Key : "unit" , Value : "day" },
206+ }}},
207+ 1 ,
208+ }},
209+ }},
210+ {Key : "as" , Value : "offset" },
211+ {Key : "in" , Value : bson.D {
212+ {Key : "$dateAdd" , Value : bson.D {
213+ {Key : "startDate" , Value : bson.D {{Key : "$toDate" , Value : "$meetings.start_date" }}},
214+ {Key : "unit" , Value : "day" },
215+ {Key : "amount" , Value : "$$offset" },
216+ }},
217+ }},
218+ }},
219+ }},
220+ {Key : "as" , Value : "date" },
221+ {Key : "cond" , Value : bson.D {
222+ {Key : "$in" , Value : bson.A {
223+ bson.D {{Key : "$dayOfWeek" , Value : "$$date" }},
224+ bson.D {{Key : "$map" , Value : bson.D {
225+ {Key : "input" , Value : "$meetings.meeting_days" },
226+ {Key : "as" , Value : "day" },
227+ {Key : "in" , Value : bson.D {
228+ {Key : "$switch" , Value : bson.D {
229+ {Key : "branches" , Value : bson.A {
230+ bson.D {{Key : "case" , Value : bson.D {{Key : "$eq" , Value : bson.A {"$$day" , "Sunday" }}}}, {Key : "then" , Value : 1 }},
231+ bson.D {{Key : "case" , Value : bson.D {{Key : "$eq" , Value : bson.A {"$$day" , "Monday" }}}}, {Key : "then" , Value : 2 }},
232+ bson.D {{Key : "case" , Value : bson.D {{Key : "$eq" , Value : bson.A {"$$day" , "Tuesday" }}}}, {Key : "then" , Value : 3 }},
233+ bson.D {{Key : "case" , Value : bson.D {{Key : "$eq" , Value : bson.A {"$$day" , "Wednesday" }}}}, {Key : "then" , Value : 4 }},
234+ bson.D {{Key : "case" , Value : bson.D {{Key : "$eq" , Value : bson.A {"$$day" , "Thursday" }}}}, {Key : "then" , Value : 5 }},
235+ bson.D {{Key : "case" , Value : bson.D {{Key : "$eq" , Value : bson.A {"$$day" , "Friday" }}}}, {Key : "then" , Value : 6 }},
236+ bson.D {{Key : "case" , Value : bson.D {{Key : "$eq" , Value : bson.A {"$$day" , "Saturday" }}}}, {Key : "then" , Value : 7 }},
237+ }},
238+ {Key : "default" , Value : nil },
239+ }},
240+ }},
241+ }}},
242+ }},
243+ }},
244+ }},
245+ }},
246+ }}},
247+ //separate for each meeting data
248+ {{Key : "$unwind" , Value : "$meeting_dates" }},
249+ //remove data before today
250+ {{Key : "$match" , Value : bson.D {
251+ {Key : "$expr" , Value : bson.D {
252+ {Key : "$gte" , Value : bson.A {
253+ "$meeting_dates" ,
254+ bson.D {{Key : "$dateSubtract" , Value : bson.D {
255+ {Key : "startDate" , Value : bson.D {{Key : "$dateTrunc" , Value : bson.D {
256+ {Key : "date" , Value : "$$NOW" },
257+ {Key : "unit" , Value : "day" },
258+ }}}},
259+ {Key : "unit" , Value : "day" },
260+ {Key : "amount" , Value : 7 },
261+ }}},
262+ }},
263+ }},
264+ }}},
265+ //group into building > room hierarchy format
266+ {{Key : "$group" , Value : bson.D {
267+ {Key : "_id" , Value : bson.D {
268+ {Key : "date" , Value : "$meeting_dates" },
269+ {Key : "building" , Value : "$meetings.location.building" },
270+ {Key : "room" , Value : "$meetings.location.room" },
271+ }},
272+ {Key : "events" , Value : bson.D {
273+ {Key : "$push" , Value : bson.D {
274+ {Key : "section" , Value : "$_id" },
275+ {Key : "start_time" , Value : "$meetings.start_time" },
276+ {Key : "end_time" , Value : "$meetings.end_time" },
277+ }},
278+ }},
279+ }}},
280+ {{Key : "$group" , Value : bson.D {
281+ {Key : "_id" , Value : bson.D {
282+ {Key : "date" , Value : "$_id.date" },
283+ {Key : "building" , Value : "$_id.building" },
284+ }},
285+ {Key : "rooms" , Value : bson.D {
286+ {Key : "$push" , Value : bson.D {
287+ {Key : "room" , Value : "$_id.room" },
288+ {Key : "events" , Value : "$events" },
289+ }},
290+ }},
291+ }}},
292+ {{Key : "$group" , Value : bson.D {
293+ {Key : "_id" , Value : bson.D {
294+ {Key : "date" , Value : "$_id.date" },
295+ }},
296+ {Key : "buildings" , Value : bson.D {
297+ {Key : "$push" , Value : bson.D {
298+ {Key : "building" , Value : "$_id.building" },
299+ {Key : "rooms" , Value : "$rooms" },
300+ }},
301+ }},
302+ }}},
303+ //format date
304+ {{Key : "$project" , Value : bson.D {
305+ {Key : "_id" , Value : 0 },
306+ {Key : "date" , Value : bson.D {
307+ {Key : "$dateToString" , Value : bson.D {
308+ {Key : "format" , Value : "%Y-%m-%d" },
309+ {Key : "date" , Value : "$_id.date" },
310+ }},
311+ }},
312+ {Key : "buildings" , Value : 1 },
313+ }}},
314+ //set as events collection
315+ {{Key : "$out" , Value : "events" }},
316+ }
317+
318+ cursor , err := sections .Aggregate (ctx , pipeline )
319+ if err != nil {
320+ log .Panic (err )
321+ }
322+ defer cursor .Close (ctx )
323+
324+ log .Println ("Done aggregating events!" )
325+ }
0 commit comments