@@ -149,15 +149,23 @@ class EventsFactory extends Factory {
149149 * @param {Number } skip - certain number of documents to skip
150150 * @param {'BY_DATE' | 'BY_COUNT' } sort - events sort order
151151 * @param {EventsFilters } filters - marks by which events should be filtered
152+ * @param {String } search - Search query
152153 *
153154 * @return {RecentEventSchema[] }
154155 */
155156 async findRecent (
156157 limit = 10 ,
157158 skip = 0 ,
158159 sort = 'BY_DATE' ,
159- filters = { }
160+ filters = { } ,
161+ search = ''
160162 ) {
163+ if ( typeof search !== 'string' ) {
164+ throw new Error ( 'Search parameter must be a string' ) ;
165+ }
166+
167+ const escapedSearch = search . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, '\\$&' ) ;
168+
161169 limit = this . validateLimit ( limit ) ;
162170
163171 switch ( sort ) {
@@ -184,71 +192,64 @@ class EventsFactory extends Factory {
184192 } ,
185193 ] ;
186194
187- /**
188- * If some events should be omitted, use alternative pipeline
189- */
190- if ( Object . values ( filters ) . length > 0 ) {
191- pipeline . push (
192- /**
193- * Lookup events object for each daily event
194- */
195- {
196- $lookup : {
197- from : 'events:' + this . projectId ,
198- localField : 'groupHash' ,
199- foreignField : 'groupHash' ,
200- as : 'event' ,
195+ const searchFilter = search . trim ( ) . length > 0
196+ ? {
197+ $or : [
198+ {
199+ 'event.payload.title' : {
200+ $regex : escapedSearch ,
201+ $options : 'i' ,
202+ } ,
201203 } ,
202- } ,
203- {
204- $unwind : '$event' ,
205- } ,
206- /**
207- * Match filters
208- */
209- {
210- $match : {
211- ...Object . fromEntries (
212- Object
213- . entries ( filters )
214- . map ( ( [ mark , exists ] ) => [ `event.marks.${ mark } ` , { $exists : exists } ] )
215- ) ,
204+ {
205+ 'event.payload.backtrace.file' : {
206+ $regex : escapedSearch ,
207+ $options : 'i' ,
208+ } ,
216209 } ,
210+ ] ,
211+ }
212+ : { } ;
213+
214+ const matchFilter = filters
215+ ? Object . fromEntries (
216+ Object
217+ . entries ( filters )
218+ . map ( ( [ mark , exists ] ) => [ `event.marks.${ mark } ` , { $exists : exists } ] )
219+ )
220+ : { } ;
221+
222+ pipeline . push (
223+ {
224+ $lookup : {
225+ from : 'events:' + this . projectId ,
226+ localField : 'groupHash' ,
227+ foreignField : 'groupHash' ,
228+ as : 'event' ,
217229 } ,
218- { $skip : skip } ,
219- { $limit : limit } ,
220- {
221- $group : {
222- _id : null ,
223- dailyInfo : { $push : '$$ROOT' } ,
224- events : { $push : '$event' } ,
225- } ,
230+ } ,
231+ {
232+ $unwind : '$event' ,
233+ } ,
234+ {
235+ $match : {
236+ ... matchFilter ,
237+ ... searchFilter ,
226238 } ,
227- {
228- $unset : 'dailyInfo.event' ,
229- }
230- ) ;
231- } else {
232- pipeline . push (
233- { $skip : skip } ,
234- { $limit : limit } ,
235- {
236- $group : {
237- _id : null ,
238- groupHash : { $addToSet : '$groupHash' } ,
239- dailyInfo : { $push : '$$ROOT' } ,
240- } ,
239+ } ,
240+ { $skip : skip } ,
241+ { $limit : limit } ,
242+ {
243+ $group : {
244+ _id : null ,
245+ dailyInfo : { $push : '$$ROOT' } ,
246+ events : { $push : '$event' } ,
241247 } ,
242- {
243- $lookup : {
244- from : 'events:' + this . projectId ,
245- localField : 'groupHash' ,
246- foreignField : 'groupHash' ,
247- as : 'events' ,
248- } ,
249- }
250- ) ;
251- }
248+ } ,
249+ {
250+ $unset : 'dailyInfo.event' ,
251+ }
252+ ) ;
252253
253254 const cursor = this . getCollection ( this . TYPES . DAILY_EVENTS ) . aggregate ( pipeline ) ;
254255
@@ -316,7 +317,7 @@ class EventsFactory extends Factory {
316317 } ) ;
317318
318319 /**
319- * Group events using 'groupByTimestamp :NNNNNNNN' key
320+ * Group events using 'groupingTimestamp :NNNNNNNN' key
320321 * @type {ProjectChartItem[] }
321322 */
322323 const groupedData = groupBy ( 'groupingTimestamp' ) ( dailyEvents ) ;
0 commit comments