From eb98ba0f6ef12caf06b6e47cb8b75d33fdec8381 Mon Sep 17 00:00:00 2001 From: Rithvik Nishad Date: Tue, 11 Jul 2023 08:58:07 +0000 Subject: [PATCH] Medibase: Drop littletable; instead store as list from ORM's `values_list` (#1443) * custom in memory search * as tuple * fix tests * remove db queryset reference after loading to in-memory * minor optimization * remove commented code * load to in-mem using ORM's `values_list` * Update care/facility/api/viewsets/prescription.py Co-authored-by: Aakash Singh --------- Co-authored-by: Aakash Singh --- care/facility/api/viewsets/prescription.py | 50 +++++++++------------- care/facility/static_data/medibase.py | 48 ++++++++++++--------- config/wsgi.py | 2 + 3 files changed, 50 insertions(+), 50 deletions(-) diff --git a/care/facility/api/viewsets/prescription.py b/care/facility/api/viewsets/prescription.py index ff1dfaa3a1..e6007e72c3 100644 --- a/care/facility/api/viewsets/prescription.py +++ b/care/facility/api/viewsets/prescription.py @@ -1,5 +1,3 @@ -from re import IGNORECASE - from django.shortcuts import get_object_or_404 from django_filters import rest_framework as filters from drf_spectacular.utils import extend_schema @@ -140,36 +138,30 @@ class MedibaseViewSet(ViewSet): permission_classes = (IsAuthenticated,) def serailize_data(self, objects): - result = [] - for object in objects: - if type(object) == tuple: - object = object[0] - result.append( - { - "id": object.external_id, - "name": object.name, - "type": object.type, - "generic": object.generic, - "company": object.company, - "contents": object.contents, - "cims_class": object.cims_class, - "atc_classification": object.atc_classification, - } - ) - return result + return [ + { + "id": x[0], + "name": x[1], + "type": x[2], + "generic": x[3], + "company": x[4], + "contents": x[5], + "cims_class": x[6], + "atc_classification": x[7], + } + for x in objects + ] def sort(self, query, results): exact_matches = [] partial_matches = [] - for result in results: - if type(result) == tuple: - result = result[0] - words = result.searchable.lower().split() + for x in results: + words = f"{x[1]} {x[3]} {x[4]}".lower().split() if query in words: - exact_matches.append(result) + exact_matches.append(x) else: - partial_matches.append(result) + partial_matches.append(x) return exact_matches + partial_matches @@ -178,10 +170,8 @@ def list(self, request): queryset = MedibaseMedicineTable - if request.GET.get("query", False): - query = request.GET.get("query").strip().lower() - queryset = queryset.where( - searchable=queryset.re_match(r".*" + query + r".*", IGNORECASE) - ) + if query := request.query_params.get("query"): + query = query.strip().lower() + queryset = [x for x in queryset if query in f"{x[1]} {x[3]} {x[4]}".lower()] queryset = self.sort(query, queryset) return Response(self.serailize_data(queryset[:15])) diff --git a/care/facility/static_data/medibase.py b/care/facility/static_data/medibase.py index 946360635f..fb5718c3df 100644 --- a/care/facility/static_data/medibase.py +++ b/care/facility/static_data/medibase.py @@ -1,26 +1,34 @@ -from littletable import Table +from django.db.models import CharField, TextField, Value +from django.db.models.functions import Coalesce from care.facility.models.prescription import MedibaseMedicine -MedibaseMedicineTable = Table("MedibaseMedicine") -medibase_objects = MedibaseMedicine.objects.all() - -for obj in medibase_objects: - MedibaseMedicineTable.insert( - { - "id": obj.id, - "external_id": obj.external_id, - "name": obj.name, - "type": obj.type, - "generic": obj.generic or "", - "company": obj.company or "", - "contents": obj.contents or "", - "cims_class": obj.cims_class or "", - "atc_classification": obj.atc_classification or "", - "searchable": f"{obj.name} {obj.generic} {obj.company}", - } +def load_medibase_in_memory(): + return ( + MedibaseMedicine.objects.all() + .annotate( + generic_pretty=Coalesce("generic", Value(""), output_field=CharField()), + company_pretty=Coalesce("company", Value(""), output_field=CharField()), + contents_pretty=Coalesce("contents", Value(""), output_field=TextField()), + cims_class_pretty=Coalesce( + "cims_class", Value(""), output_field=CharField() + ), + atc_classification_pretty=Coalesce( + "atc_classification", Value(""), output_field=TextField() + ), + ) + .values_list( + "external_id", + "name", + "type", + "generic_pretty", + "company_pretty", + "contents_pretty", + "cims_class_pretty", + "atc_classification_pretty", + ) ) -MedibaseMedicineTable.create_index("id", unique=True) -MedibaseMedicineTable.create_search_index("searchable") + +MedibaseMedicineTable = load_medibase_in_memory() diff --git a/config/wsgi.py b/config/wsgi.py index 835d5c2ece..9827d177fd 100644 --- a/config/wsgi.py +++ b/config/wsgi.py @@ -36,3 +36,5 @@ # Apply WSGI middleware here. # from helloworld.wsgi import HelloWorldApplication # application = HelloWorldApplication(application) + +from care.facility.static_data.medibase import MedibaseMedicineTable # noqa