Uploaded image for project: 'OpenMRS Core'
  1. OpenMRS Core
  2. TRUNK-2705

Improve concept searching when a concept contains multiple matched concept names

    XMLWordPrintable

Details

    Description

      Fix concept indexing so that if a concept has multiple concept names that include a common word that matches a search phrase then the concept name including the word with highest weight always gets selected to make the concept hit compete favorably with other concepts when sorting hits. Right now the one with the minimum conceptNameId wins which might not necessarily have the highest weight.

      To reproduce this:

      • Find a random concept to edit
      • Add UNIQUE NAME as a synonym and save
      • Edit the concept again and add UNIQUE as another synonym
      • Go to the find concept page and enter UNIQUE

      The name that gets displayed in the results will be UNIQUE NAME instead of UNIQUE and the reason for this is because UNIQUE NAME was added first so it has a lower concept name id, if you added the names in the opposite order, UNIQUE would get displayed.

      A possible solution is to make sure that during concept word creation, only one word with the highest weight ge
      ts stored in case multiple names contain the same word OR a concept word should hold a collection of names for a single concept in which it is contained, this will make it possible to pick the best concept name when executing the query. Use the test below to confirm that the fix works.

      @Test
      public void getConcepts_shouldReturnASearchResultWhoseConceptNameContainsAWordWithMoreWeight() throws Exception {
      	executeDataSet("org/openmrs/api/include/ConceptServiceTest-words.xml");
      	Concept conceptWithMultipleMatchingNames = conceptService.getConcept(3000);
      	//recalculate the weights just in case the logic for calculating the weights is changed
      	conceptService.updateConceptIndex(conceptWithMultipleMatchingNames);
      	conceptService.updateConceptIndex(conceptService.getConcept(4000));
      	List<ConceptSearchResult> searchResults = conceptService.getConcepts("trust", Collections
      		    .singletonList(Locale.ENGLISH), false, null, null, null, null, null, null, null);
      		
      	Assert.assertEquals(2, searchResults.size());
      	//the first concept is the one with a word with the highest weight
      	Assert.assertEquals(conceptWithMultipleMatchingNames, searchResults.get(0).getConcept());
      	//This test would only pass in case the name selected in the query happens to have a lower concept name id than the others.
      	//For conceptId=3000, its search result should ALWAYS match on 'TRUST ME' because it is shorter THAN 'TRUST ALWAYS'
      	//so it has a higher weight hence giving this concept a higher weight when being compared to other concept hits.
      	Assert.assertEquals(9998, searchResults.get(0).getConceptName().getConceptNameId().intValue());
      }
      

      Gliffy Diagrams

        Attachments

          Issue Links

            Activity

              People

                grace Grace Potma
                wyclif Wyclif Luyima
                Votes:
                9 Vote for this issue
                Watchers:
                11 Start watching this issue

                Dates

                  Created:
                  Updated:
                  Resolved:

                  Time Tracking

                    Estimated:
                    Original Estimate - 4 hours
                    4h
                    Remaining:
                    Remaining Estimate - Not Specified
                    Not Specified
                    Logged:
                    Time Spent - 3 hours Time Not Required
                    3h