1010import org .apache .commons .collections4 .CollectionUtils ;
1111import org .apache .commons .lang3 .StringUtils ;
1212
13+ import org .bson .Document ;
1314import org .springframework .data .domain .Page ;
1415import org .springframework .data .domain .PageImpl ;
1516import org .springframework .data .domain .Pageable ;
@@ -99,12 +100,6 @@ && isNumeric(versionParts[2])) {
99100 // provided, we need to force this criteria search
100101 break ;
101102 case "cmsId" :
102- if (isNumeric (searchField )) {
103- int number = Integer .parseInt (searchField );
104- orConditions .add (Criteria .where ("measureSet.cmsId" ).is (number ));
105- } else {
106- orConditions .add (Criteria .where ("measureSet.cmsId" ).is (searchField ));
107- }
108103 break ;
109104 case "measure" :
110105 orConditions .add (
@@ -136,6 +131,8 @@ public Page<MeasureListDTO> searchMeasuresByCriteria(
136131 boolean filterByCurrentUser ,
137132 // TODO Remove parameter when either measureSearch or EditTestsOnVersionedMeasure is removed.
138133 String invocationSource ) {
134+ List <AggregationOperation > aggregationOperations = new ArrayList <>();
135+
139136 // join measure and measure_set to lookup owner and ACL info
140137 LookupOperation lookupOperation = getLookupOperation ();
141138
@@ -146,11 +143,17 @@ public Page<MeasureListDTO> searchMeasuresByCriteria(
146143 invocationSource .equals ("testCase" )
147144 ? appConfigService .isFlagEnabled (MadieFeatureFlag .EDIT_TESTS_ON_VERSIONED_MEASURES )
148145 : appConfigService .isFlagEnabled (MadieFeatureFlag .MEASURE_SEARCH );
146+
147+ aggregationOperations .add (lookupOperation );
148+ aggregationOperations .add (unwindOperation );
149+
149150 if (measureSearchCriteria != null ) {
150151 // If searchField is given and no filter is applied, then search for the searchField in
151152 // measureName and ecqmTitle
152153 if (StringUtils .isNotBlank (measureSearchCriteria .getSearchField ())
153154 && CollectionUtils .isEmpty (measureSearchCriteria .getOptionalSearchProperties ())) {
155+ aggregationOperations .add (addCmsIdDisplayField ());
156+
154157 String [] searchWords = measureSearchCriteria .getSearchField ().split ("\\ s+" );
155158 List <Criteria > wordCriteria = new ArrayList <>();
156159
@@ -161,12 +164,13 @@ public Page<MeasureListDTO> searchMeasuresByCriteria(
161164 new Criteria ()
162165 .orOperator (
163166 Criteria .where ("measureName" ).regex (".*" + word + ".*" , "i" ),
164- Criteria .where ("ecqmTitle" ).regex (".*" + word + ".*" , "i" )));
167+ Criteria .where ("ecqmTitle" ).regex (".*" + word + ".*" , "i" ),
168+ Criteria .where ("cmsIdDisplay" ).regex (".*" + word + ".*" , "i" )));
165169 }
166170 }
167171
168172 if (!wordCriteria .isEmpty ()) {
169- measureCriteria . andOperator (wordCriteria );
173+ aggregationOperations . add ( match ( new Criteria (). andOperator (wordCriteria )) );
170174 }
171175 }
172176 // if searchField and optional filters are provided, then search for searchField only in the
@@ -256,16 +260,20 @@ lookupOperation, unwindOperation, matchOperation, group("measureSetId")),
256260 .build ();
257261 ReplaceRootOperation replaceRootOperation = replaceRoot ("selectedDoc" );
258262
259- pipeline =
260- newAggregation (
261- lookupOperation ,
262- unwindOperation ,
263- matchMeasureSetIds ,
264- sortByVersionAndDraft ,
265- groupByMeasureSet ,
266- addHasAssociated ,
267- replaceRootOperation ,
268- facets );
263+ if (StringUtils .isNotBlank (measureSearchCriteria .getSearchField ())
264+ && measureSearchCriteria .getOptionalSearchProperties ().contains ("cmsId" )) {
265+ aggregationOperations .add (addCmsIdDisplayField ());
266+ aggregationOperations .add (matchCmsIdDisplay (measureSearchCriteria .getSearchField ()));
267+ }
268+
269+ aggregationOperations .add (matchMeasureSetIds );
270+ aggregationOperations .add (sortByVersionAndDraft );
271+ aggregationOperations .add (groupByMeasureSet );
272+ aggregationOperations .add (addHasAssociated );
273+ aggregationOperations .add (replaceRootOperation );
274+ aggregationOperations .add (facets );
275+
276+ pipeline = newAggregation (aggregationOperations );
269277
270278 } else {
271279 pipeline = newAggregation (lookupOperation , unwindOperation , matchOperation , facets );
@@ -295,6 +303,34 @@ lookupOperation, unwindOperation, matchOperation, group("measureSetId")),
295303 results .get (0 ).getQueryResults (), pageable , results .get (0 ).getCount ().size ());
296304 }
297305
306+ // Add string field called cmsIdDisplay. If model is QI-Core, append "FHIR" to measureSet
307+ // .cmsId, else only convert measureSet.cmsId to a string
308+ private AggregationOperation addCmsIdDisplayField () {
309+ return context ->
310+ new Document (
311+ "$addFields" ,
312+ new Document (
313+ "cmsIdDisplay" ,
314+ new Document (
315+ "$cond" ,
316+ List .of (
317+ new Document (
318+ "$regexMatch" ,
319+ new Document ("input" , "$model" ).append ("regex" , "QI-Core" )),
320+ new Document (
321+ "$concat" ,
322+ List .of (new Document ("$toString" , "$measureSet.cmsId" ), "FHIR" )),
323+ new Document ("$toString" , "$measureSet.cmsId" )))));
324+ }
325+
326+ // Case-insensitive contains search
327+ private AggregationOperation matchCmsIdDisplay (String input ) {
328+ return context ->
329+ new Document (
330+ "$match" ,
331+ new Document ("cmsIdDisplay" , new Document ("$regex" , input ).append ("$options" , "i" )));
332+ }
333+
298334 @ Override
299335 public List <LibraryUsage > findLibraryUsageByLibraryName (String name ) {
300336 LookupOperation lookupOperation = getLookupOperation ();
0 commit comments