Skip to content

Searching

Notas Hellout edited this page Mar 17, 2024 · 1 revision

Here we document the logic behind the searching functionality of the Patient app, and its evolution.

Patient name searching

Currently, only patient names are covered with some form of fuzzy searching functionality.

Initial implementation

The initial implementation is based on retrieving all patient names on the client-side:

export default withTracker(() => {
	Meteor.subscribe('patients');
	return {
                ...
		patients: Patients.find({}, {sort: {firstname: 1}}).fetch(),
                ...
	};
})(App);

Then filtering them on each query with the following function:

function getSuggestions(suggestions, inputValue) {
  let count = 0;
 
  return suggestions.filter(suggestion => {
    const keep = count < 5 && (!inputValue || suggestion.label.toLowerCase().includes(inputValue.toLowerCase()));
 
    if (keep) ++count;
 
    return keep;
  });
}

Obviously, this does not scale, and causes problems already with a few thousand patients.

Tweaking the first implementation

Support accent-agnostic search: #54:

Second implementation

The second implementation fixes issues inherent to a solution that creates and queries an index on the client-side.

See #7:

Third implementation

The third implementation fixes issues with the diverse ways in which the same name can be written or pronounced.

Brainstorm

  • Create artificial fields for all patients:
    • Should map vandenbr to (van, den, br)
    • Split attached names into parts
    • Split each part into all substrings of reasonable size
    • Store substrings into dedicated full-text search database
    • Full parts get a lot of points
    • Substrings get significantly less points
    • When querying first split query into the same parts
    • Only return cached fields for display
    • Maybe use a minimum threshold for matching score
  • Maybe do other kinds of search queries if full-text does not yield anything
    • For instance, maybe $regex: /^word/ on select fields for each word in query if not too many given

See #108:

See #90:

Tweaking the third implementation

Small changes that improve on the third implementation incrementally.

See:

  1. Break ties (#320): 564306afd5dd5b61913956d39405df797c836306
  2. Make lastname matches score higher: 4bcde59a027cadaea8717054b476eec829a1bfbe

Third implementation

The third implementation exploits uni-, bi-, and trigrams in a way that completely does away with a solution tailored to French and Flemish names, and, to some extent, the concepts of firstname and lastname.

See: #379: Fixed by #382.

UX concerns

  • #272: When using pre-filled queries, pre-fill with the exact string used for the request.
  • #107: When implementing a search functionality for the same items in different places, use the same logic to derive results, unless you clearly signal that it is different.

Ideal implementation

An ideal implementation would create an index that handles issues with oral transmission of names and typing mistakes: i.e. patient calls and gives their name using a specific pronunciation, doctor interprets the pronunciation depending on their linguistic background and types it in the system with additional potential typing mistakes. The system should have some level of cross-alphabet transliteration to allow searching for names written with a different alphabet than the searching alphabet phonetically.