Opal Search overview

The Opal Search backend is switchable using the settings value OPAL_SEARCH_BACKEND.

By default it will do a database query.

The backend takes in a dictionary with the following fields

{
      "queryType": either "Equals" or "Contains",
      "field": the label of the column that will be queried, e.g. Hospital Number,
      "query": the value to be queried, e.g. "1111",
      'combine': whether the query is 'and' or 'or' in conjunction with other dictionaries
      'column': the model to be queried e.g. 'demographics'
}

Customisation of search results

Search results are rendered with the template partials/_patient_summary_list.html. To improve performance of serializing multiple patients, the backend returns a patient summary for the current page of search results.

To add data to these results the application can implement a PatientSummary class.

The following example adds the title to the data returned to the front end.

from opal.core.search.queries import PatientSummary

class MyPatientSummary(PatientSummary):
    def __init__(self, patient, episodes):
        super()__init__(patient, episodes)
        self.patient_title = patient.demographics().title

    def to_json(self):
        as_json = super().to_json()
        as_json['title'] = self.patient_title
        return as_json


class MyCustomBackend(DatabaseQueryBackend):
    patient_summary_class = PatientSummary

# change settings.py to include OPAL_SEARCH_BACKEND='{path to my backend}.MyCustomBackend'

The raw serialised data is available to the front end in a .data property.

[[ result.data.title ]] [[ result.first_name ]] [[ result.surname ]] [[ result.hospitalNumber ]]

The Advanced search interface

The Opal advanced search interface at /#/extract allows users to specify rules by which to query for episodes.

By default this allows users to construct simple logical queries based on the values of any subrecord field.

The interface respects the types of fields - for instance using before/after for date fields or equals/contains for text fields.

This screen also allows users to download episode data for the cohort that matches the specified rules.

Custom Search Rules

These rules are extensible, allowing custom rules that perform more advanced queries to be inserted.

opal.core.search.SearchRule

Is a discoverable.

It is defined with a group of SearchRuleFields that appear like subrecord model fields in the front end.

The SearchRuleField has a query method that returns a list of Episodes.

The SearchRuleField must define a field_type, these then provide the following operators to the front end

field_type queryType
string equals, contains
date_time before, after
date before, after
boolean true, false
null_boolean true, false
many_to_many a list of the lookup list for this field
many_to_many_multi_select a multi select field, defined by the enum field from the rule

ie if you state the field is a string, the user will be provided with an equals/contains, which will be passed to the query as given_query["queryType"]

For example

class SomeField(SearchRuleField):
    display_name = "Some Field" # the display name of the field
    description = "A Description for the user to explain what this field means"
    field_type = "date_time" # what kind of filter that is offered, datetime will off before and after

    def query(self, given_query):
        return Episode.objects.all()


class MyCustomQuery(SearchRule):
    display_name = "My Custom Query"
    fields = (SomeField,)

Opal contains autocomplete search functionality for the navbar search box.

You can enable it with the setting OPAL_AUTOCOMPLETE_SEARCH (defaults to False).

# yourapp/settings.py
OPAL_AUTOCOMPLETE_SEARCH = True