Repository: cancervariants/therapy-normalization (language: python)

Issue:
Api update
 * Update query methods API to be consistent with other normalizers
 * Also clean up a bunch of little test messes
 * Pin ipython to resolve security vulnerability


Discussion / hints:

Fix patch:
diff --git a/Pipfile b/Pipfile
index f0f10bd1..9b6e7c71 100644
--- a/Pipfile
+++ b/Pipfile
@@ -5,7 +5,7 @@ verify_ssl = true
 
 [packages]
 pydantic = ">=1.8.2"
-fastapi = ">=0.65.2"
+fastapi = ">=0.72.0"
 urllib3 = ">=1.26.5"
 uvicorn = "*"
 click = "*"
@@ -13,7 +13,7 @@ lxml = ">=4.6.5"
 boto3 = "*"
 cython = "*"
 owlready2 = "*"
-pyparsing = "==2.4.7"
+pyparsing = "*"
 rdflib = "*"
 uvloop = "*"
 websockets = ">=9.1"
@@ -23,7 +23,7 @@ wikibaseintegrator = "==0.11.0"
 ipykernel = "*"
 bs4 = "*"
 pyyaml = "*"
-disease-normalizer = ">=0.2.11"
+disease-normalizer = ">=0.2.12"
 "ga4gh.vrsatile.pydantic" = ">=0.0.5"
 chembl-downloader = "*"
 bioversions = ">=0.4.3"
@@ -39,6 +39,7 @@ flake8-docstrings = "*"
 flake8-quotes = "*"
 flake8-import-order = "*"
 flake8-annotations = "*"
+ipython = ">=7.31.1"
 jupyterlab = "*"
 civicpy = "*"
 mypy = "*"
diff --git a/requirements-dev.txt b/requirements-dev.txt
index f5dfc18b..0e73811d 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -10,72 +10,74 @@
 
 -i https://pypi.org/simple
 -e .
-anyio==3.4.0; python_full_version >= '3.6.2'
+anyio==3.5.0; python_full_version >= '3.6.2'
 appnope==0.1.2; platform_system == 'Darwin'
 argon2-cffi-bindings==21.2.0; python_version >= '3.6'
 argon2-cffi==21.3.0; python_version >= '3.6'
-asgiref==3.4.1; python_version >= '3.6'
-attrs==21.2.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
+asgiref==3.5.0; python_version >= '3.7'
+asttokens==2.0.5
+attrs==21.4.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
 babel==2.9.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
 backcall==0.2.0
 backoff==1.11.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
 backports-datetime-fromisoformat==1.0.0
-backports.entry-points-selectable==1.1.1; python_version >= '2.7'
 beautifulsoup4==4.10.0; python_version >= '3.1'
-bioregistry==0.4.26; python_version >= '3.6'
+bioregistry==0.4.48; python_version >= '3.6'
 bioversions==0.4.4
+black==21.12b0; python_full_version >= '3.6.2'
 bleach==4.1.0; python_version >= '3.6'
-boto3==1.20.23
-botocore==1.23.23; python_version >= '3.6'
+boto3==1.20.43
+botocore==1.23.43; python_version >= '3.6'
 bs4==0.0.1
 cachier==1.5.4
 certifi==2021.10.8
 cffi==1.15.0
 cfgv==3.3.1; python_full_version >= '3.6.1'
-charset-normalizer==2.0.9; python_version >= '3'
-chembl-downloader==0.1.2
+charset-normalizer==2.0.10; python_version >= '3'
+chembl-downloader==0.2.1
 civicpy==1.1.3
 click-default-group==1.2.2
 click==8.0.3
-coverage[toml]==6.2; python_version >= '3.6'
-cython==0.29.25
+coverage[toml]==6.3; python_version >= '3.7'
+cython==0.29.26
 dataclasses-json==0.5.6; python_version >= '3.6'
 debugpy==1.5.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
-decorator==5.1.0; python_version >= '3.5'
+decorator==5.1.1; python_version >= '3.5'
 defusedxml==0.7.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
 deprecation==2.1.0
-disease-normalizer==0.2.11
+disease-normalizer==0.2.12
 distlib==0.3.4
 entrypoints==0.3; python_version >= '2.7'
-fastapi==0.70.1
-filelock==3.4.0; python_version >= '3.6'
+executing==0.8.2
+fastapi==0.73.0
+filelock==3.4.2; python_version >= '3.7'
 flake8-annotations==2.7.0
 flake8-docstrings==1.6.0
 flake8-import-order==0.18.1
 flake8-quotes==3.3.1
 flake8==4.0.1
 ga4gh.vrsatile.pydantic==0.0.6
-h11==0.12.0; python_version >= '3.6'
+h11==0.13.0; python_version >= '3.6'
 httptools==0.3.0
-identify==2.4.0; python_full_version >= '3.6.1'
+identify==2.4.5; python_version >= '3.7'
 idna==3.3; python_version >= '3.5'
 iniconfig==1.1.1
-ipykernel==6.6.0
+ipykernel==6.7.0
 ipython-genutils==0.2.0
-ipython==7.30.1; python_version >= '3.7'
+ipython==8.0.1; python_version >= '3.8'
 isodate==0.6.1
 jedi==0.18.1; python_version >= '3.6'
 jinja2==3.0.3; python_version >= '3.6'
 jmespath==0.10.0; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'
 json5==0.9.6
-jsonschema==4.2.1; python_version >= '3.7'
-jupyter-client==7.1.0; python_full_version >= '3.6.1'
+jsonschema==4.4.0; python_version >= '3.7'
+jupyter-client==7.1.2; python_full_version >= '3.6.1'
 jupyter-core==4.9.1; python_version >= '3.6'
-jupyter-server==1.13.1; python_version >= '3.6'
+jupyter-server==1.13.4; python_version >= '3.7'
 jupyterlab-pygments==0.1.2
-jupyterlab-server==2.9.0; python_version >= '3.6'
-jupyterlab==3.2.5
-lxml==4.6.5
+jupyterlab-server==2.10.3; python_version >= '3.6'
+jupyterlab==3.2.8
+lxml==4.7.1
 markupsafe==2.0.1; python_version >= '3.6'
 marshmallow-enum==1.5.1
 marshmallow==3.14.1; python_version >= '3.6'
@@ -85,82 +87,86 @@ mistune==0.8.4
 more-click==0.0.6; python_version >= '3.6'
 mwoauth==0.3.7
 mypy-extensions==0.4.3
-mypy==0.910
-nbclassic==0.3.4; python_version >= '3.6'
-nbclient==0.5.9; python_full_version >= '3.6.1'
-nbconvert==6.3.0; python_version >= '3.7'
+mypy==0.931
+nbclassic==0.3.5; python_version >= '3.6'
+nbclient==0.5.10; python_version >= '3.7'
+nbconvert==6.4.0; python_version >= '3.7'
 nbformat==5.1.3; python_version >= '3.5'
 nest-asyncio==1.5.4; python_version >= '3.5'
 networkx==2.6.3; python_version >= '3.7'
 nodeenv==1.6.0
-notebook==6.4.6; python_version >= '3.6'
-numpy==1.21.4; python_version < '3.10' and platform_machine != 'aarch64' and platform_machine != 'arm64'
+notebook==6.4.8; python_version >= '3.6'
+numpy==1.22.1; python_version < '3.10' and platform_machine != 'aarch64' and platform_machine != 'arm64'
 oauthlib==3.1.1; python_version >= '3.6'
 obonet==0.3.0; python_version >= '3.5'
-owlready2==0.35
+owlready2==0.36
 packaging==21.3; python_version >= '3.6'
-pandas==1.3.5; python_full_version >= '3.7.1'
+pandas==1.4.0; python_version >= '3.8'
 pandocfilters==1.5.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
 parso==0.8.3; python_version >= '3.6'
+pathspec==0.9.0
 pathtools==0.1.2
 pexpect==4.8.0; sys_platform != 'win32'
 pickleshare==0.7.5
-platformdirs==2.4.0; python_version >= '3.6'
+platformdirs==2.4.1; python_version >= '3.7'
 pluggy==1.0.0; python_version >= '3.6'
 portalocker==2.3.2
-pre-commit==2.16.0
-prometheus-client==0.12.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
+pre-commit==2.17.0
+prometheus-client==0.13.0; python_version >= '3.6'
 prompt-toolkit==3.0.24; python_full_version >= '3.6.2'
 ptyprocess==0.7.0
+pure-eval==0.2.2
 py==1.11.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
 pycodestyle==2.8.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
 pycparser==2.21; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
-pydantic==1.8.2
+pydantic==1.9.0
 pydocstyle==6.1.1; python_version >= '3.6'
 pyflakes==2.4.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
-pygments==2.10.0; python_version >= '3.5'
+pygments==2.11.2; python_version >= '3.5'
 pyjwt==1.7.1
 pyparsing==2.4.7
-pyrsistent==0.18.0; python_version >= '3.6'
+pyrsistent==0.18.1; python_version >= '3.7'
 pysam==0.18.0
-pystow==0.2.6
+pystow==0.3.1
 pytest-cov==3.0.0
 pytest==6.2.5
 python-dateutil==2.8.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
 pytz==2021.3
 pyyaml==6.0
 pyzmq==22.3.0; python_version >= '3.6'
-rdflib==6.0.2
+rdflib==6.1.1
 requests-ftp==0.3.1
 requests-oauthlib==1.3.0
-requests==2.26.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'
+requests==2.27.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'
 s3transfer==0.5.0; python_version >= '3.6'
 send2trash==1.8.0
-setuptools==59.6.0; python_version >= '3.6'
+setuptools==60.5.0; python_version >= '3.7'
 simplejson==3.17.6; python_version >= '2.5' and python_version not in '3.0, 3.1, 3.2, 3.3'
 six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
 sniffio==1.2.0; python_version >= '3.5'
 snowballstemmer==2.2.0
 soupsieve==2.3.1; python_version >= '3.6'
-starlette==0.16.0; python_version >= '3.6'
+stack-data==0.1.4
+starlette==0.17.1; python_version >= '3.6'
 tabulate==0.8.9
 terminado==0.12.1; python_version >= '3.6'
 testpath==0.5.0; python_version >= '3.5'
 toml==0.10.2; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'
-tomli==1.2.2; python_version >= '3.6'
+tomli==1.2.3; python_version >= '3.6'
 tornado==6.1; python_version >= '3.5'
-tox==3.24.4
+tox==3.24.5
 tqdm==4.62.3; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
 traitlets==5.1.1; python_version >= '3.7'
-types-pyyaml==6.0.1
-types-requests==2.26.1
+types-pyyaml==6.0.3
+types-requests==2.27.7
+types-urllib3==1.26.7
 typing-extensions==4.0.1
 typing-inspect==0.7.1
-urllib3==1.26.7
-uvicorn==0.16.0
+urllib3==1.26.8
+uvicorn==0.17.0.post1
 uvloop==0.16.0
 vcfpy==0.13.3
-virtualenv==20.10.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
+virtualenv==20.13.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
 watchdog==2.1.6; python_version >= '3.6'
 wcwidth==0.2.5
 webencodings==0.5.1
diff --git a/requirements.txt b/requirements.txt
index 607016b0..a0908aff 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -6,42 +6,45 @@
 #
 
 -i https://pypi.org/simple
-anyio==3.4.0; python_full_version >= '3.6.2'
+anyio==3.5.0; python_full_version >= '3.6.2'
 appnope==0.1.2; platform_system == 'Darwin'
-asgiref==3.4.1; python_version >= '3.6'
+asgiref==3.5.0; python_version >= '3.7'
+asttokens==2.0.5
 backcall==0.2.0
 backoff==1.11.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
 beautifulsoup4==4.10.0; python_version >= '3.1'
-bioregistry==0.4.26; python_version >= '3.6'
+bioregistry==0.4.48; python_version >= '3.6'
 bioversions==0.4.4
-boto3==1.20.23
-botocore==1.23.23; python_version >= '3.6'
+black==21.12b0; python_full_version >= '3.6.2'
+boto3==1.20.43
+botocore==1.23.43; python_version >= '3.6'
 bs4==0.0.1
 cachier==1.5.4
 certifi==2021.10.8
-charset-normalizer==2.0.9; python_version >= '3'
-chembl-downloader==0.1.2
+charset-normalizer==2.0.10; python_version >= '3'
+chembl-downloader==0.2.1
 click-default-group==1.2.2
 click==8.0.3
-cython==0.29.25
+cython==0.29.26
 dataclasses-json==0.5.6; python_version >= '3.6'
 debugpy==1.5.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
-decorator==5.1.0; python_version >= '3.5'
-disease-normalizer==0.2.11
+decorator==5.1.1; python_version >= '3.5'
+disease-normalizer==0.2.12
 entrypoints==0.3; python_version >= '2.7'
-fastapi==0.70.1
+executing==0.8.2
+fastapi==0.73.0
 ga4gh.vrsatile.pydantic==0.0.6
-h11==0.12.0; python_version >= '3.6'
+h11==0.13.0; python_version >= '3.6'
 httptools==0.3.0
 idna==3.3; python_version >= '3.5'
-ipykernel==6.6.0
-ipython==7.30.1; python_version >= '3.7'
+ipykernel==6.7.0
+ipython==8.0.1; python_version >= '3.8'
 isodate==0.6.1
 jedi==0.18.1; python_version >= '3.6'
 jmespath==0.10.0; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'
-jupyter-client==7.1.0; python_full_version >= '3.6.1'
+jupyter-client==7.1.2; python_full_version >= '3.6.1'
 jupyter-core==4.9.1; python_version >= '3.6'
-lxml==4.6.5
+lxml==4.7.1
 marshmallow-enum==1.5.1
 marshmallow==3.14.1; python_version >= '3.6'
 matplotlib-inline==0.1.3; python_version >= '3.5'
@@ -50,41 +53,46 @@ mwoauth==0.3.7
 mypy-extensions==0.4.3
 nest-asyncio==1.5.4; python_version >= '3.5'
 oauthlib==3.1.1; python_version >= '3.6'
-owlready2==0.35
+owlready2==0.36
 parso==0.8.3; python_version >= '3.6'
+pathspec==0.9.0
 pathtools==0.1.2
 pexpect==4.8.0; sys_platform != 'win32'
 pickleshare==0.7.5
+platformdirs==2.4.1; python_version >= '3.7'
 portalocker==2.3.2
 prompt-toolkit==3.0.24; python_full_version >= '3.6.2'
 ptyprocess==0.7.0
-pydantic==1.8.2
-pygments==2.10.0; python_version >= '3.5'
+pure-eval==0.2.2
+pydantic==1.9.0
+pygments==2.11.2; python_version >= '3.5'
 pyjwt==1.7.1
 pyparsing==2.4.7
-pystow==0.2.6
+pystow==0.3.1
 python-dateutil==2.8.2; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
 pyyaml==6.0
 pyzmq==22.3.0; python_version >= '3.6'
-rdflib==6.0.2
+rdflib==6.1.1
 requests-ftp==0.3.1
 requests-oauthlib==1.3.0
-requests==2.26.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'
+requests==2.27.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'
 s3transfer==0.5.0; python_version >= '3.6'
-setuptools==59.6.0; python_version >= '3.6'
+setuptools==60.5.0; python_version >= '3.7'
 simplejson==3.17.6; python_version >= '2.5' and python_version not in '3.0, 3.1, 3.2, 3.3'
 six==1.16.0; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
 sniffio==1.2.0; python_version >= '3.5'
 soupsieve==2.3.1; python_version >= '3.6'
-starlette==0.16.0; python_version >= '3.6'
+stack-data==0.1.4
+starlette==0.17.1; python_version >= '3.6'
 tabulate==0.8.9
+tomli==1.2.3; python_version >= '3.6'
 tornado==6.1; python_version >= '3.5'
 tqdm==4.62.3; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
 traitlets==5.1.1; python_version >= '3.7'
 typing-extensions==4.0.1
 typing-inspect==0.7.1
-urllib3==1.26.7
-uvicorn==0.16.0
+urllib3==1.26.8
+uvicorn==0.17.0.post1
 uvloop==0.16.0
 watchdog==2.1.6; python_version >= '3.6'
 wcwidth==0.2.5
diff --git a/setup.cfg b/setup.cfg
index 957fa117..a2f33427 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -15,7 +15,7 @@ zip_safe = False
 include_package_data = True
 
 install_requires =
-    fastapi >= 0.65.2
+    fastapi >= 0.72.0
     urllib3 >= 1.26.5
     uvicorn
     uvloop
@@ -34,7 +34,7 @@ install_requires =
     chembl-downloader
     pystow
     bioversions >= 0.4.3
-    disease-normalizer >= 0.2.11
+    disease-normalizer >= 0.2.12
     ga4gh.vrsatile.pydantic >= 0.0.5
 
 tests_require =
diff --git a/therapy/cli.py b/therapy/cli.py
index 28917321..c4c68a12 100644
--- a/therapy/cli.py
+++ b/therapy/cli.py
@@ -48,8 +48,15 @@ class CLI:
         is_flag=True,
         help="Update concepts for normalize endpoint from accepted sources."
     )
+    @click.option(
+        "--use_existing",
+        is_flag=True,
+        default=False,
+        help="Use most recent existing source data instead of fetching latest version"
+    )
     def update_normalizer_db(normalizer: str, prod: bool, db_url: str,
-                             update_all: bool, update_merged: bool) -> None:
+                             update_all: bool, update_merged: bool,
+                             use_existing: bool) -> None:
         """Update selected normalizer source(s) in the therapy database.
         \f  # noqa: D301
         :param str normalizer: comma-separated string listing source names
@@ -57,6 +64,7 @@ def update_normalizer_db(normalizer: str, prod: bool, db_url: str,
         :param str db_url: DynamoDB endpoint URL (usually only needed locally)
         :param bool update_all: if true, update all sources
         :param bool update_merged: if true, update normalized group results
+        :param bool use_existing: if true, don't try to fetch latest source data
         """
         endpoint_url = None
         if prod:
@@ -75,7 +83,7 @@ def update_normalizer_db(normalizer: str, prod: bool, db_url: str,
         if update_all:
             normalizers = list(src for src in SOURCES)
             CLI()._check_disease_normalizer(normalizers, endpoint_url)
-            CLI()._update_normalizers(normalizers, db, update_merged)
+            CLI()._update_normalizers(normalizers, db, update_merged, use_existing)
         elif not normalizer:
             if update_merged:
                 CLI()._update_merged(db, [])
@@ -93,7 +101,7 @@ def update_normalizer_db(normalizer: str, prod: bool, db_url: str,
                 raise Exception(f"Not valid source(s): {non_sources}")
 
             CLI()._check_disease_normalizer(normalizers, endpoint_url)
-            CLI()._update_normalizers(normalizers, db, update_merged)
+            CLI()._update_normalizers(normalizers, db, update_merged, use_existing)
 
     def _check_disease_normalizer(self, normalizers: List[str],
                                   endpoint_url: Optional[str]) -> None:
@@ -112,6 +120,7 @@ def _check_disease_normalizer(self, normalizers: List[str],
                     ("disease_metadata" not in current_tables) or \
                     (db.diseases.scan()["Count"] == 0) or \
                     (db.metadata.scan()["Count"] < len(DiseaseSources)):
+
                 msg = "Disease Normalizer not loaded. Loading now..."
                 logger.debug(msg)
                 click.echo(msg)
@@ -140,12 +149,14 @@ def _help_msg() -> None:
 
     @staticmethod
     def _update_normalizers(normalizers: List[str], db: Database,
-                            update_merged: bool) -> None:
+                            update_merged: bool, use_existing: bool) -> None:
         """Update selected normalizer sources.
         :param List[str] normalizers: list of source names to update
         :param Database db: database instance to use
         :param bool update_merged: if true, store concept IDs as they're processed and
             produce normalized records
+        :param bool use_existing: if true, don't try to fetch latest source data in
+            source perform_etl methods
         """
         processed_ids = list()
         for n in normalizers:
@@ -168,7 +179,18 @@ def _update_normalizers(normalizers: List[str], db: Database,
 
             start_load = timer()
             source = SOURCES_CLASS[n](database=db)
-            processed_ids += source.perform_etl()
+            try:
+                processed_ids += source.perform_etl(use_existing)
+            except FileNotFoundError as e:
+                if use_existing:
+                    if click.confirm(
+                        f"Encountered FileNotFoundError while loading {n}: "
+                        f"{e.args[0] if len(e.args) > 0 else ''}\n"
+                        "Attempt to retrieve latest version from source? "
+                    ):
+                        processed_ids += source.perform_etl()
+                    else:
+                        raise e
             end_load = timer()
             load_time = end_load - start_load
 
diff --git a/therapy/etl/base.py b/therapy/etl/base.py
index 0cd88e06..37c7b1b1 100644
--- a/therapy/etl/base.py
+++ b/therapy/etl/base.py
@@ -7,10 +7,14 @@
 import os
 import zipfile
 import tempfile
+import re
+import json
+from functools import lru_cache
 
 from pydantic import ValidationError
 import requests
 import bioversions
+from disease.query import QueryHandler as DiseaseNormalizer
 
 from therapy import APP_ROOT, ITEM_TYPES, DownloadException
 from therapy.schemas import Drug
@@ -45,15 +49,16 @@ def __init__(self, database: Database,
         self._src_dir: Path = Path(data_path / name)
         self._added_ids: List[str] = []
 
-    def perform_etl(self) -> List[str]:
+    def perform_etl(self, use_existing: bool = False) -> List[str]:
         """Public-facing method to begin ETL procedures on given data.
         Returned concept IDs can be passed to Merge method for computing
         merged concepts.
 
+        :param bool use_existing: if True, don't try to retrieve latest source data
         :return: list of concept IDs which were successfully processed and
             uploaded.
         """
-        self._extract_data()
+        self._extract_data(use_existing)
         self._load_meta()
         self._transform_data()
         return self._added_ids
@@ -138,26 +143,61 @@ def _ftp_download(self, host: str, host_dir: str, host_fn: str) -> None:
             logger.error(f"FTP download failed: {e}")
             raise Exception(e)
 
-    def _extract_data(self) -> None:
+    def _parse_version(self, file_path: Path, pattern: Optional[re.Pattern] = None
+                       ) -> str:
+        """Get version number from provided file path.
+
+        :param Path file_path: path to located source data file
+        :param Optional[re.Pattern] pattern: regex pattern to use
+        :return: source data version
+        :raises: FileNotFoundError if version parsing fails
+        """
+        if pattern is None:
+            pattern = re.compile(type(self).__name__.lower() + r"_(.+)\..+")
+        matches = re.match(pattern, file_path.name)
+        if matches is None:
+            raise FileNotFoundError
+        else:
+            return matches.groups()[0]
+
+    def _extract_data(self, use_existing: bool = False) -> None:
         """Get source file from data directory.
-        This method should create the source data directory if needed,
-        acquire the most recent version number, check that local data is
-        up-to-date and retrieve the latest data if needed, and set the
-        `self._src_file` attribute to the source file location. Child classes
-        could add additional functions, e.g. setting up DB cursors.
-
-        Sources that use multiple data files (such as RxNorm and HemOnc) will
-        have to reimplement this method.
+
+        This method should ensure the source data directory exists, acquire source data,
+        set the source version value, and assign the source file location to
+        `self._src_file`. Child classes needing additional functionality (like setting
+        up a DB cursor, or managing multiple source files) will need to reimplement
+        this method. If `use_existing` is True, the version number will be parsed from
+        the existing filename; otherwise, it will be retrieved from the data source,
+        and if the local file is out-of-date, the newest version will be acquired.
+
+        :param bool use_existing: if True, don't try to fetch latest source data
         """
         self._src_dir.mkdir(exist_ok=True, parents=True)
-        self._version = self.get_latest_version()
-        fglob = f"{type(self).__name__.lower()}_{self._version}.*"
-        latest = list(self._src_dir.glob(fglob))
-        if not latest:
-            self._download_data()
+        src_name = type(self).__name__.lower()
+        if use_existing:
+            files = list(sorted(self._src_dir.glob(f"{src_name}_*.*")))
+            if len(files) < 1:
+                raise FileNotFoundError(f"No source data found for {src_name}")
+            self._src_file: Path = files[-1]
+            try:
+                self._version = self._parse_version(self._src_file)
+            except FileNotFoundError:
+                raise FileNotFoundError(
+                    f"Unable to parse version value from {src_name} source data file "
+                    f"located at {self._src_file.absolute().as_uri()} -- "
+                    "check filename against schema defined in README: "
+                    "https://github.com/cancervariants/therapy-normalization#update-sources"  # noqa: E501
+                )
+        else:
+            self._version = self.get_latest_version()
+            fglob = f"{src_name}_{self._version}.*"
             latest = list(self._src_dir.glob(fglob))
-        assert len(latest) != 0  # probably unnecessary, but just to be safe
-        self._src_file: Path = latest[0]
+            if not latest:
+                self._download_data()
+                latest = list(self._src_dir.glob(fglob))
+            assert len(latest) != 0  # probably unnecessary, but just to be safe
+            self._src_file = latest[0]
 
     @abstractmethod
     def _load_meta(self) -> None:
@@ -229,18 +269,50 @@ def _load_therapy(self, therapy: Dict) -> None:
         # compress has_indication
         indications = therapy.get("has_indication")
         if indications:
-            therapy["has_indication"] = [
-                [ind["disease_id"], ind["disease_label"], ind["normalized_disease_id"]]
+            therapy["has_indication"] = list({
+                json.dumps([
+                    ind["disease_id"],
+                    ind["disease_label"],
+                    ind.get("normalized_disease_id"),
+                    ind.get("supplemental_info")
+                ])
                 for ind in indications
-            ]
+            })
         elif "has_indication" in therapy:
             del therapy["has_indication"]
 
         # handle detail fields
-        approval_attrs = ("approval_rating", "approval_year")
+        approval_attrs = ("approval_ratings", "approval_year")
         for field in approval_attrs:
             if approval_attrs in therapy and therapy[field] is None:
                 del therapy[field]
 
         self.database.add_record(therapy)
         self._added_ids.append(concept_id)
+
+
+class DiseaseIndicationBase(Base):
+    """Base class for sources that require disease normalization capabilities."""
+
+    def __init__(self, database: Database,
+                 data_path: Path = DEFAULT_DATA_PATH):
+        """Initialize source ETL instance.
+
+        :param therapy.database.Database database: application database
+        :param Path data_path: path to normalizer data directory
+        """
+        super().__init__(database, data_path)
+        self.disease_normalizer = DiseaseNormalizer(self.database.endpoint_url)
+
+    @lru_cache(maxsize=64)
+    def _normalize_disease(self, query: str) -> Optional[str]:
+        """Attempt normalization of disease term.
+        :param str query: term to normalize
+        :return: ID if successful, None otherwise
+        """
+        response = self.disease_normalizer.normalize(query)
+        if response.match_type > 0:
+            return response.disease_descriptor.disease_id
+        else:
+            logger.warning(f"Failed to normalize disease term: {query}")
+            return None
diff --git a/therapy/etl/chembl.py b/therapy/etl/chembl.py
index 4a52c5ea..2fb6c342 100644
--- a/therapy/etl/chembl.py
+++ b/therapy/etl/chembl.py
@@ -3,11 +3,12 @@
 import os
 import shutil
 import sqlite3
+from typing import Optional, List, Dict
 
 import chembl_downloader
 import bioversions
 
-from therapy.etl.base import Base
+from therapy.etl.base import DiseaseIndicationBase
 from therapy.schemas import SourceName, NamespacePrefix, ApprovalRating, \
     SourceMeta
 
@@ -16,7 +17,7 @@
 logger.setLevel(logging.DEBUG)
 
 
-class ChEMBL(Base):
+class ChEMBL(DiseaseIndicationBase):
     """Class for ChEMBL ETL methods."""
 
     def _download_data(self) -> None:
@@ -28,161 +29,164 @@ def _download_data(self) -> None:
         shutil.rmtree(tmp_path.parent.parent.parent)
         logger.info("Successfully retrieved source data for ChEMBL")
 
-    def _extract_data(self) -> None:
-        """Extract data from the ChEMBL source."""
-        super()._extract_data()
+    def _extract_data(self, use_existing: bool = False) -> None:
+        """Extract data from the ChEMBL source.
+
+        :param bool use_existing: if True, don't try to fetch latest source data
+        """
+        super()._extract_data(use_existing)
         conn = sqlite3.connect(self._src_file)
         conn.row_factory = sqlite3.Row
         self._conn = conn
         self._cursor = conn.cursor()
 
-    def _transform_data(self) -> None:
-        """Transform SQLite data to temporary JSON."""
-        self._create_dictionary_synonyms_table()
-        self._create_trade_names_table()
-        self._create_temp_table()
-
-        self._cursor.execute("DROP TABLE DictionarySynonyms;")
-        self._cursor.execute("DROP TABLE TradeNames;")
-
-        self._load_json()
-        self._conn.commit()
-        self._conn.close()
-
-    def _create_dictionary_synonyms_table(self) -> None:
-        """Create temporary table to store drugs and their synonyms."""
-        create_dictionary_synonyms_table = f"""
-            CREATE TEMPORARY TABLE DictionarySynonyms AS
-            SELECT
-                md.molregno,
-                '{NamespacePrefix.CHEMBL.value}:'||md.chembl_id as chembl_id,
-                md.pref_name,
-                md.max_phase,
-                md.withdrawn_flag,
-                group_concat(
-                    ms.synonyms, '||')as synonyms
-            FROM molecule_dictionary md
-            LEFT JOIN molecule_synonyms ms USING(molregno)
-            GROUP BY md.molregno
-            UNION ALL
-            SELECT
-                md.molregno,
-                '{NamespacePrefix.CHEMBL.value}:'||md.chembl_id as chembl_id,
-                md.pref_name,
-                md.max_phase,
-                md.withdrawn_flag,
-                group_concat(
-                    ms.synonyms, '||') as synonyms
-            FROM molecule_synonyms ms
-            LEFT JOIN molecule_dictionary md USING(molregno)
-            WHERE md.molregno IS NULL
-            GROUP BY md.molregno
-        """
-        self._cursor.execute(create_dictionary_synonyms_table)
-
-    def _create_trade_names_table(self) -> None:
-        """Create temporary table to store trade name data."""
-        create_trade_names_table = """
-            CREATE TEMPORARY TABLE TradeNames AS
-            SELECT
-                f.molregno,
-                f.product_id,
-                group_concat(
-                    p.trade_name, '||') as trade_names
-            FROM formulations f
-            LEFT JOIN products p
-                ON f.product_id = p.product_id
-            GROUP BY f.molregno;
+    @staticmethod
+    def _unwrap_group_concat(value: Optional[str]) -> List[str]:
+        """Process concatenated values retrieved from ChEMBL DB.
+        :param Optional[str] value: the value provided by the cursor
+        :return: List of separated values (empty if none present)
         """
-        self._cursor.execute(create_trade_names_table)
-
-    def _create_temp_table(self) -> None:
-        """Create temporary table to store therapies data."""
-        create_temp_table = """
-            CREATE TEMPORARY TABLE temp(concept_id, label, approval_rating,
-                                        src_name, trade_names, aliases);
+        if value:
+            return value.split("||")
+        else:
+            return []
+
+    @staticmethod
+    def _get_approval_rating(value: int) -> ApprovalRating:
+        """Standardize approval rating value
+        :param int value: value retrieved from ChEMBL database
+        :return: instantiated ApprovalRating
+        :raise: ValueError if invalid value is provided
         """
-        self._cursor.execute(create_temp_table)
-
-        insert_temp = f"""
-            INSERT INTO temp(concept_id, label, approval_rating, src_name,
-                             trade_names, aliases)
-            SELECT
-                ds.chembl_id,
-                ds.pref_name,
-                CASE
-                    WHEN ds.withdrawn_flag
-                        THEN '{ApprovalRating.CHEMBL_WITHDRAWN.value}'
-                    WHEN ds.max_phase == 0
-                        THEN '{ApprovalRating.CHEMBL_0.value}'
-                    WHEN ds.max_phase == 1
-                        THEN '{ApprovalRating.CHEMBL_1.value}'
-                    WHEN ds.max_phase == 2
-                        THEN '{ApprovalRating.CHEMBL_2.value}'
-                    WHEN ds.max_phase ==3
-                        THEN '{ApprovalRating.CHEMBL_3.value}'
-                    WHEN ds.max_phase == 4
-                        THEN '{ApprovalRating.CHEMBL_4.value}'
-                    ELSE
-                        '{None}'
-                END,
-                '{SourceName.CHEMBL.value}',
-                t.trade_names,
-                ds.synonyms
-            FROM DictionarySynonyms ds
-            LEFT JOIN TradeNames t USING(molregno)
-            GROUP BY ds.molregno
-            UNION ALL
-            SELECT
-                ds.chembl_id,
-                ds.pref_name,
-                CASE
-                    WHEN ds.withdrawn_flag
-                        THEN '{ApprovalRating.CHEMBL_WITHDRAWN.value}'
-                    WHEN ds.max_phase == 0
-                        THEN '{ApprovalRating.CHEMBL_0.value}'
-                    WHEN ds.max_phase == 1
-                        THEN '{ApprovalRating.CHEMBL_1.value}'
-                    WHEN ds.max_phase == 2
-                        THEN '{ApprovalRating.CHEMBL_2.value}'
-                    WHEN ds.max_phase ==3
-                        THEN '{ApprovalRating.CHEMBL_3.value}'
-                    WHEN ds.max_phase == 4
-                        THEN '{ApprovalRating.CHEMBL_4.value}'
-                    ELSE
-                        '{None}'
-                END,
-                '{SourceName.CHEMBL.value}',
-                t.trade_names,
-                ds.synonyms
-            FROM TradeNames t
-            LEFT JOIN DictionarySynonyms ds USING(molregno)
-            WHERE ds.molregno IS NULL
-            GROUP BY ds.molregno;
+        if value == 0:
+            return ApprovalRating.CHEMBL_0
+        elif value == 1:
+            return ApprovalRating.CHEMBL_1
+        elif value == 2:
+            return ApprovalRating.CHEMBL_2
+        elif value == 3:
+            return ApprovalRating.CHEMBL_3
+        elif value == 4:
+            return ApprovalRating.CHEMBL_4
+        else:
+            raise ValueError(f"Unrecognized approval rating: {value}")
+
+    def _get_indications(self, value: Optional[str]) -> List[Dict]:
+        """Construct indication objects to prepare for loading into DB
+        :param Optional[str] value: `indication` value fetched from ChEMBL DB
+        :return: List containing indication dicts
         """
-        self._cursor.execute(insert_temp)
-
-    def _load_json(self) -> None:
-        """Load ChEMBL data into database."""
-        chembl_data = """
-            SELECT
-                concept_id,
-                label,
-                approval_rating,
-                src_name,
-                trade_names,
-                aliases
-            FROM temp;
+        if value:
+            indications = []
+            indication_groups = value.split("|||")
+            for group in set(indication_groups):
+                ind_group = group.split("||")
+                phase = self._get_approval_rating(int(ind_group[4]))
+                indication = {}
+                for i, term in enumerate(ind_group[:4]):
+                    normalized_disease_id = self._normalize_disease(term)
+                    if normalized_disease_id is not None:
+                        label = ind_group[2] if i % 2 == 0 else ind_group[3]
+                        disease_id = ind_group[0] if i % 2 == 0 else ind_group[1]
+                        indication = {
+                            "disease_id": disease_id,
+                            "disease_label": label,
+                            "normalized_disease_id": normalized_disease_id,
+                            "supplemental_info": {"chembl_max_phase_for_ind": phase}
+                        }
+                        break
+                if not indication:
+                    indication = {
+                        "disease_id": ind_group[0],
+                        "disease_label": ind_group[2],
+                        "supplemental_info": {"chembl_max_phase_for_ind": phase}
+                    }
+                indications.append(indication)
+            return indications
+        else:
+            return []
+
+    def _transform_data(self) -> None:
+        """Transform SQLite data and load to DB."""
+        query = """
+        SELECT
+            md.chembl_id,
+            md.molregno,
+            md.pref_name,
+            md.max_phase,
+            md.withdrawn_flag,
+            ms.aliases,
+            tn.trade_names,
+            d.indications
+        FROM molecule_dictionary md
+        LEFT JOIN (
+            SELECT molregno, GROUP_CONCAT(synonyms, '||') aliases
+            FROM (
+                SELECT DISTINCT molregno, synonyms
+                FROM molecule_synonyms
+                WHERE syn_type != 'TRADE_NAME'
+            ) GROUP BY molregno
+        ) ms on md.molregno = ms.molregno
+        LEFT JOIN (
+            SELECT molregno, GROUP_CONCAT(trade_name, '||') trade_names
+            FROM (
+                SELECT DISTINCT molregno, trade_name
+                FROM (
+                    SELECT molregno, synonyms as trade_name
+                    FROM molecule_synonyms
+                    WHERE syn_type == 'TRADE_NAME'
+                    UNION
+                    SELECT molregno, trade_name
+                    FROM (
+                        SELECT f.molregno, p.trade_name
+                        FROM formulations f
+                        LEFT JOIN products p
+                        ON f.product_id = p.product_id
+                    )
+                )
+            ) GROUP BY molregno
+        ) tn on md.molregno = tn.molregno
+        LEFT JOIN (
+            SELECT molregno, GROUP_CONCAT(indication, '|||') as indications
+            FROM (
+                SELECT DISTINCT d.molregno,
+                'mesh:' || d.mesh_id || '||' || d.efo_id || '||' || d.mesh_heading
+                 || '||' || d.efo_term || '||' || d.max_phase_for_ind as indication
+                FROM drug_indication AS d
+                WHERE (
+                    d.molregno IS NOT NULL
+                    AND d.mesh_heading IS NOT NULL
+                    AND d.mesh_id IS NOT NULL
+                    AND d.efo_term IS NOT NULL
+                    AND d.efo_id IS NOT NULL
+                    AND d.max_phase_for_ind IS NOT NULL
+                )
+            ) GROUP BY molregno
+        ) d on md.molregno = d.molregno
+        GROUP BY md.molregno;
         """
-        result = [dict(row) for row in
-                  self._cursor.execute(chembl_data).fetchall()]
-        self._cursor.execute("DROP TABLE temp;")
-
-        for record in result:
-            for attr in ["aliases", "trade_names"]:
-                if attr in record and record[attr]:
-                    record[attr] = record[attr].split("||")
-            self._load_therapy(record)
+        self._cursor.execute(query)
+
+        for row in self._cursor:
+            appr_ratings = []
+            max_phase = self._get_approval_rating(row["max_phase"])
+            if max_phase is not None:
+                appr_ratings.append(max_phase)
+            if row["withdrawn_flag"] == "1":
+                appr_ratings.append(ApprovalRating.CHEMBL_WITHDRAWN)
+
+            has_indication = self._get_indications(row["indications"])
+
+            params = {
+                "concept_id": f"{NamespacePrefix.CHEMBL.value}:{row['chembl_id']}",
+                "label": row["pref_name"],
+                "approval_ratings": appr_ratings,
+                "aliases": self._unwrap_group_concat(row["aliases"]),
+                "trade_names": self._unwrap_group_concat(row["trade_names"]),
+                "has_indication": has_indication
+            }
+            self._load_therapy(params)
+        self._conn.close()
 
     def _load_meta(self) -> None:
         """Add ChEMBL metadata."""
diff --git a/therapy/etl/drugsatfda.py b/therapy/etl/drugsatfda.py
index 3f5f872e..7b0ec272 100644
--- a/therapy/etl/drugsatfda.py
+++ b/therapy/etl/drugsatfda.py
@@ -102,7 +102,7 @@ def _transform_data(self) -> None:
 
             rating = self._get_marketing_status_rating(products, concept_id)
             if rating:
-                therapy["approval_rating"] = rating
+                therapy["approval_ratings"] = [rating]
 
             brand_names = [p["brand_name"] for p in products]
 
diff --git a/therapy/etl/guidetopharmacology.py b/therapy/etl/guidetopharmacology.py
index 56c999aa..2b891840 100644
--- a/therapy/etl/guidetopharmacology.py
+++ b/therapy/etl/guidetopharmacology.py
@@ -1,8 +1,9 @@
 """Module for Guide to PHARMACOLOGY ETL methods."""
-from typing import Optional, Dict, Any, List, Union
+from typing import Optional, Dict, Any, List, Union, Tuple
 import csv
 import html
 from pathlib import Path
+import re
 
 import requests
 
@@ -44,17 +45,52 @@ def _download_file(self, file_url: str, fn: str) -> None:
             with open(str(path), "wb") as f:
                 f.write(r.content)
 
-    def _extract_data(self) -> None:
-        """Gather GtoPdb source files."""
+    def _extract_data(self, use_existing: bool = False) -> None:
+        """Gather GtoPdb source files.
+
+        :param bool use_existing: if True, don't try to fetch latest source data
+        """
         self._src_dir.mkdir(exist_ok=True, parents=True)
-        self._version = self.get_latest_version()
         prefix = SourceName.GUIDETOPHARMACOLOGY.value.lower()
-        self._ligands_file = self._src_dir / f"{prefix}_ligands_{self._version}.tsv"
-        self._mapping_file = self._src_dir / f"{prefix}_ligand_id_mapping_{self._version}.tsv"  # noqa: E501
-        if not (self._ligands_file.exists() and self._mapping_file.exists()):
-            self._download_data()
-            assert self._ligands_file.exists()
-            assert self._mapping_file.exists()
+        if use_existing:
+            ligands_files = list(sorted(self._src_dir.glob(f"{prefix}_ligands_*.tsv")))
+            if len(ligands_files) < 1:
+                raise FileNotFoundError("No GtoPdb ligands files found")
+
+            mapping_file: Optional[Tuple] = None
+            for ligands_file in ligands_files[::-1]:
+                try:
+                    version = self._parse_version(
+                        ligands_file,
+                        re.compile(prefix + r"_ligands_(.+)\.tsv")
+                    )
+                except FileNotFoundError:
+                    raise FileNotFoundError(
+                        "Unable to parse GtoPdb version value from ligands file "
+                        f"located at {ligands_file.absolute().as_uri()} -- check "
+                        "filename against schema defined in README: "
+                        "https://github.com/cancervariants/therapy-normalization#update-sources"  # noqa: E501
+                    )
+                check_mapping_file = self._src_dir / f"{prefix}_ligand_id_mapping_{version}.tsv"  # noqa: E501
+                if check_mapping_file.exists():
+                    self.version = version
+                    self._ligands_file = ligands_file
+                    self._mapping_file = check_mapping_file
+                    break
+            if mapping_file is None:
+                raise FileNotFoundError(
+                    "Unable to find complete GtoPdb data set with matching version "
+                    "values. Check filenames against schema defined in README: "
+                    "https://github.com/cancervariants/therapy-normalization#update-sources"  # noqa: E501
+                )
+        else:
+            self._version = self.get_latest_version()
+            self._ligands_file = self._src_dir / f"{prefix}_ligands_{self._version}.tsv"
+            self._mapping_file = self._src_dir / f"{prefix}_ligand_id_mapping_{self._version}.tsv"  # noqa: E501
+            if not (self._ligands_file.exists() and self._mapping_file.exists()):
+                self._download_data()
+                assert self._ligands_file.exists()
+                assert self._mapping_file.exists()
 
     def _transform_data(self) -> None:
         """Transform Guide To PHARMACOLOGY data."""
@@ -83,7 +119,7 @@ def _transform_ligands(self, data: Dict) -> None:
 
                 approval_rating = self._set_approval_rating(row[4], row[5])
                 if approval_rating:
-                    params["approval_rating"] = approval_rating
+                    params["approval_ratings"] = [approval_rating]
 
                 associated_with = list()
                 aliases = list()
diff --git a/therapy/etl/hemonc.py b/therapy/etl/hemonc.py
index 484e4db2..fc1070d0 100644
--- a/therapy/etl/hemonc.py
+++ b/therapy/etl/hemonc.py
@@ -1,39 +1,28 @@
 """Provide ETL methods for HemOnc.org data."""
 import logging
 from pathlib import Path
-from typing import Dict, Tuple
+from typing import Dict, Tuple, Optional
 import csv
 import os
 import zipfile
+import re
 
 import requests
 import isodate
-from disease.query import QueryHandler as DiseaseNormalizer
 
 from therapy import DownloadException
-from therapy.database import Database
 from therapy.schemas import NamespacePrefix, SourceMeta, SourceName, RecordParams, \
     ApprovalRating
-from therapy.etl.base import Base, DEFAULT_DATA_PATH
+from therapy.etl.base import DiseaseIndicationBase
 
 
 logger = logging.getLogger("therapy")
 logger.setLevel(logging.DEBUG)
 
 
-class HemOnc(Base):
+class HemOnc(DiseaseIndicationBase):
     """Class for HemOnc.org ETL methods."""
 
-    def __init__(self, database: Database,
-                 data_path: Path = DEFAULT_DATA_PATH):
-        """Initialize HemOnc instance.
-
-        :param therapy.database.Database database: application database
-        :param Path data_path: path to normalizer data directory
-        """
-        super().__init__(database, data_path)
-        self.disease_normalizer = DiseaseNormalizer(self.database.endpoint_url)
-
     def get_latest_version(self) -> str:
         """Retrieve latest version of source data.
         :raise: Exception if retrieval is unsuccessful
@@ -83,7 +72,7 @@ def _download_data(self) -> None:
         headers = {"X-Dataverse-key": api_key}
         self._http_download(url, self._src_dir, headers, self._zip_handler)
 
-    def _extract_data(self) -> None:
+    def _extract_data(self, use_existing: bool = False) -> None:
         """Get source files from data directory.
 
         The following files are necessary for data processing:
@@ -92,19 +81,62 @@ def _extract_data(self) -> None:
             hemonc_synonyms_<version>.csv
         This method will attempt to retrieve their latest versions if they are
         unavailable locally.
+
+        :param bool use_existing: if True, don't try to fetch latest source data
         """
         self._src_dir.mkdir(exist_ok=True, parents=True)
-        self._version = self.get_latest_version()
-        data_filenames = (
-            self._src_dir / f"hemonc_concepts_{self._version}.csv",
-            self._src_dir / f"hemonc_rels_{self._version}.csv",
-            self._src_dir / f"hemonc_synonyms_{self._version}.csv"
-        )
-        if not all((f.exists() for f in data_filenames)):
-            self._download_data()
-        self._src_files = data_filenames
-        for file in self._src_files:
-            assert file.exists()
+
+        if use_existing:
+            concepts = list(sorted(self._src_dir.glob("hemonc_concepts_*.csv")))
+            if len(concepts) < 1:
+                raise FileNotFoundError("No HemOnc concepts file found")
+
+            src_files: Optional[Tuple] = None
+            for concepts_file in concepts[::-1]:
+                try:
+                    version = self._parse_version(
+                        concepts_file,
+                        re.compile(r"hemonc_concepts_(.+)\.csv")
+                    )
+                except FileNotFoundError:
+                    raise FileNotFoundError(
+                        f"Unable to parse HemOnc version value from concepts file "
+                        f"located at {concepts_file.absolute().as_uri()} -- check "
+                        "filename against schema defined in README: "
+                        "https://github.com/cancervariants/therapy-normalization#update-sources"  # noqa: E501
+                    )
+                other_files = (
+                    self._src_dir / f"hemonc_rels_{version}.csv",
+                    self._src_dir / f"hemonc_synonyms_{version}.csv"
+                )
+                if other_files[0].exists() and other_files[1].exists():
+                    self.version = version
+                    src_files = (
+                        concepts_file,
+                        other_files[0],
+                        other_files[1]
+                    )
+                    break
+            if src_files is None:
+                raise FileNotFoundError(
+                    "Unable to find complete HemOnc data set with matching version "
+                    "values. Check filenames against schema defined in README: "
+                    "https://github.com/cancervariants/therapy-normalization#update-sources"  # noqa: E501
+                )
+            else:
+                self._src_files = src_files
+        else:
+            self._version = self.get_latest_version()
+            data_filenames = (
+                self._src_dir / f"hemonc_concepts_{self._version}.csv",
+                self._src_dir / f"hemonc_rels_{self._version}.csv",
+                self._src_dir / f"hemonc_synonyms_{self._version}.csv"
+            )
+            if not all((f.exists() for f in data_filenames)):
+                self._download_data()
+            self._src_files = data_filenames
+            for file in self._src_files:
+                assert file.exists()
 
     def _load_meta(self) -> None:
         """Add HemOnc metadata."""
@@ -158,22 +190,22 @@ def _get_concepts(self) -> Tuple[Dict, Dict, Dict]:
         return therapies, brand_names, conditions
 
     @staticmethod
-    def _id_to_yr(hemonc_id: str) -> int:
+    def _id_to_yr(hemonc_id: str) -> str:
         """Get year from HemOnc ID corresponding to year concept.
         :param str hemonc_id: HemOnc ID to get year for
-        :return: int representing year. Raises TypeError if HemOnc ID not valid.
+        :return: str representing year. Raises TypeError if HemOnc ID not valid.
         """
         id_int = int(hemonc_id)
         if id_int == 780:
-            return 9999
+            return "9999"
         elif id_int == 48349:
-            return 2020
+            return "2020"
         elif id_int == 5963:
-            return 2021
+            return "2021"
         elif id_int < 699 or id_int > 780:
             raise TypeError("ID not a valid HemOnc year concept")
         else:
-            return id_int + 1240
+            return str(id_int + 1240)
 
     def _get_rels(self, therapies: Dict, brand_names: Dict,
                   conditions: Dict) -> Dict:
@@ -217,10 +249,10 @@ def _get_rels(self, therapies: Dict, brand_names: Dict,
                     logger.error(f"Failed parse of FDA approval year ID "
                                  f"{row[1]} for HemOnc ID {row[0]}")
                     continue
-                if year == 9999:
+                if year == "9999":
                     logger.warning(f"HemOnc ID {row[0]} has FDA approval year"
                                    f" 9999")
-                record["approval_rating"] = ApprovalRating.HEMONC_APPROVED.value
+                record["approval_ratings"] = [ApprovalRating.HEMONC_APPROVED.value]
                 if "approval_year" in record:
                     record["approval_year"].append(year)
                 else:
@@ -228,18 +260,13 @@ def _get_rels(self, therapies: Dict, brand_names: Dict,
 
             elif rel_type == "Has FDA indication":
                 label = conditions[row[1]]
-                norm_response = self.disease_normalizer.search_groups(label)
-                if norm_response["match_type"] > 0:
-                    ncit_id = norm_response["disease_descriptor"]["disease_id"]
-                else:
-                    ncit_id = ""
-                    logger.warning(f"Normalization of condition id: {row[1]}"
-                                   f", {label}, failed.")
+                norm_id = self._normalize_disease(label)
                 hemonc_concept_id = f"{NamespacePrefix.HEMONC.value}:{row[1]}"
                 indication = {
                     "disease_id": hemonc_concept_id,
                     "disease_label": label,
-                    "normalized_disease_id": ncit_id
+                    "normalized_disease_id": norm_id,
+                    "supplemental_info": {"regulatory_body": "FDA"}
                 }
                 if "has_indication" in record:
                     record["has_indication"].append(indication)
diff --git a/therapy/etl/merge.py b/therapy/etl/merge.py
index 50342896..454fbc89 100644
--- a/therapy/etl/merge.py
+++ b/therapy/etl/merge.py
@@ -242,9 +242,9 @@ def record_order(record: Dict) -> Tuple[int, str]:
         for record in records:
             for field in set_fields:
                 merged_attrs[field] |= set(record.get(field, set()))
-            approval_rating = record.get("approval_rating")
-            if approval_rating:
-                merged_attrs["approval_ratings"].add(approval_rating)
+            approval_ratings = record.get("approval_ratings")
+            if approval_ratings:
+                merged_attrs["approval_ratings"] |= set(approval_ratings)
             if merged_attrs["label"] is None:
                 merged_attrs["label"] = record.get("label")
             for ind in record.get("has_indication", []):
diff --git a/therapy/etl/rxnorm.py b/therapy/etl/rxnorm.py
index fb69a47d..4dc626f1 100644
--- a/therapy/etl/rxnorm.py
+++ b/therapy/etl/rxnorm.py
@@ -107,13 +107,15 @@ def _download_data(self) -> None:
         self._http_download(f"{url}?ticket={st_r.text}", self._src_dir,
                             handler=self._zip_handler)
 
-    def _extract_data(self) -> None:
+    def _extract_data(self, use_existing: bool = False) -> None:
         """Get source files from RxNorm data directory.
         This class expects a file named `rxnorm_<version>.RRF` and a file named
         `rxnorm_drug_forms_<version>.yaml`. This method will download and
         generate them if they are unavailable.
+
+        :param bool use_existing: if True, don't try to fetch latest source data
         """
-        super()._extract_data()
+        super()._extract_data(use_existing)
         drug_forms_path = self._src_dir / f"rxnorm_drug_forms_{self._version}.yaml"
         if not drug_forms_path.exists():
             self._create_drug_form_yaml()
@@ -169,7 +171,7 @@ def _transform_data(self) -> None:
 
                         params = {"concept_id": value["concept_id"]}
 
-                        for field in list(ITEM_TYPES.keys()) + ["approval_rating"]:
+                        for field in list(ITEM_TYPES.keys()) + ["approval_ratings"]:
                             field_value = value.get(field)
                             if field_value:
                                 params[field] = field_value
@@ -264,7 +266,7 @@ def _add_str_field(self, params: Dict, row: List, precise_ingredient: Dict,
         if (term_type == "IN" or term_type == "PIN") and source == "RXNORM":
             params["label"] = term
             if row[17] == "4096":
-                params["approval_rating"] = ApprovalRating.RXNORM_PRESCRIBABLE.value
+                params["approval_ratings"] = [ApprovalRating.RXNORM_PRESCRIBABLE.value]
         elif term_type in ALIASES:
             self._add_term(params, term, "aliases")
         elif term_type in TRADE_NAMES:
diff --git a/therapy/main.py b/therapy/main.py
index 100947e7..6b6307f2 100644
--- a/therapy/main.py
+++ b/therapy/main.py
@@ -11,7 +11,11 @@
 
 
 query_handler = QueryHandler()
-app = FastAPI(docs_url="/therapy", openapi_url="/therapy/openapi.json")
+app = FastAPI(
+    docs_url="/therapy",
+    openapi_url="/therapy/openapi.json",
+    swagger_ui_parameters={"tryItOutEnabled": True}
+)
 
 
 def custom_openapi() -> Dict:
@@ -29,9 +33,10 @@ def custom_openapi() -> Dict:
 #        "name": "Name-of-license",
 #        "url": "http://www.to-be-determined.com"
 #    }
-    openapi_schema["info"]["contact"] = {  # TODO
+    openapi_schema["info"]["contact"] = {
         "name": "Alex H. Wagner",
-        "email": "Alex.Wagner@nationwidechildrens.org"
+        "email": "Alex.Wagner@nationwidechildrens.org",
+        "url": "https://www.nationwidechildrens.org/specialties/institute-for-genomic-medicine/research-labs/wagner-lab"  # noqa: E501
     }
     app.openapi_schema = openapi_schema
     return app.openapi_schema
@@ -70,7 +75,7 @@ def search(q: str = Query(..., description=q_descr),
            incl: Optional[str] = Query(None, description=incl_descr),
            excl: Optional[str] = Query(None, description=excl_descr),
            infer_namespace: bool = Query(True, description=infer_descr)
-           ) -> Dict:
+           ) -> SearchService:
     """For each source, return strongest-match concepts for query string
     provided by user.
 
@@ -85,10 +90,10 @@ def search(q: str = Query(..., description=q_descr),
     :returns: JSON response with matched records and source metadata
     """
     try:
-        response = query_handler.search_sources(html.unescape(q),
-                                                keyed=keyed,  # type: ignore
-                                                incl=incl, excl=excl,  # type: ignore
-                                                infer=infer_namespace)  # type: ignore
+        response = query_handler.search(html.unescape(q),
+                                        keyed=keyed,  # type: ignore
+                                        incl=incl, excl=excl,  # type: ignore
+                                        infer=infer_namespace)  # type: ignore
     except InvalidParameterException as e:
         raise HTTPException(status_code=422, detail=str(e))
     return response
@@ -107,7 +112,7 @@ def search(q: str = Query(..., description=q_descr),
          description=normalize_description)
 def normalize(q: str = Query(..., description=merged_q_descr),
               infer_namespace: bool = Query(True, description=infer_descr)
-              ) -> Dict:
+              ) -> NormalizationService:
     """Return merged strongest-match concept for query string provided by
     user.
 
@@ -116,8 +121,8 @@ def normalize(q: str = Query(..., description=merged_q_descr),
     :returns: JSON response with matching normalized record and source metadata
     """
     try:
-        response = query_handler.search_groups(html.unescape(q),
-                                               infer_namespace)  # type: ignore
+        response = query_handler.normalize(html.unescape(q),
+                                           infer_namespace)  # type: ignore
     except InvalidParameterException as e:
         raise HTTPException(status_code=422, detail=str(e))
     return response
diff --git a/therapy/query.py b/therapy/query.py
index de72bac7..2b3225a4 100644
--- a/therapy/query.py
+++ b/therapy/query.py
@@ -3,6 +3,7 @@
 from typing import List, Dict, Set, Tuple, Union, Any, Optional
 from urllib.parse import quote
 from datetime import datetime
+import json
 
 from uvicorn.config import logger
 from botocore.exceptions import ClientError
@@ -80,6 +81,20 @@ def _fetch_meta(self, src_name: str) -> SourceMeta:
             self.db.cached_sources[src_name] = response
             return response
 
+    @staticmethod
+    def _get_indication(indication_string: str) -> HasIndication:
+        """Load indication data.
+        :param str indication_string: dumped JSON string from db
+        :return: complete HasIndication object
+        """
+        indication_values = json.loads(indication_string)
+        return HasIndication(
+            disease_id=indication_values[0],
+            disease_label=indication_values[1],
+            normalized_disease_id=indication_values[2],
+            supplemental_info=indication_values[3]
+        )
+
     def _add_record(self,
                     response: Dict[str, Dict],
                     item: Dict,
@@ -94,10 +109,7 @@ def _add_record(self,
         """
         inds = item.get("has_indication")
         if inds:
-            item["has_indication"] = [HasIndication(disease_id=i[0],
-                                                    disease_label=i[1],
-                                                    normalized_disease_id=i[2])
-                                      for i in inds]
+            item["has_indication"] = [self._get_indication(i) for i in inds]
 
         drug = Drug(**item)
         src_name = item["src_name"]
@@ -300,8 +312,8 @@ def _response_list(self, query: str, sources: Set[str],
 
         return response_dict
 
-    def search_sources(self, query_str: str, keyed: bool = False, incl: str = "",
-                       excl: str = "", infer: bool = True) -> Dict:
+    def search(self, query_str: str, keyed: bool = False, incl: str = "",
+               excl: str = "", infer: bool = True) -> SearchService:
         """Fetch normalized therapy objects.
 
         :param str query_str: query, a string, to search for
@@ -361,7 +373,7 @@ def search_sources(self, query_str: str, keyed: bool = False, incl: str = "",
         response["service_meta_"] = ServiceMeta(
             response_datetime=datetime.now(),
         ).dict()
-        return SearchService(**response).dict()
+        return SearchService(**response)
 
     def _add_merged_meta(self, response: Dict) -> Dict:
         """Add source metadata to response object.
@@ -391,7 +403,7 @@ def _record_order(self, record: Dict) -> Tuple[int, str]:
         return source_rank, record["concept_id"]
 
     def _add_vod(self, response: Dict, record: Dict, query: str,
-                 match_type: MatchType) -> Dict:
+                 match_type: MatchType) -> NormalizationService:
         """Format received DB record as VOD and update response object.
         :param Dict response: in-progress response object
         :param Dict record: record as stored in DB
@@ -412,8 +424,7 @@ def _add_vod(self, response: Dict, record: Dict, query: str,
         if "aliases" in record:
             vod["alternate_labels"] = record["aliases"]
 
-        if any(filter(lambda f: f in record, ("approval_rating",
-                                              "approval_ratings",
+        if any(filter(lambda f: f in record, ("approval_ratings",
                                               "approval_year",
                                               "has_indication"))):
             approv = {
@@ -421,13 +432,7 @@ def _add_vod(self, response: Dict, record: Dict, query: str,
                 "name": "regulatory_approval",
                 "value": {}
             }
-            # temporarily handle rating vs ratings fields slightly differently
-            # to change in issue 223
-            if "approval_rating" in record:
-                value = record.get("approval_rating")
-                if value:
-                    approv["value"]["approval_ratings"] = [value]  # type: ignore
-            elif "approval_ratings" in record:
+            if "approval_ratings" in record:
                 value = record.get("approval_ratings")
                 if value:
                     approv["value"]["approval_ratings"] = value  # type: ignore
@@ -435,16 +440,27 @@ def _add_vod(self, response: Dict, record: Dict, query: str,
                 value = record.get("approval_year")
                 if value:
                     approv["value"]["approval_year"] = value  # type: ignore
+
             inds = record.get("has_indication", [])
             inds_list = []
-            for ind in inds:
-                ind_obj = {
-                    "id": ind[0],
+            for ind_db in inds:
+                indication = self._get_indication(ind_db)
+                ind_value_obj: Dict[str, Optional[Union[str, List]]] = {
+                    "id": indication.disease_id,
                     "type": "DiseaseDescriptor",
-                    "label": ind[1],
-                    "disease_id": ind[2],
+                    "label": indication.disease_label,
+                    "disease_id": indication.normalized_disease_id,
                 }
-                inds_list.append(ind_obj)
+                if indication.supplemental_info:
+                    ind_value_obj["extensions"] = [
+                        {
+                            "type": "Extension",
+                            "name": k,
+                            "value": v
+                        }
+                        for k, v in indication.supplemental_info.items()
+                    ]
+                inds_list.append(ind_value_obj)
             if inds_list:
                 approv["value"]["has_indication"] = inds_list  # type: ignore
             vod["extensions"].append(approv)
@@ -466,10 +482,10 @@ def _add_vod(self, response: Dict, record: Dict, query: str,
         response["match_type"] = match_type
         response["therapy_descriptor"] = vod
         response = self._add_merged_meta(response)
-        return response
+        return NormalizationService(**response)
 
     def _handle_failed_merge_ref(self, record: Dict, response: Dict,
-                                 query: str) -> Dict:
+                                 query: str) -> NormalizationService:
         """Log + fill out response for a failed merge reference lookup.
 
         :param Dict record: record containing failed merge_ref
@@ -480,17 +496,17 @@ def _handle_failed_merge_ref(self, record: Dict, response: Dict,
         logger.error(f"Merge ref lookup failed for ref {record['merge_ref']} "
                      f"in record {record['concept_id']} from query `{query}`")
         response["match_type"] = MatchType.NO_MATCH
-        return response
+        return NormalizationService(**response)
 
-    def _resolve_merge(self, response: Dict, query: str,
-                       record: Dict, match_type: MatchType) -> Dict:
+    def _resolve_merge(self, response: Dict, query: str, record: Dict,
+                       match_type: MatchType) -> NormalizationService:
         """Given a record, return the corresponding normalized record
 
         :param Dict response: in-progress response object
         :param str query: exact query as provided by user
         :param Dict record: record to retrieve normalized concept for
         :param MatchType match_type: type of match that returned these records
-        :return: formed response, a Dict
+        :return: Normalized response object
         """
         merge_ref = record.get("merge_ref")
         if merge_ref:
@@ -504,11 +520,12 @@ def _resolve_merge(self, response: Dict, query: str,
             # record is sole member of concept group
             return self._add_vod(response, record, query, match_type)
 
-    def search_groups(self, query: str, infer: bool = True) -> Dict:
+    def normalize(self, query: str, infer: bool = True) -> NormalizationService:
         """Return merged, normalized concept for given search term.
 
         :param str query: string to search against
         :param bool infer: if true, try to infer namespace for IDs
+        :return: Normalized response object
         """
         # prepare basic response
         response: Dict[str, Any] = {
@@ -520,7 +537,7 @@ def search_groups(self, query: str, infer: bool = True) -> Dict:
         }
         if query == "":
             response["match_type"] = MatchType.NO_MATCH.value
-            return response
+            return NormalizationService(**response)
         query_str = query.lower().strip()
 
         # check merged concept ID match
@@ -538,11 +555,14 @@ def search_groups(self, query: str, infer: bool = True) -> Dict:
         if infer:
             inferred_response = self._infer_namespace(query)
             if inferred_response:
-                response = self._resolve_merge(response, query,
-                                               inferred_response[0],
-                                               MatchType.CONCEPT_ID)
-                response["warnings"].append(inferred_response[1])
-                return response
+                norm_response = self._resolve_merge(response, query,
+                                                    inferred_response[0],
+                                                    MatchType.CONCEPT_ID)
+                if norm_response.warnings:
+                    norm_response.warnings.append(inferred_response[1])
+                else:
+                    norm_response.warnings = [inferred_response[1]]
+                return norm_response
 
         # check other match types
         for match_type in ITEM_TYPES.values():
@@ -563,4 +583,4 @@ def search_groups(self, query: str, infer: bool = True) -> Dict:
 
         if not matching_records:  # type: ignore
             response["match_type"] = MatchType.NO_MATCH.value
-        return NormalizationService(**response).dict()
+        return NormalizationService(**response)
diff --git a/therapy/schemas.py b/therapy/schemas.py
index d201e90d..84fa9972 100644
--- a/therapy/schemas.py
+++ b/therapy/schemas.py
@@ -96,11 +96,12 @@ class ApprovalRating(str, Enum):
 
 
 class HasIndication(BaseModel):
-    """Data regarding FDA indication. Currently provided only by HemOnc.org data."""
+    """Data regarding disease indications from regulatory bodies."""
 
     disease_id: str
     disease_label: str
     normalized_disease_id: Optional[str]
+    supplemental_info: Optional[Dict[str, str]] = None
 
     class Config:
         """Configure HasIndication class"""
@@ -114,19 +115,20 @@ def schema_extra(schema: Dict[str, Any], model: Type["HasIndication"]) -> None:
                 prop.pop("title", None)
             schema["example"] = [
                 {
-                    "disease_id": "hemonc:671",
-                    "disease_label": "Testicular cancer",
-                    "normalized_disease_id": "ncit:C7251"
-                },
-                {
-                    "disease_id": "hemonc:645",
-                    "disease_label": "Ovarian cancer",
-                    "normalized_disease_id": "ncit:C7431"
+                    "disease_id": "mesh:D016778",
+                    "disease_label": "Malaria, Falciparum",
+                    "normalized_disease_id": "ncit:C34798",
+                    "supplemental_info": {
+                        "chembl_max_phase_for_ind": "chembl_phase_2"
+                    }
                 },
                 {
-                    "disease_id": "hemonc:569",
-                    "disease_label": "Bladder cancer",
-                    "normalized_disease_id": "ncit:C9334"
+                    "disease_id": "hemonc:634",
+                    "disease_label": "Myelodysplastic syndrome",
+                    "normalized_disease_id": "ncit:C3247",
+                    "supplemental_info": {
+                        "regulatory_body": "FDA"
+                    }
                 }
             ]
 
@@ -140,8 +142,8 @@ class Drug(BaseModel):
     trade_names: Optional[List[str]] = []
     xrefs: Optional[List[str]] = []
     associated_with: Optional[List[str]] = []
-    approval_rating: Optional[ApprovalRating] = None
-    approval_year: Optional[List[int]] = []
+    approval_ratings: Optional[List[ApprovalRating]] = None
+    approval_year: Optional[List[str]] = []
     has_indication: Optional[List[HasIndication]] = []
 
     class Config:
@@ -171,7 +173,7 @@ def schema_extra(schema: Dict[str, Any], model: Type["Drug"]) -> None:
                 ],
                 "xrefs": [],
                 "associated_with": None,
-                "approval_rating": "approved",
+                "approval_ratings": "approved",
                 "approval_year": [],
                 "has_indication": [],
                 "trade_names": ["PLATINOL", "PLATINOL-AQ", "CISPLATIN"]
@@ -406,8 +408,8 @@ class ApprovalRatingValue(BaseModel):
     """
 
     approval_ratings: Optional[List[ApprovalRating]]
-    approval_year: Optional[List[int]]
-    has_indication: Optional[List[Union[Dict, ValueObjectDescriptor]]]
+    approval_year: Optional[List[str]]
+    has_indication: Optional[List[ValueObjectDescriptor]]
 
 
 class ServiceMeta(BaseModel):
@@ -609,7 +611,7 @@ def schema_extra(schema: Dict[str, Any], model: Type["SearchService"]) -> None:
                                 ],
                                 "xrefs": ["drugbank:DB00515"],
                                 "associated_with": ["fda:Q20Q21Q62J"],
-                                "approval_rating": None,
+                                "approval_ratings": None,
                                 "trade_names": []
                             }
                         ],
@@ -663,7 +665,7 @@ def schema_extra(schema: Dict[str, Any], model: Type["SearchService"]) -> None:
                                     "mmsl:31747",
                                     "mmsl:4456"
                                 ],
-                                "approval_rating": "rxnorm_prescribable",
+                                "approval_ratings": ["rxnorm_prescribable"],
                                 "trade_names": [
                                     "Cisplatin",
                                     "Platinol"
@@ -697,7 +699,7 @@ def schema_extra(schema: Dict[str, Any], model: Type["SearchService"]) -> None:
                                     "fda:Q20Q21Q62J",
                                     "chebi:CHEBI:27899"
                                 ],
-                                "approval_rating": None,
+                                "approval_ratings": None,
                                 "trade_names": []
                             }
                         ],
@@ -738,7 +740,7 @@ def schema_extra(schema: Dict[str, Any], model: Type["SearchService"]) -> None:
                                 "associated_with": [
                                     "pubchem.compound:5702198"
                                 ],
-                                "approval_rating": None,
+                                "approval_ratings": None,
                                 "trade_names": []
                             }
                         ],
diff --git a/therapy/version.py b/therapy/version.py
index b9e242bf..b70e11a8 100644
--- a/therapy/version.py
+++ b/therapy/version.py
@@ -1,2 +1,2 @@
 """Therapy normalizer version"""
-__version__ = "0.3.2"
+__version__ = "0.3.3"
diff --git a/tox.ini b/tox.ini
index b5dcfe50..0f0ef939 100644
--- a/tox.ini
+++ b/tox.ini
@@ -13,7 +13,7 @@ deps =
     lint: flake8-quotes
     lint: flake8-import-order
     lint: flake8-annotations
-    mypy: mypy
+    mypy: mypy == 0.910
     mypy: types-PyYAML
     mypy: types-requests
 setenv =


Test patch:
diff --git a/tests/conftest.py b/tests/conftest.py
index d7c80c17..e3e9fcd2 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -6,10 +6,18 @@
 
 import pytest
 
-from therapy.schemas import Drug, MatchType
+from therapy.schemas import Drug, MatchType, MatchesKeyed
 from therapy.database import Database
 
+
 TEST_ROOT = Path(__file__).resolve().parents[1]
+TEST_DATA_DIRECTORY = TEST_ROOT / "tests" / "unit" / "data"
+
+
+@pytest.fixture(scope="session")
+def test_data():
+    """Provide test data location to test modules"""
+    return TEST_DATA_DIRECTORY
 
 
 @pytest.fixture(scope="module", autouse=True)
@@ -23,15 +31,13 @@ def __init__(self):
                 self.load_test_data()
 
         def load_test_data(self) -> None:
-            with open(f"{TEST_ROOT}/tests/unit/"
-                      f"data/therapies.json", "r") as f:
+            with open(TEST_DATA_DIRECTORY / "therapies.json", "r") as f:
                 therapies = json.load(f)
                 with self.db.therapies.batch_writer() as batch:
                     for therapy in therapies:
                         batch.put_item(Item=therapy)
 
-            with open(f"{TEST_ROOT}/tests/unit/"
-                      f"data/metadata.json", "r") as f:
+            with open(TEST_DATA_DIRECTORY / "metadata.json", "r") as f:
                 metadata = json.load(f)
                 with self.db.metadata.batch_writer() as batch:
                     for m in metadata:
@@ -57,7 +63,7 @@ def __init__(self):
             `self.updates` stores update requests, with the concept_id as the key, and
             a dict of {new_attribute: new_value} as the value.
             """
-            infile = TEST_ROOT / "tests" / "unit" / "data" / "therapies.json"
+            infile = TEST_DATA_DIRECTORY / "therapies.json"
             self.records = {}
             with open(infile, "r") as f:
                 records_json = json.load(f)
@@ -74,7 +80,7 @@ def __init__(self):
             self.added_records: Dict[str, Dict[Any, Any]] = {}
             self.updates: Dict[str, Dict[Any, Any]] = {}
 
-            meta = TEST_ROOT / "tests" / "unit" / "data" / "metadata.json"
+            meta = TEST_DATA_DIRECTORY / "metadata.json"
             with open(meta, "r") as f:
                 meta_json = json.load(f)
             self.cached_sources = {}
@@ -159,30 +165,47 @@ def update_record(self, concept_id: str, attribute: str,
     return MockDatabase
 
 
-def compare_records(actual: Dict, fixt: Drug):
+def compare_records(actual: Drug, fixt: Drug):
     """Check that identity records are identical."""
-    fixture = fixt.dict()
-    assert actual["concept_id"] == fixture["concept_id"]
-    assert actual["label"] == fixture["label"]
-    assert set(actual["aliases"]) == set(fixture["aliases"])
-    assert set(actual["trade_names"]) == set(fixture["trade_names"])
-    assert set(actual["xrefs"]) == set(fixture["xrefs"])
-    assert set(actual["associated_with"]) == set(fixture["associated_with"])
-    if actual["approval_rating"] or fixture["approval_rating"]:
-        assert actual["approval_rating"] == fixture["approval_rating"]
-    if actual["approval_year"] or fixture["approval_year"]:
-        assert set(actual["approval_year"]) == set(fixture["approval_year"])
-    if actual["has_indication"] or fixture["has_indication"]:
-        actual_inds = actual["has_indication"].copy()
-        fixture_inds = fixture["has_indication"].copy()
+    assert actual.concept_id == fixt.concept_id
+    assert actual.label == fixt.label
+
+    assert (actual.aliases is None) == (fixt.aliases is None)
+    if (actual.aliases is not None) and (fixt.aliases is not None):
+        assert set(actual.aliases) == set(fixt.aliases)
+
+    assert (actual.trade_names is None) == (fixt.trade_names is None)
+    if (actual.trade_names is not None) and (fixt.trade_names is not None):
+        assert set(actual.trade_names) == set(fixt.trade_names)
+
+    assert (actual.xrefs is None) == (fixt.xrefs is None)
+    if (actual.xrefs is not None) and (fixt.xrefs is not None):
+        assert set(actual.xrefs) == set(fixt.xrefs)
+
+    assert (actual.associated_with is None) == (fixt.associated_with is None)
+    if (actual.associated_with is not None) and (fixt.associated_with is not None):
+        assert set(actual.associated_with) == set(fixt.associated_with)
+
+    assert (not actual.approval_ratings) == (not fixt.approval_ratings)
+    if (actual.approval_ratings) and (fixt.approval_ratings):
+        assert set(actual.approval_ratings) == set(fixt.approval_ratings)
+
+    assert (actual.approval_year is None) == (fixt.approval_year is None)
+    if (actual.approval_year is not None) and (fixt.approval_year is not None):
+        assert set(actual.approval_year) == set(fixt.approval_year)
+
+    assert (actual.has_indication is None) == (fixt.has_indication is None)
+    if (actual.has_indication is not None) and (fixt.has_indication is not None):
+        actual_inds = actual.has_indication.copy()
+        fixture_inds = fixt.has_indication.copy()
         assert len(actual_inds) == len(fixture_inds)
-        actual_inds.sort(key=lambda x: x["disease_id"])
-        fixture_inds.sort(key=lambda x: x["disease_id"])
+        actual_inds.sort(key=lambda x: x.disease_id)
+        fixture_inds.sort(key=lambda x: x.disease_id)
         for i in range(len(actual_inds)):
             assert actual_inds[i] == fixture_inds[i]
 
 
-def compare_response(response: Dict, match_type: MatchType,
+def compare_response(response: MatchesKeyed, match_type: MatchType,
                      fixture: Drug = None, fixture_list: List[Drug] = None,
                      num_records: int = 0):
     """Check that test response is correct. Only 1 of {fixture, fixture_list}
@@ -204,17 +227,17 @@ def compare_response(response: Dict, match_type: MatchType,
         raise Exception("`num_records` should only be given with "
                         "`fixture_list`.")
 
-    assert response["match_type"] == match_type
+    assert response.match_type == match_type
     if fixture:
-        assert len(response["records"]) == 1
-        compare_records(response["records"][0], fixture)
+        assert len(response.records) == 1
+        compare_records(response.records[0], fixture)
     elif fixture_list:
         if not num_records:
-            assert len(response["records"]) == len(fixture_list)
+            assert len(response.records) == len(fixture_list)
         else:
-            assert len(response["records"]) == num_records
+            assert len(response.records) == num_records
         for fixt in fixture_list:
-            for record in response["records"]:
+            for record in response.records:
                 if fixt.concept_id == record.concept_id:
                     compare_records(record, fixt)
                     break
diff --git a/tests/unit/data/test_chembl_data.json b/tests/unit/data/test_chembl_data.json
new file mode 100644
index 00000000..249aedc7
--- /dev/null
+++ b/tests/unit/data/test_chembl_data.json
@@ -0,0 +1,1558 @@
+{
+  "cisplatin": {
+    "concept_id": "chembl:CHEMBL11359",
+    "label": "CISPLATIN",
+    "aliases": [
+      "Cis-platinum ii",
+      "NSC-119875",
+      "Liplacis",
+      "cis-diamminedichloroplatinum(II)",
+      "INT230-6 COMPONENT CISPLATIN",
+      "Cisplatinum",
+      "CIS-DDP",
+      "INT-230-6 COMPONENT CISPLATIN"
+    ],
+    "trade_names": [
+      "PLATINOL",
+      "Platinol",
+      "Platinol-aq",
+      "Cisplatin",
+      "PLATINOL-AQ"
+    ],
+    "xrefs": [],
+    "associated_with": [],
+    "approval_ratings": ["chembl_phase_4"],
+    "approval_year": [],
+    "has_indication": [
+      {
+        "disease_id": "mesh:D016545",
+        "disease_label": "Choroid Plexus Neoplasms",
+        "normalized_disease_id": "ncit:C4533",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D005910",
+        "disease_label": "Glioma",
+        "normalized_disease_id": "ncit:C3059",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D005185",
+        "disease_label": "Fallopian Tube Neoplasms",
+        "normalized_disease_id": "ncit:C3867",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D009101",
+        "disease_label": "Multiple Myeloma",
+        "normalized_disease_id": "ncit:C3242",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D010190",
+        "disease_label": "Pancreatic Neoplasms",
+        "normalized_disease_id": "ncit:C3305",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D009190",
+        "disease_label": "Myelodysplastic Syndromes",
+        "normalized_disease_id": "ncit:C3247",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D064129",
+        "disease_label": "Prostatic Neoplasms, Castration-Resistant",
+        "normalized_disease_id": "DOID:0080909",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D018285",
+        "disease_label": "Klatskin Tumor",
+        "normalized_disease_id": "ncit:C36077",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_1" }
+      },
+      {
+        "disease_id": "mesh:D012175",
+        "disease_label": "Retinoblastoma",
+        "normalized_disease_id": "ncit:C7541",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D009303",
+        "disease_label": "Nasopharyngeal Neoplasms",
+        "normalized_disease_id": "ncit:C3257",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D055752",
+        "disease_label": "Small Cell Lung Carcinoma",
+        "normalized_disease_id": "ncit:C4917",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D009369",
+        "disease_label": "Neoplasms",
+        "normalized_disease_id": "ncit:C3262",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_4" }
+      },
+      {
+        "disease_id": "mesh:D001005",
+        "disease_label": "Anus Neoplasms",
+        "normalized_disease_id": "ncit:C2877",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D031901",
+        "disease_label": "Gestational Trophoblastic Disease",
+        "normalized_disease_id": "ncit:C4699",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D006689",
+        "disease_label": "Hodgkin Disease",
+        "normalized_disease_id": "ncit:C9357",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D015266",
+        "disease_label": "Carcinoma, Merkel Cell",
+        "normalized_disease_id": "ncit:C9231",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_1" }
+      },
+      {
+        "disease_id": "EFO:1000043",
+        "disease_label": "ovarian serous cystadenocarcinoma",
+        "normalized_disease_id": "ncit:C7978",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_1" }
+      },
+      {
+        "disease_id": "mesh:D010610",
+        "disease_label": "Pharyngeal Neoplasms",
+        "normalized_disease_id": "ncit:C7545",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D014594",
+        "disease_label": "Uterine Neoplasms",
+        "normalized_disease_id": "ncit:C3552",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D018273",
+        "disease_label": "Carcinoma, Islet Cell",
+        "normalized_disease_id": "ncit:C3770",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D018278",
+        "disease_label": "Carcinoma, Neuroendocrine",
+        "normalized_disease_id": "ncit:C3773",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D052016",
+        "disease_label": "Mucositis",
+        "normalized_disease_id": "ncit:C3853",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D002280",
+        "disease_label": "Carcinoma, Basal Cell",
+        "normalized_disease_id": "ncit:C156767",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_1" }
+      },
+      {
+        "disease_id": "mesh:D005706",
+        "disease_label": "Gallbladder Neoplasms",
+        "normalized_disease_id": "ncit:C7481",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D002276",
+        "disease_label": "Carcinoid Tumor",
+        "normalized_disease_id": "ncit:C2915",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D013964",
+        "disease_label": "Thyroid Neoplasms",
+        "normalized_disease_id": "ncit:C7510",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_1" }
+      },
+      {
+        "disease_id": "mesh:D002292",
+        "disease_label": "Carcinoma, Renal Cell",
+        "normalized_disease_id": "mondo:0005086",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D020250",
+        "disease_label": "Postoperative Nausea and Vomiting",
+        "normalized_disease_id": null,
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D009447",
+        "disease_label": "Neuroblastoma",
+        "normalized_disease_id": "ncit:C3270",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D001749",
+        "disease_label": "Urinary Bladder Neoplasms",
+        "normalized_disease_id": "ncit:C9334",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "EFO:0009708",
+        "disease_label": "metastasis",
+        "normalized_disease_id": "ncit:C3261",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D018269",
+        "disease_label": "Carcinoma, Endometrioid",
+        "normalized_disease_id": "ncit:C7558",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_1" }
+      },
+      {
+        "disease_id": "mesh:D007822",
+        "disease_label": "Laryngeal Neoplasms",
+        "normalized_disease_id": "ncit:C3156",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D006258",
+        "disease_label": "Head and Neck Neoplasms",
+        "normalized_disease_id": "ncit:C4013",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D018239",
+        "disease_label": "Seminoma",
+        "normalized_disease_id": "ncit:C9309",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D000230",
+        "disease_label": "Adenocarcinoma",
+        "normalized_disease_id": "ncit:C2852",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D014987",
+        "disease_label": "Xerostomia",
+        "normalized_disease_id": null,
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_1" }
+      },
+      {
+        "disease_id": "EFO:0005570",
+        "disease_label": "oral cavity cancer",
+        "normalized_disease_id": "ncit:C9314",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D001932",
+        "disease_label": "Brain Neoplasms",
+        "normalized_disease_id": "ncit:C3568",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D058922",
+        "disease_label": "Inflammatory Breast Neoplasms",
+        "normalized_disease_id": "ncit:C4001",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D016543",
+        "disease_label": "Central Nervous System Neoplasms",
+        "normalized_disease_id": "ncit:C4627",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D007012",
+        "disease_label": "Hypopharyngeal Neoplasms",
+        "normalized_disease_id": "ncit:C7190",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D008223",
+        "disease_label": "Lymphoma",
+        "normalized_disease_id": "ncit:C3208",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D000077192",
+        "disease_label": "Adenocarcinoma of Lung",
+        "normalized_disease_id": "ncit:C3512",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D008527",
+        "disease_label": "Medulloblastoma",
+        "normalized_disease_id": "ncit:C3222",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D018312",
+        "disease_label": "Sex Cord-Gonadal Stromal Tumors",
+        "normalized_disease_id": "ncit:C3794",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D013280",
+        "disease_label": "Stomatitis",
+        "normalized_disease_id": "ncit:C26887",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D064726",
+        "disease_label": "Triple Negative Breast Neoplasms",
+        "normalized_disease_id": "ncit:C71732",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D009373",
+        "disease_label": "Neoplasms, Germ Cell and Embryonal",
+        "normalized_disease_id": "ncit:C3708",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D021441",
+        "disease_label": "Carcinoma, Pancreatic Ductal",
+        "normalized_disease_id": "ncit:C9120",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D018305",
+        "disease_label": "Ganglioneuroblastoma",
+        "normalized_disease_id": "ncit:C3790",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D010534",
+        "disease_label": "Peritoneal Neoplasms",
+        "normalized_disease_id": "ncit:C3322",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D007674",
+        "disease_label": "Kidney Diseases",
+        "normalized_disease_id": "ncit:C3149",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_1" }
+      },
+      {
+        "disease_id": "mesh:D010412",
+        "disease_label": "Penile Neoplasms",
+        "normalized_disease_id": "ncit:C3317",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D010255",
+        "disease_label": "Paranasal Sinus Neoplasms",
+        "normalized_disease_id": "ncit:C6014",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D010996",
+        "disease_label": "Pleural Effusion",
+        "normalized_disease_id": null,
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D001661",
+        "disease_label": "Biliary Tract Neoplasms",
+        "normalized_disease_id": "mondo:0003060",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D012509",
+        "disease_label": "Sarcoma",
+        "normalized_disease_id": "ncit:C9118",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D009325",
+        "disease_label": "Nausea",
+        "normalized_disease_id": null,
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D018197",
+        "disease_label": "Hepatoblastoma",
+        "normalized_disease_id": "ncit:C3728",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D012208",
+        "disease_label": "Rhabdomyosarcoma",
+        "normalized_disease_id": "ncit:C3359",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_0" }
+      },
+      {
+        "disease_id": "mesh:D013274",
+        "disease_label": "Stomach Neoplasms",
+        "normalized_disease_id": "ncit:C3387",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D014846",
+        "disease_label": "Vulvar Neoplasms",
+        "normalized_disease_id": "ncit:C7502",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D013953",
+        "disease_label": "Thymus Neoplasms",
+        "normalized_disease_id": "ncit:C4962",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D020522",
+        "disease_label": "Lymphoma, Mantle-Cell",
+        "normalized_disease_id": "ncit:C4337",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D007938",
+        "disease_label": "Leukemia",
+        "normalized_disease_id": "ncit:C3161",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D016411",
+        "disease_label": "Lymphoma, T-Cell, Peripheral",
+        "normalized_disease_id": "ncit:C3468",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D015179",
+        "disease_label": "Colorectal Neoplasms",
+        "normalized_disease_id": "ncit:C2956",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D013945",
+        "disease_label": "Thymoma",
+        "normalized_disease_id": "ncit:C3411",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D018242",
+        "disease_label": "Neuroectodermal Tumors, Primitive",
+        "normalized_disease_id": "ncit:C3222",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D004066",
+        "disease_label": "Digestive System Diseases",
+        "normalized_disease_id": "ncit:C3959",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D008654",
+        "disease_label": "Mesothelioma",
+        "normalized_disease_id": "ncit:C3234",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D013724",
+        "disease_label": "Teratoma",
+        "normalized_disease_id": "ncit:C3403",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D016889",
+        "disease_label": "Endometrial Neoplasms",
+        "normalized_disease_id": "ncit:C3012",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D008107",
+        "disease_label": "Liver Diseases",
+        "normalized_disease_id": "ncit:C3196",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_1" }
+      },
+      {
+        "disease_id": "mesh:D015459",
+        "disease_label": "Leukemia-Lymphoma, Adult T-Cell",
+        "normalized_disease_id": "ncit:C3184",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D016403",
+        "disease_label": "Lymphoma, Large B-Cell, Diffuse",
+        "normalized_disease_id": "ncit:C8851",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D009959",
+        "disease_label": "Oropharyngeal Neoplasms",
+        "normalized_disease_id": "ncit:C7398",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D014523",
+        "disease_label": "Urethral Neoplasms",
+        "normalized_disease_id": "ncit:C3619",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D012516",
+        "disease_label": "Osteosarcoma",
+        "normalized_disease_id": "ncit:C53707",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D014062",
+        "disease_label": "Tongue Neoplasms",
+        "normalized_disease_id": "ncit:C9345",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D014565",
+        "disease_label": "Urogenital Neoplasms",
+        "normalized_disease_id": "mondo:0025370",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D008113",
+        "disease_label": "Liver Neoplasms",
+        "normalized_disease_id": "ncit:C34803",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D000077195",
+        "disease_label": "Squamous Cell Carcinoma of Head and Neck",
+        "normalized_disease_id": "ncit:C4044",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D007119",
+        "disease_label": "Immunoblastic Lymphadenopathy",
+        "normalized_disease_id": "ncit:C7528",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D013736",
+        "disease_label": "Testicular Neoplasms",
+        "normalized_disease_id": "ncit:C7251",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D006528",
+        "disease_label": "Carcinoma, Hepatocellular",
+        "normalized_disease_id": "ncit:C3099",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D018236",
+        "disease_label": "Carcinoma, Embryonal",
+        "normalized_disease_id": "ncit:C3752",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D001943",
+        "disease_label": "Breast Neoplasms",
+        "normalized_disease_id": "ncit:C2910",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D002294",
+        "disease_label": "Carcinoma, Squamous Cell",
+        "normalized_disease_id": "ncit:C2929",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D000740",
+        "disease_label": "Anemia",
+        "normalized_disease_id": "ncit:C2869",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D008175",
+        "disease_label": "Lung Neoplasms",
+        "normalized_disease_id": "ncit:C3200",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D008228",
+        "disease_label": "Lymphoma, Non-Hodgkin",
+        "normalized_disease_id": "ncit:C3211",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D017728",
+        "disease_label": "Lymphoma, Large-Cell, Anaplastic",
+        "normalized_disease_id": "ncit:C3720",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D010051",
+        "disease_label": "Ovarian Neoplasms",
+        "normalized_disease_id": "ncit:C7431",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D008224",
+        "disease_label": "Lymphoma, Follicular",
+        "normalized_disease_id": "ncit:C3209",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D007680",
+        "disease_label": "Kidney Neoplasms",
+        "normalized_disease_id": "ncit:C7548",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D004067",
+        "disease_label": "Digestive System Neoplasms",
+        "normalized_disease_id": "ncit:C4890",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_1" }
+      },
+      {
+        "disease_id": "mesh:D002277",
+        "disease_label": "Carcinoma",
+        "normalized_disease_id": "ncit:C2916",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D046152",
+        "disease_label": "Gastrointestinal Stromal Tumors",
+        "normalized_disease_id": "ncit:C3868",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D004806",
+        "disease_label": "Ependymoma",
+        "normalized_disease_id": "ncit:C3017",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D002289",
+        "disease_label": "Carcinoma, Non-Small-Cell Lung",
+        "normalized_disease_id": "ncit:C2926",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D002583",
+        "disease_label": "Uterine Cervical Neoplasms",
+        "normalized_disease_id": "ncit:C9311",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D008479",
+        "disease_label": "Mediastinal Neoplasms",
+        "normalized_disease_id": "ncit:C3549",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D006103",
+        "disease_label": "Granuloma, Lethal Midline",
+        "normalized_disease_id": "mondo:0006828",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D008288",
+        "disease_label": "Malaria",
+        "normalized_disease_id": "ncit:C34797",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D000306",
+        "disease_label": "Adrenal Cortex Neoplasms",
+        "normalized_disease_id": "ncit:C9325",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D018240",
+        "disease_label": "Endodermal Sinus Tumor",
+        "normalized_disease_id": "ncit:C3011",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D004938",
+        "disease_label": "Esophageal Neoplasms",
+        "normalized_disease_id": "ncit:C7478",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D012468",
+        "disease_label": "Salivary Gland Neoplasms",
+        "normalized_disease_id": "ncit:C3811",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "EFO:0003868",
+        "disease_label": "mouth neoplasm",
+        "normalized_disease_id": "ncit:C7606",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D002822",
+        "disease_label": "Choriocarcinoma",
+        "normalized_disease_id": "ncit:C2948",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D018281",
+        "disease_label": "Cholangiocarcinoma",
+        "normalized_disease_id": "ncit:C4436",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D016483",
+        "disease_label": "Lymphoma, AIDS-Related",
+        "normalized_disease_id": "ncit:C3471",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D008545",
+        "disease_label": "Melanoma",
+        "normalized_disease_id": "ncit:C3224",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      }
+    ]
+  },
+
+  "l745870": {
+    "label": "L-745870",
+    "concept_id": "chembl:CHEMBL267014",
+    "aliases": [],
+    "approval_ratings": ["chembl_phase_0"],
+    "xrefs": [],
+    "associated_with": [],
+    "trade_names": []
+  },
+  "aspirin": {
+    "concept_id": "chembl:CHEMBL25",
+    "label": "ASPIRIN",
+    "aliases": [
+      "Acetylsalicylic Acid",
+      "NSC-406186",
+      "BAY1019036",
+      "NSC-27223",
+      "Acetylsalicylic acid",
+      "Aspirin"
+    ],
+    "trade_names": [],
+    "xrefs": [],
+    "associated_with": [],
+    "approval_ratings": ["chembl_phase_4"],
+    "approval_year": [],
+    "has_indication": [
+      {
+        "disease_id": "mesh:D012214",
+        "disease_label": "Rheumatic Heart Disease",
+        "normalized_disease_id": "ncit:C34882",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D064129",
+        "disease_label": "Prostatic Neoplasms, Castration-Resistant",
+        "normalized_disease_id": "DOID:0080909",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D010051",
+        "disease_label": "Ovarian Neoplasms",
+        "normalized_disease_id": "ncit:C7431",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D010003",
+        "disease_label": "Osteoarthritis",
+        "normalized_disease_id": "ncit:C3293",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D010518",
+        "disease_label": "Periodontitis",
+        "normalized_disease_id": "ncit:C34918",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D002544",
+        "disease_label": "Cerebral Infarction",
+        "normalized_disease_id": "ncit:C50486",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D003930",
+        "disease_label": "Diabetic Retinopathy",
+        "normalized_disease_id": "ncit:C34538",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D010437",
+        "disease_label": "Peptic Ulcer",
+        "normalized_disease_id": "ncit:C3318",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D012559",
+        "disease_label": "Schizophrenia",
+        "normalized_disease_id": "mondo:0005090",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D009101",
+        "disease_label": "Multiple Myeloma",
+        "normalized_disease_id": "ncit:C3242",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D014808",
+        "disease_label": "Vitamin D Deficiency",
+        "normalized_disease_id": "ncit:C114830",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D014652",
+        "disease_label": "Vascular Diseases",
+        "normalized_disease_id": "ncit:C35117",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D009203",
+        "disease_label": "Myocardial Infarction",
+        "normalized_disease_id": "ncit:C27996",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D006261",
+        "disease_label": "Headache",
+        "normalized_disease_id": null,
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D019851",
+        "disease_label": "Thrombophilia",
+        "normalized_disease_id": "ncit:C84479",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D002386",
+        "disease_label": "Cataract",
+        "normalized_disease_id": "ncit:C26713",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D001766",
+        "disease_label": "Blindness",
+        "normalized_disease_id": "ncit:C97109",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D017202",
+        "disease_label": "Myocardial Ischemia",
+        "normalized_disease_id": "ncit:C50625",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D011024",
+        "disease_label": "Pneumonia, Viral",
+        "normalized_disease_id": "mondo:0006012",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D012170",
+        "disease_label": "Retinal Vein Occlusion",
+        "normalized_disease_id": "ncit:C34981",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D007249",
+        "disease_label": "Inflammation",
+        "normalized_disease_id": null,
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_1" }
+      },
+      {
+        "disease_id": "mesh:D006562",
+        "disease_label": "Herpes Zoster",
+        "normalized_disease_id": "ncit:C71079",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_1" }
+      },
+      {
+        "disease_id": "mesh:D011125",
+        "disease_label": "Adenomatous Polyposis Coli",
+        "normalized_disease_id": "ncit:C3339",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D014376",
+        "disease_label": "Tuberculosis",
+        "normalized_disease_id": "ncit:C3423",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D000083242",
+        "disease_label": "Ischemic Stroke",
+        "normalized_disease_id": "ncit:C95802",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D011471",
+        "disease_label": "Prostatic Neoplasms",
+        "normalized_disease_id": "ncit:C7378",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D000755",
+        "disease_label": "Anemia, Sickle Cell",
+        "normalized_disease_id": "ncit:C34383",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_1" }
+      },
+      {
+        "disease_id": "mesh:D017116",
+        "disease_label": "Low Back Pain",
+        "normalized_disease_id": null,
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D001471",
+        "disease_label": "Barrett Esophagus",
+        "normalized_disease_id": "ncit:C2891",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D006561",
+        "disease_label": "Herpes Simplex",
+        "normalized_disease_id": "mondo:0004609",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_1" }
+      },
+      {
+        "disease_id": "mesh:D011225",
+        "disease_label": "Pre-Eclampsia",
+        "normalized_disease_id": "ncit:C85021",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D004381",
+        "disease_label": "Duodenal Ulcer",
+        "normalized_disease_id": "ncit:C26755",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D058729",
+        "disease_label": "Peripheral Arterial Disease",
+        "normalized_disease_id": "ncit:C84496",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D006973",
+        "disease_label": "Hypertension",
+        "normalized_disease_id": "mondo:0005044",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D014456",
+        "disease_label": "Ulcer",
+        "normalized_disease_id": "mondo:0043839",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_1" }
+      },
+      {
+        "disease_id": "mesh:D005317",
+        "disease_label": "Fetal Growth Retardation",
+        "normalized_disease_id": "ncit:C114875",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D002532",
+        "disease_label": "Intracranial Aneurysm",
+        "normalized_disease_id": "mondo:0005291",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D006937",
+        "disease_label": "Hypercholesterolemia",
+        "normalized_disease_id": null,
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D001778",
+        "disease_label": "Blood Coagulation Disorders",
+        "normalized_disease_id": "ncit:C2902",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D014029",
+        "disease_label": "Tobacco Use Disorder",
+        "normalized_disease_id": "DOID:0050742",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D009303",
+        "disease_label": "Nasopharyngeal Neoplasms",
+        "normalized_disease_id": "ncit:C3257",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D007972",
+        "disease_label": "Leukoplakia, Oral",
+        "normalized_disease_id": "ncit:C3187",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_1" }
+      },
+      {
+        "disease_id": "mesh:D006976",
+        "disease_label": "Hypertension, Pulmonary",
+        "normalized_disease_id": "mondo:0005149",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D012128",
+        "disease_label": "Respiratory Distress Syndrome",
+        "normalized_disease_id": "mondo:0100130",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D010612",
+        "disease_label": "Pharyngitis",
+        "normalized_disease_id": "ncit:C26851",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D002318",
+        "disease_label": "Cardiovascular Diseases",
+        "normalized_disease_id": "ncit:C2931",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D015228",
+        "disease_label": "Hypertriglyceridemia",
+        "normalized_disease_id": "mondo:0005347",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_1" }
+      },
+      {
+        "disease_id": "mesh:D016491",
+        "disease_label": "Peripheral Vascular Diseases",
+        "normalized_disease_id": "ncit:C35136",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_0" }
+      },
+      {
+        "disease_id": "mesh:D013927",
+        "disease_label": "Thrombosis",
+        "normalized_disease_id": "ncit:C26891",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_4" }
+      },
+      {
+        "disease_id": "mesh:D008268",
+        "disease_label": "Macular Degeneration",
+        "normalized_disease_id": "ncit:C123330",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D003139",
+        "disease_label": "Common Cold",
+        "normalized_disease_id": "ncit:C34500",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D000026",
+        "disease_label": "Abortion, Habitual",
+        "normalized_disease_id": "mondo:0006774",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D004211",
+        "disease_label": "Disseminated Intravascular Coagulation",
+        "normalized_disease_id": "ncit:C2992",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D010020",
+        "disease_label": "Osteonecrosis",
+        "normalized_disease_id": "ncit:C34880",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D003110",
+        "disease_label": "Colonic Neoplasms",
+        "normalized_disease_id": "ncit:C2953",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D054556",
+        "disease_label": "Venous Thromboembolism",
+        "normalized_disease_id": "ncit:C99537",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D002537",
+        "disease_label": "Intracranial Arteriosclerosis",
+        "normalized_disease_id": "mondo:0001632",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D060050",
+        "disease_label": "Angina, Stable",
+        "normalized_disease_id": null,
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D003920",
+        "disease_label": "Diabetes Mellitus",
+        "normalized_disease_id": "ncit:C2985",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D007319",
+        "disease_label": "Sleep Initiation and Maintenance Disorders",
+        "normalized_disease_id": "mondo:0013600",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_0" }
+      },
+      {
+        "disease_id": "mesh:D045169",
+        "disease_label": "Severe Acute Respiratory Syndrome",
+        "normalized_disease_id": "ncit:C85064",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D003327",
+        "disease_label": "Coronary Disease",
+        "normalized_disease_id": "ncit:C26732",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D003123",
+        "disease_label": "Colorectal Neoplasms, Hereditary Nonpolyposis",
+        "normalized_disease_id": "ncit:C8494",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D006333",
+        "disease_label": "Heart Failure",
+        "normalized_disease_id": "ncit:C50577",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D029424",
+        "disease_label": "Pulmonary Disease, Chronic Obstructive",
+        "normalized_disease_id": "ncit:C3199",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D014647",
+        "disease_label": "Varicose Ulcer",
+        "normalized_disease_id": null,
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D001714",
+        "disease_label": "Bipolar Disorder",
+        "normalized_disease_id": "mondo:0004985",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D018805",
+        "disease_label": "Sepsis",
+        "normalized_disease_id": "ncit:C3364",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D020246",
+        "disease_label": "Venous Thrombosis",
+        "normalized_disease_id": "mondo:0008559",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D012131",
+        "disease_label": "Respiratory Insufficiency",
+        "normalized_disease_id": "ncit:C26872",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D010146",
+        "disease_label": "Pain",
+        "normalized_disease_id": null,
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_4" }
+      },
+      {
+        "disease_id": "mesh:D013274",
+        "disease_label": "Stomach Neoplasms",
+        "normalized_disease_id": "ncit:C3387",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D010927",
+        "disease_label": "Placental Insufficiency",
+        "normalized_disease_id": "mondo:0005919",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D008881",
+        "disease_label": "Migraine Disorders",
+        "normalized_disease_id": "ncit:C89715",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_4" }
+      },
+      {
+        "disease_id": "mesh:D006471",
+        "disease_label": "Gastrointestinal Hemorrhage",
+        "normalized_disease_id": null,
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D013920",
+        "disease_label": "Thrombocythemia, Essential",
+        "normalized_disease_id": "ncit:C3407",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D054058",
+        "disease_label": "Acute Coronary Syndrome",
+        "normalized_disease_id": "ncit:C53652",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D001249",
+        "disease_label": "Asthma",
+        "normalized_disease_id": "ncit:C28397",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D015179",
+        "disease_label": "Colorectal Neoplasms",
+        "normalized_disease_id": "ncit:C2956",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D005221",
+        "disease_label": "Fatigue",
+        "normalized_disease_id": null,
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_0" }
+      },
+      {
+        "disease_id": "mesh:D005909",
+        "disease_label": "Glioblastoma",
+        "normalized_disease_id": "ncit:C3058",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D015658",
+        "disease_label": "HIV Infections",
+        "normalized_disease_id": "ncit:C3108",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D014947",
+        "disease_label": "Wounds and Injuries",
+        "normalized_disease_id": "mondo:0021178",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D020521",
+        "disease_label": "Stroke",
+        "normalized_disease_id": "ncit:C3390",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_4" }
+      },
+      {
+        "disease_id": "mesh:D004066",
+        "disease_label": "Digestive System Diseases",
+        "normalized_disease_id": "ncit:C3959",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_1" }
+      },
+      {
+        "disease_id": "mesh:D000077192",
+        "disease_label": "Adenocarcinoma of Lung",
+        "normalized_disease_id": "ncit:C3512",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_0" }
+      },
+      {
+        "disease_id": "mesh:D012004",
+        "disease_label": "Rectal Neoplasms",
+        "normalized_disease_id": "ncit:C3350",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D003093",
+        "disease_label": "Colitis, Ulcerative",
+        "normalized_disease_id": "ncit:C2952",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D011247",
+        "disease_label": "Pregnancy",
+        "normalized_disease_id": null,
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D002583",
+        "disease_label": "Uterine Cervical Neoplasms",
+        "normalized_disease_id": "ncit:C9311",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D018781",
+        "disease_label": "Tension-Type Headache",
+        "normalized_disease_id": null,
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D009369",
+        "disease_label": "Neoplasms",
+        "normalized_disease_id": "ncit:C3262",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D003924",
+        "disease_label": "Diabetes Mellitus, Type 2",
+        "normalized_disease_id": "ncit:C26747",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D006331",
+        "disease_label": "Heart Diseases",
+        "normalized_disease_id": "ncit:C3079",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D062788",
+        "disease_label": "Adenomyosis",
+        "normalized_disease_id": "ncit:C6996",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_0" }
+      },
+      {
+        "disease_id": "mesh:D006258",
+        "disease_label": "Head and Neck Neoplasms",
+        "normalized_disease_id": "ncit:C4013",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_1" }
+      },
+      {
+        "disease_id": "mesh:D011618",
+        "disease_label": "Psychotic Disorders",
+        "normalized_disease_id": "mondo:0001265",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D003865",
+        "disease_label": "Depressive Disorder, Major",
+        "normalized_disease_id": "mondo:0002009",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D001024",
+        "disease_label": "Aortic Valve Stenosis",
+        "normalized_disease_id": "mondo:0004978",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D056586",
+        "disease_label": "Acute Chest Syndrome",
+        "normalized_disease_id": "ncit:C138179",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D009080",
+        "disease_label": "Mucocutaneous Lymph Node Syndrome",
+        "normalized_disease_id": "ncit:C34825",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D061218",
+        "disease_label": "Depressive Disorder, Treatment-Resistant",
+        "normalized_disease_id": null,
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D051436",
+        "disease_label": "Renal Insufficiency, Chronic",
+        "normalized_disease_id": "ncit:C9438",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D050197",
+        "disease_label": "Atherosclerosis",
+        "normalized_disease_id": "ncit:C35768",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D020520",
+        "disease_label": "Brain Infarction",
+        "normalized_disease_id": "mondo:0005394",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D011087",
+        "disease_label": "Polycythemia Vera",
+        "normalized_disease_id": "ncit:C3336",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D055371",
+        "disease_label": "Acute Lung Injury",
+        "normalized_disease_id": "mondo:0015796",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D006528",
+        "disease_label": "Carcinoma, Hepatocellular",
+        "normalized_disease_id": "ncit:C3099",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D000072658",
+        "disease_label": "Non-ST Elevated Myocardial Infarction",
+        "normalized_disease_id": null,
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D002546",
+        "disease_label": "Ischemic Attack, Transient",
+        "normalized_disease_id": "ncit:C50781",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D001943",
+        "disease_label": "Breast Neoplasms",
+        "normalized_disease_id": "ncit:C2910",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D016893",
+        "disease_label": "Carotid Stenosis",
+        "normalized_disease_id": "ncit:C95804",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D002312",
+        "disease_label": "Cardiomyopathy, Hypertrophic",
+        "normalized_disease_id": "ncit:C34449",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D006470",
+        "disease_label": "Hemorrhage",
+        "normalized_disease_id": null,
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D001281",
+        "disease_label": "Atrial Fibrillation",
+        "normalized_disease_id": "ncit:C50466",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D002294",
+        "disease_label": "Carcinoma, Squamous Cell",
+        "normalized_disease_id": "ncit:C2929",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "EFO:0008585",
+        "disease_label": "ST Elevation Myocardial Infarction",
+        "normalized_disease_id": "mondo:0041656",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D007246",
+        "disease_label": "Infertility",
+        "normalized_disease_id": "mondo:0005047",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D015356",
+        "disease_label": "Retinal Artery Occlusion",
+        "normalized_disease_id": "ncit:C34978",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D008545",
+        "disease_label": "Melanoma",
+        "normalized_disease_id": "ncit:C3224",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D007511",
+        "disease_label": "Ischemia",
+        "normalized_disease_id": "mondo:0005053",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "EFO:0000339",
+        "disease_label": "chronic myelogenous leukemia",
+        "normalized_disease_id": "ncit:C3174",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D011014",
+        "disease_label": "Pneumonia",
+        "normalized_disease_id": "ncit:C3333",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D008581",
+        "disease_label": "Meningitis",
+        "normalized_disease_id": "ncit:C79598",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D024821",
+        "disease_label": "Metabolic Syndrome",
+        "normalized_disease_id": "mondo:0011565",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D000236",
+        "disease_label": "Adenoma",
+        "normalized_disease_id": "ncit:C2855",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D005334",
+        "disease_label": "Fever",
+        "normalized_disease_id": null,
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_4" }
+      },
+      {
+        "disease_id": "mesh:D002289",
+        "disease_label": "Carcinoma, Non-Small-Cell Lung",
+        "normalized_disease_id": "ncit:C2926",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D002561",
+        "disease_label": "Cerebrovascular Disorders",
+        "normalized_disease_id": "ncit:C2938",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D013276",
+        "disease_label": "Stomach Ulcer",
+        "normalized_disease_id": "ncit:C3388",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "mesh:D008180",
+        "disease_label": "Lupus Erythematosus, Systemic",
+        "normalized_disease_id": "ncit:C3201",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D016889",
+        "disease_label": "Endometrial Neoplasms",
+        "normalized_disease_id": "ncit:C3012",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_2" }
+      },
+      {
+        "disease_id": "mesh:D050723",
+        "disease_label": "Fractures, Bone",
+        "normalized_disease_id": "mondo:0005315",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_0" }
+      },
+      {
+        "disease_id": "mesh:D004938",
+        "disease_label": "Esophageal Neoplasms",
+        "normalized_disease_id": "ncit:C7478",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      },
+      {
+        "disease_id": "Orphanet:309005",
+        "disease_label": "Disorder of lipid metabolism",
+        "normalized_disease_id": "ncit:C97092",
+        "supplemental_info": { "chembl_max_phase_for_ind": "chembl_phase_3" }
+      }
+    ]
+  }
+}
diff --git a/tests/unit/data/test_merge_data.json b/tests/unit/data/test_merge_data.json
new file mode 100644
index 00000000..5bc2d740
--- /dev/null
+++ b/tests/unit/data/test_merge_data.json
@@ -0,0 +1,371 @@
+{
+  "phenobarbital": {
+    "label_and_type": "rxcui:8134##merger",
+    "concept_id": "rxcui:8134",
+    "xrefs": [
+      "ncit:C739",
+      "drugbank:DB01174",
+      "chemidplus:50-06-6",
+      "wikidata:Q407241",
+      "chembl:CHEMBL40",
+      "iuphar.ligand:2804"
+    ],
+    "aliases": [
+      "Phenylbarbital",
+      "PHENobarbital",
+      "Phenobarbitone",
+      "NSC-128143",
+      "5-Ethyl-5-phenyl-pyrimidine-2,4,6-trione",
+      "5-Phenyl-5-ethylbarbituric acid",
+      "5-ethyl-5-phenyl-1,3-diazinane-2,4,6-trione",
+      "Phenobarbituric Acid",
+      "Phenylethylbarbituric Acid",
+      "Acid, Phenylethylbarbituric",
+      "PHENOBARBITAL",
+      "phenobarbitone",
+      "Phenylethylbarbiturs\u00e4ure",
+      "5-Ethyl-5-phenylbarbituric acid",
+      "NSC-128143-",
+      "phenobarb",
+      "Luminal",
+      "5-ethyl-5-phenyl-2,4,6(1H,3H,5H)-pyrimidinetrione",
+      "PHENYLETHYLMALONYLUREA",
+      "Phenylethylbarbiturate",
+      "Luminal\u00ae",
+      "Phenemal",
+      "fenobarbital",
+      "Fenobarbital",
+      "Phenylethylbarbitursaeure",
+      "5-Ethyl-5-phenyl-2,4,6(1H,3H,5H)-pyrimidinetrione",
+      "phenylethylbarbiturate",
+      "Phenobarbital civ",
+      "Phenylaethylbarbitursaeure",
+      "Phenobarbitol",
+      "NSC-9848",
+      "Phenyl\u00e4thylbarbiturs\u00e4ure",
+      "phenobarbital",
+      "5-ethyl-5-phenylpyrimidine-2,4,6(1H,3H,5H)-trione",
+      "APRD00184",
+      "Phenylethylmalonylurea",
+      "PHENO",
+      "phenobarbital sodium",
+      "Phenobarbital"
+    ],
+    "trade_names": [
+      "Eskabarb",
+      "Solfoton",
+      "Phenobarbitone",
+      "Noptil",
+      "Luminal",
+      "Talpheno"
+    ],
+    "associated_with": [
+      "pubchem.compound:4763",
+      "usp:m63400",
+      "gsddb:2179",
+      "snomedct:51073002",
+      "vandf:4017422",
+      "mmsl:2390",
+      "msh:D010634",
+      "snomedct:373505007",
+      "mmsl:5272",
+      "unii:YQE403BP4D",
+      "fdbmk:001406",
+      "mmsl:d00340",
+      "atc:N03AA02",
+      "umls:C0031412",
+      "CHEBI:8069",
+      "inchikey:DDBREPKUVSBGFI-UHFFFAOYSA-N",
+      "drugcentral:2134",
+      "pubchem.substance:135650817"
+    ],
+    "label": "Phenobarbital",
+    "approval_ratings": [
+      "rxnorm_prescribable",
+      "chembl_phase_4",
+      "gtopdb_approved"
+    ],
+    "has_indication": [
+      "[\"mesh:D008223\", \"Lymphoma\", \"ncit:C3208\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D012559\", \"Schizophrenia\", \"mondo:0005090\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009503\", \"Neutropenia\", \"mondo:0001475\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D003866\", \"Depressive Disorder\", \"mondo:0002050\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001007\", \"Anxiety\", \"mondo:0011918\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D004827\", \"Epilepsy\", \"ncit:C3020\", {\"chembl_max_phase_for_ind\": \"chembl_phase_4\"}]",
+      "[\"mesh:D003704\", \"Dementia\", \"mondo:0001627\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009357\", \"Neonatal Abstinence Syndrome\", \"ncit:C87101\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D012640\", \"Seizures\", \"ncit:C3980\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D013226\", \"Status Epilepticus\", \"ncit:C85079\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001007\", \"Anxiety\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]"
+    ]
+  },
+  "cisplatin": {
+    "label_and_type": "rxcui:2555##merger",
+    "concept_id": "rxcui:2555",
+    "aliases": [
+      "cis-Diamminedichloroplatinum",
+      "Diamminodichloride, Platinum",
+      "INT230-6 COMPONENT CISPLATIN",
+      "cisplatinum",
+      "Platinol",
+      "cis-Diaminedichloroplatinum",
+      "cis-platinum",
+      "CISplatin",
+      "Cis-platinum ii",
+      "Liplacis",
+      "cis Diamminedichloroplatinum",
+      "NSC-119875",
+      "DACP",
+      "1,2-Diaminocyclohexaneplatinum II citrate",
+      "CIS-DDP",
+      "cis-Dichlorodiammineplatinum(II)",
+      "INT-230-6 COMPONENT CISPLATIN",
+      "Platinol-AQ",
+      "Cis-DDP",
+      "NSC 119875",
+      "APRD00359",
+      "CDDP",
+      "DDP",
+      "Dichlorodiammineplatinum",
+      "cis-Platinum",
+      "cis-diamminedichloroplatinum III",
+      "cisplatino",
+      "cis-diamminedichloroplatinum(II)",
+      "cis Platinum",
+      "Platinum Diamminodichloride",
+      "Cisplatinum",
+      "cis-Diamminedichloroplatinum(II)"
+    ],
+    "approval_ratings": [
+      "gtopdb_approved",
+      "rxnorm_prescribable",
+      "hemonc_approved",
+      "fda_prescription",
+      "chembl_phase_4"
+    ],
+    "approval_year": ["1978"],
+    "associated_with": [
+      "ndc:0703-5748",
+      "ndc:63323-103",
+      "ndc:70860-206",
+      "ndc:44567-509",
+      "spl:5a24d5bd-c44a-43f7-a04c-76caf3475012",
+      "usp:m17910",
+      "ndc:44567-530",
+      "pubchem.substance:178102005",
+      "spl:9b008181-ab66-db2f-e053-2995a90aad57",
+      "ndc:16729-288",
+      "spl:a66eda32-1164-439a-ac8e-73138365ec06",
+      "spl:dd45d777-d4c1-40ee-b4f0-c9e001a15a8c",
+      "CHEBI:27899",
+      "ndc:44567-511",
+      "ndc:0703-5747",
+      "ndc:68083-162",
+      "atc:L01XA01",
+      "mesh:D002945",
+      "ndc:44567-510",
+      "mmsl:31747",
+      "spl:2c569ef0-588f-4828-8b2d-03a2120c9b4c",
+      "vandf:4018139",
+      "inchikey:LXZZYRPGZAFOLE-UHFFFAOYSA-L",
+      "ndc:68083-163",
+      "inchikey:MOTIYCLHZZLHHQ-UHFFFAOYSA-N",
+      "spl:54b3415c-c095-4c82-b216-e0e6e6bb8d03",
+      "mmsl:d00195",
+      "spl:01c7a680-ee0d-42da-85e8-8d56c6fe7006",
+      "spl:c43de769-d6d8-3bb9-e053-2995a90a5aa2",
+      "unii:H8MTN7XVC2",
+      "ndc:68001-283",
+      "unii:Q20Q21Q62J",
+      "pubchem.compound:5702198",
+      "pubchem.compound:441203",
+      "ndc:0143-9505",
+      "spl:c3ddc4a5-9f1b-a8ee-e053-2a95a90a2265",
+      "mmsl:4456",
+      "umls:C0008838",
+      "ndc:0143-9504"
+    ],
+    "has_indication": [
+      "[\"hemonc:569\", \"Bladder cancer\", \"ncit:C9334\", {\"regulatory_body\": \"FDA\"}]",
+      "[\"hemonc:645\", \"Ovarian cancer\", \"ncit:C7431\", {\"regulatory_body\": \"FDA\"}]",
+      "[\"hemonc:671\", \"Testicular cancer\", \"ncit:C7251\", {\"regulatory_body\": \"FDA\"}]",
+      "[\"mesh:D016545\", \"Choroid Plexus Neoplasms\", \"ncit:C4533\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D005910\", \"Glioma\", \"ncit:C3059\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D005185\", \"Fallopian Tube Neoplasms\", \"ncit:C3867\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009101\", \"Multiple Myeloma\", \"ncit:C3242\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D010190\", \"Pancreatic Neoplasms\", \"ncit:C3305\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009190\", \"Myelodysplastic Syndromes\", \"ncit:C3247\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D064129\", \"Prostatic Neoplasms, Castration-Resistant\", \"DOID:0080909\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D018285\", \"Klatskin Tumor\", \"ncit:C36077\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D012175\", \"Retinoblastoma\", \"ncit:C7541\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009303\", \"Nasopharyngeal Neoplasms\", \"ncit:C3257\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D055752\", \"Small Cell Lung Carcinoma\", \"ncit:C4917\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009369\", \"Neoplasms\", \"ncit:C3262\", {\"chembl_max_phase_for_ind\": \"chembl_phase_4\"}]",
+      "[\"mesh:D001005\", \"Anus Neoplasms\", \"ncit:C2877\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D031901\", \"Gestational Trophoblastic Disease\", \"ncit:C4699\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D006689\", \"Hodgkin Disease\", \"ncit:C9357\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D015266\", \"Carcinoma, Merkel Cell\", \"ncit:C9231\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"EFO:1000043\", \"ovarian serous cystadenocarcinoma\", \"ncit:C7978\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D010610\", \"Pharyngeal Neoplasms\", \"ncit:C7545\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D014594\", \"Uterine Neoplasms\", \"ncit:C3552\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D018273\", \"Carcinoma, Islet Cell\", \"ncit:C3770\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D018278\", \"Carcinoma, Neuroendocrine\", \"ncit:C3773\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D052016\", \"Mucositis\", \"ncit:C3853\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002280\", \"Carcinoma, Basal Cell\", \"ncit:C156767\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D005706\", \"Gallbladder Neoplasms\", \"ncit:C7481\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002276\", \"Carcinoid Tumor\", \"ncit:C2915\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D013964\", \"Thyroid Neoplasms\", \"ncit:C7510\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D002292\", \"Carcinoma, Renal Cell\", \"mondo:0005086\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D020250\", \"Postoperative Nausea and Vomiting\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009447\", \"Neuroblastoma\", \"ncit:C3270\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001749\", \"Urinary Bladder Neoplasms\", \"ncit:C9334\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"EFO:0009708\", \"metastasis\", \"ncit:C3261\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D018269\", \"Carcinoma, Endometrioid\", \"ncit:C7558\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D007822\", \"Laryngeal Neoplasms\", \"ncit:C3156\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D006258\", \"Head and Neck Neoplasms\", \"ncit:C4013\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D018239\", \"Seminoma\", \"ncit:C9309\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D000230\", \"Adenocarcinoma\", \"ncit:C2852\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D014987\", \"Xerostomia\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"EFO:0005570\", \"oral cavity cancer\", \"ncit:C9314\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001932\", \"Brain Neoplasms\", \"ncit:C3568\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D058922\", \"Inflammatory Breast Neoplasms\", \"ncit:C4001\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D016543\", \"Central Nervous System Neoplasms\", \"ncit:C4627\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D007012\", \"Hypopharyngeal Neoplasms\", \"ncit:C7190\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008223\", \"Lymphoma\", \"ncit:C3208\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D000077192\", \"Adenocarcinoma of Lung\", \"ncit:C3512\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008527\", \"Medulloblastoma\", \"ncit:C3222\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D018312\", \"Sex Cord-Gonadal Stromal Tumors\", \"ncit:C3794\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D013280\", \"Stomatitis\", \"ncit:C26887\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D064726\", \"Triple Negative Breast Neoplasms\", \"ncit:C71732\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D009373\", \"Neoplasms, Germ Cell and Embryonal\", \"ncit:C3708\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D021441\", \"Carcinoma, Pancreatic Ductal\", \"ncit:C9120\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D018305\", \"Ganglioneuroblastoma\", \"ncit:C3790\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D010534\", \"Peritoneal Neoplasms\", \"ncit:C3322\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D007674\", \"Kidney Diseases\", \"ncit:C3149\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D010412\", \"Penile Neoplasms\", \"ncit:C3317\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D010255\", \"Paranasal Sinus Neoplasms\", \"ncit:C6014\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D010996\", \"Pleural Effusion\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001661\", \"Biliary Tract Neoplasms\", \"mondo:0003060\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D012509\", \"Sarcoma\", \"ncit:C9118\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009325\", \"Nausea\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D018197\", \"Hepatoblastoma\", \"ncit:C3728\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D012208\", \"Rhabdomyosarcoma\", \"ncit:C3359\", {\"chembl_max_phase_for_ind\": \"chembl_phase_0\"}]",
+      "[\"mesh:D013274\", \"Stomach Neoplasms\", \"ncit:C3387\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D014846\", \"Vulvar Neoplasms\", \"ncit:C7502\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D013953\", \"Thymus Neoplasms\", \"ncit:C4962\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D020522\", \"Lymphoma, Mantle-Cell\", \"ncit:C4337\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D007938\", \"Leukemia\", \"ncit:C3161\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D016411\", \"Lymphoma, T-Cell, Peripheral\", \"ncit:C3468\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D015179\", \"Colorectal Neoplasms\", \"ncit:C2956\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D013945\", \"Thymoma\", \"ncit:C3411\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D018242\", \"Neuroectodermal Tumors, Primitive\", \"ncit:C3222\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D004066\", \"Digestive System Diseases\", \"ncit:C3959\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D008654\", \"Mesothelioma\", \"ncit:C3234\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D013724\", \"Teratoma\", \"ncit:C3403\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D016889\", \"Endometrial Neoplasms\", \"ncit:C3012\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008107\", \"Liver Diseases\", \"ncit:C3196\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D015459\", \"Leukemia-Lymphoma, Adult T-Cell\", \"ncit:C3184\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D016403\", \"Lymphoma, Large B-Cell, Diffuse\", \"ncit:C8851\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009959\", \"Oropharyngeal Neoplasms\", \"ncit:C7398\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D014523\", \"Urethral Neoplasms\", \"ncit:C3619\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D012516\", \"Osteosarcoma\", \"ncit:C53707\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D014062\", \"Tongue Neoplasms\", \"ncit:C9345\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D014565\", \"Urogenital Neoplasms\", \"mondo:0025370\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008113\", \"Liver Neoplasms\", \"ncit:C34803\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D000077195\", \"Squamous Cell Carcinoma of Head and Neck\", \"ncit:C4044\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D007119\", \"Immunoblastic Lymphadenopathy\", \"ncit:C7528\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D013736\", \"Testicular Neoplasms\", \"ncit:C7251\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D006528\", \"Carcinoma, Hepatocellular\", \"ncit:C3099\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D018236\", \"Carcinoma, Embryonal\", \"ncit:C3752\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001943\", \"Breast Neoplasms\", \"ncit:C2910\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002294\", \"Carcinoma, Squamous Cell\", \"ncit:C2929\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D000740\", \"Anemia\", \"ncit:C2869\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008175\", \"Lung Neoplasms\", \"ncit:C3200\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008228\", \"Lymphoma, Non-Hodgkin\", \"ncit:C3211\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D017728\", \"Lymphoma, Large-Cell, Anaplastic\", \"ncit:C3720\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D010051\", \"Ovarian Neoplasms\", \"ncit:C7431\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008224\", \"Lymphoma, Follicular\", \"ncit:C3209\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D007680\", \"Kidney Neoplasms\", \"ncit:C7548\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D004067\", \"Digestive System Neoplasms\", \"ncit:C4890\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D002277\", \"Carcinoma\", \"ncit:C2916\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D046152\", \"Gastrointestinal Stromal Tumors\", \"ncit:C3868\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D004806\", \"Ependymoma\", \"ncit:C3017\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002289\", \"Carcinoma, Non-Small-Cell Lung\", \"ncit:C2926\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002583\", \"Uterine Cervical Neoplasms\", \"ncit:C9311\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008479\", \"Mediastinal Neoplasms\", \"ncit:C3549\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D006103\", \"Granuloma, Lethal Midline\", \"mondo:0006828\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D008288\", \"Malaria\", \"ncit:C34797\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D000306\", \"Adrenal Cortex Neoplasms\", \"ncit:C9325\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D018240\", \"Endodermal Sinus Tumor\", \"ncit:C3011\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D004938\", \"Esophageal Neoplasms\", \"ncit:C7478\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D012468\", \"Salivary Gland Neoplasms\", \"ncit:C3811\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"EFO:0003868\", \"mouth neoplasm\", \"ncit:C7606\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002822\", \"Choriocarcinoma\", \"ncit:C2948\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D018281\", \"Cholangiocarcinoma\", \"ncit:C4436\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D016483\", \"Lymphoma, AIDS-Related\", \"ncit:C3471\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D008545\", \"Melanoma\", \"ncit:C3224\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]"
+    ],
+    "label": "cisplatin",
+    "trade_names": [
+      "Platinol",
+      "Cisplatin",
+      "Platinol-aq",
+      "PLATINOL-AQ",
+      "PLATINOL"
+    ],
+    "xrefs": [
+      "ncit:C376",
+      "hemonc:105",
+      "drugbank:DB00515",
+      "drugbank:DB12117",
+      "drugsatfda.anda:074656",
+      "drugsatfda.anda:074735",
+      "drugsatfda.anda:075036",
+      "drugsatfda.anda:206774",
+      "drugsatfda.anda:207323",
+      "drugsatfda.nda:018057",
+      "iuphar.ligand:5343",
+      "chembl:CHEMBL11359",
+      "chemidplus:15663-27-1",
+      "wikidata:Q412415"
+    ]
+  },
+  "spiramycin": {
+    "label_and_type": "rxcui:9991##merger",
+    "concept_id": "rxcui:9991",
+    "xrefs": [
+      "ncit:C839",
+      "drugbank:DB06145",
+      "chemidplus:8025-81-8",
+      "wikidata:Q422265"
+    ],
+    "label": "spiramycin",
+    "aliases": [
+      "RP 5337",
+      "SPIRAMYCIN",
+      "Foromacidine A",
+      "Spiramycine",
+      "Provamycin",
+      "Foromacidin A",
+      "Antibiotic 799",
+      "spiramycin I",
+      "Rovamycin",
+      "Spiramycin A",
+      "Spiramycin 1",
+      "(4R,5S,6R,7R,9R,10R,11E,13E,16R)-10-{[(2R,5S,6R)-5-(dimethylamino)-6-methyltetrahydro-2H-pyran-2-yl]oxy}-9,16-dimethyl-5-methoxy-2-oxo-7-(2-oxoethyl)oxacyclohexadeca-11,13-dien-6-yl 3,6-dideoxy-4-O-(2,6-dideoxy-3-C-methyl-alpha-L-ribo-hexopyranosyl)-3-(dimethylamino)-alpha-D-glucopyranoside",
+      "Spiramycin I",
+      "Rovamycine",
+      "Demycarosylturimycin H"
+    ],
+    "associated_with": [
+      "pubchem.compound:5356392",
+      "umls:C0037962",
+      "unii:71ODY0V87H",
+      "inchikey:ACTOXUHEUCPTEW-KWBWCIJSSA-N",
+      "mesh:C017186",
+      "atc:J01FA02",
+      "mesh:D015572",
+      "unii:033ECH6IFG"
+    ]
+  }
+}
diff --git a/tests/unit/data/test_query_data.json b/tests/unit/data/test_query_data.json
new file mode 100644
index 00000000..0d941e77
--- /dev/null
+++ b/tests/unit/data/test_query_data.json
@@ -0,0 +1,1976 @@
+{
+  "cisplatin": {
+    "id": "normalize.therapy:rxcui%3A2555",
+    "type": "TherapyDescriptor",
+    "label": "cisplatin",
+    "description": null,
+    "xrefs": [
+      "ncit:C376",
+      "hemonc:105",
+      "drugbank:DB00515",
+      "drugbank:DB12117",
+      "drugsatfda.anda:074656",
+      "drugsatfda.anda:074735",
+      "drugsatfda.anda:075036",
+      "drugsatfda.anda:206774",
+      "drugsatfda.anda:207323",
+      "drugsatfda.nda:018057",
+      "iuphar.ligand:5343",
+      "chembl:CHEMBL11359",
+      "chemidplus:15663-27-1",
+      "wikidata:Q412415"
+    ],
+    "alternate_labels": [
+      "cis-Diamminedichloroplatinum",
+      "Diamminodichloride, Platinum",
+      "INT230-6 COMPONENT CISPLATIN",
+      "cisplatinum",
+      "Platinol",
+      "cis-Diaminedichloroplatinum",
+      "cis-platinum",
+      "CISplatin",
+      "Cis-platinum ii",
+      "Liplacis",
+      "cis Diamminedichloroplatinum",
+      "NSC-119875",
+      "DACP",
+      "1,2-Diaminocyclohexaneplatinum II citrate",
+      "CIS-DDP",
+      "cis-Dichlorodiammineplatinum(II)",
+      "INT-230-6 COMPONENT CISPLATIN",
+      "Platinol-AQ",
+      "Cis-DDP",
+      "NSC 119875",
+      "APRD00359",
+      "CDDP",
+      "DDP",
+      "Dichlorodiammineplatinum",
+      "cis-Platinum",
+      "cis-diamminedichloroplatinum III",
+      "cisplatino",
+      "cis-diamminedichloroplatinum(II)",
+      "cis Platinum",
+      "Platinum Diamminodichloride",
+      "Cisplatinum",
+      "cis-Diamminedichloroplatinum(II)"
+    ],
+    "extensions": [
+      {
+        "type": "Extension",
+        "name": "regulatory_approval",
+        "value": {
+          "approval_ratings": [
+            "gtopdb_approved",
+            "rxnorm_prescribable",
+            "hemonc_approved",
+            "fda_prescription",
+            "chembl_phase_4"
+          ],
+          "approval_year": ["1978"],
+          "has_indication": [
+            {
+              "id": "hemonc:671",
+              "type": "DiseaseDescriptor",
+              "label": "Testicular cancer",
+              "disease_id": "ncit:C7251",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "regulatory_body",
+                  "value": "FDA"
+                }
+              ]
+            },
+            {
+              "id": "hemonc:569",
+              "type": "DiseaseDescriptor",
+              "label": "Bladder cancer",
+              "disease_id": "ncit:C9334",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "regulatory_body",
+                  "value": "FDA"
+                }
+              ]
+            },
+            {
+              "id": "hemonc:645",
+              "type": "DiseaseDescriptor",
+              "label": "Ovarian cancer",
+              "disease_id": "ncit:C7431",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "regulatory_body",
+                  "value": "FDA"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D016545",
+              "type": "DiseaseDescriptor",
+              "label": "Choroid Plexus Neoplasms",
+              "disease_id": "ncit:C4533",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D005910",
+              "type": "DiseaseDescriptor",
+              "label": "Glioma",
+              "disease_id": "ncit:C3059",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D005185",
+              "type": "DiseaseDescriptor",
+              "label": "Fallopian Tube Neoplasms",
+              "disease_id": "ncit:C3867",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D009101",
+              "type": "DiseaseDescriptor",
+              "label": "Multiple Myeloma",
+              "disease_id": "ncit:C3242",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D010190",
+              "type": "DiseaseDescriptor",
+              "label": "Pancreatic Neoplasms",
+              "disease_id": "ncit:C3305",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D009190",
+              "type": "DiseaseDescriptor",
+              "label": "Myelodysplastic Syndromes",
+              "disease_id": "ncit:C3247",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D064129",
+              "type": "DiseaseDescriptor",
+              "label": "Prostatic Neoplasms, Castration-Resistant",
+              "disease_id": "DOID:0080909",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D018285",
+              "type": "DiseaseDescriptor",
+              "label": "Klatskin Tumor",
+              "disease_id": "ncit:C36077",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_1"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D012175",
+              "type": "DiseaseDescriptor",
+              "label": "Retinoblastoma",
+              "disease_id": "ncit:C7541",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D009303",
+              "type": "DiseaseDescriptor",
+              "label": "Nasopharyngeal Neoplasms",
+              "disease_id": "ncit:C3257",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D055752",
+              "type": "DiseaseDescriptor",
+              "label": "Small Cell Lung Carcinoma",
+              "disease_id": "ncit:C4917",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D009369",
+              "type": "DiseaseDescriptor",
+              "label": "Neoplasms",
+              "disease_id": "ncit:C3262",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_4"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D001005",
+              "type": "DiseaseDescriptor",
+              "label": "Anus Neoplasms",
+              "disease_id": "ncit:C2877",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D031901",
+              "type": "DiseaseDescriptor",
+              "label": "Gestational Trophoblastic Disease",
+              "disease_id": "ncit:C4699",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D006689",
+              "type": "DiseaseDescriptor",
+              "label": "Hodgkin Disease",
+              "disease_id": "ncit:C9357",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D015266",
+              "type": "DiseaseDescriptor",
+              "label": "Carcinoma, Merkel Cell",
+              "disease_id": "ncit:C9231",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_1"
+                }
+              ]
+            },
+            {
+              "id": "EFO:1000043",
+              "type": "DiseaseDescriptor",
+              "label": "ovarian serous cystadenocarcinoma",
+              "disease_id": "ncit:C7978",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_1"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D010610",
+              "type": "DiseaseDescriptor",
+              "label": "Pharyngeal Neoplasms",
+              "disease_id": "ncit:C7545",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D014594",
+              "type": "DiseaseDescriptor",
+              "label": "Uterine Neoplasms",
+              "disease_id": "ncit:C3552",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D018273",
+              "type": "DiseaseDescriptor",
+              "label": "Carcinoma, Islet Cell",
+              "disease_id": "ncit:C3770",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D018278",
+              "type": "DiseaseDescriptor",
+              "label": "Carcinoma, Neuroendocrine",
+              "disease_id": "ncit:C3773",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D052016",
+              "type": "DiseaseDescriptor",
+              "label": "Mucositis",
+              "disease_id": "ncit:C3853",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D002280",
+              "type": "DiseaseDescriptor",
+              "label": "Carcinoma, Basal Cell",
+              "disease_id": "ncit:C156767",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_1"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D005706",
+              "type": "DiseaseDescriptor",
+              "label": "Gallbladder Neoplasms",
+              "disease_id": "ncit:C7481",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D002276",
+              "type": "DiseaseDescriptor",
+              "label": "Carcinoid Tumor",
+              "disease_id": "ncit:C2915",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D013964",
+              "type": "DiseaseDescriptor",
+              "label": "Thyroid Neoplasms",
+              "disease_id": "ncit:C7510",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_1"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D002292",
+              "type": "DiseaseDescriptor",
+              "label": "Carcinoma, Renal Cell",
+              "disease_id": "mondo:0005086",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D020250",
+              "type": "DiseaseDescriptor",
+              "label": "Postoperative Nausea and Vomiting",
+              "disease_id": null,
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D009447",
+              "type": "DiseaseDescriptor",
+              "label": "Neuroblastoma",
+              "disease_id": "ncit:C3270",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D001749",
+              "type": "DiseaseDescriptor",
+              "label": "Urinary Bladder Neoplasms",
+              "disease_id": "ncit:C9334",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "EFO:0009708",
+              "type": "DiseaseDescriptor",
+              "label": "metastasis",
+              "disease_id": "ncit:C3261",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D018269",
+              "type": "DiseaseDescriptor",
+              "label": "Carcinoma, Endometrioid",
+              "disease_id": "ncit:C7558",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_1"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D007822",
+              "type": "DiseaseDescriptor",
+              "label": "Laryngeal Neoplasms",
+              "disease_id": "ncit:C3156",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D006258",
+              "type": "DiseaseDescriptor",
+              "label": "Head and Neck Neoplasms",
+              "disease_id": "ncit:C4013",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D018239",
+              "type": "DiseaseDescriptor",
+              "label": "Seminoma",
+              "disease_id": "ncit:C9309",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D000230",
+              "type": "DiseaseDescriptor",
+              "label": "Adenocarcinoma",
+              "disease_id": "ncit:C2852",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D014987",
+              "type": "DiseaseDescriptor",
+              "label": "Xerostomia",
+              "disease_id": null,
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_1"
+                }
+              ]
+            },
+            {
+              "id": "EFO:0005570",
+              "type": "DiseaseDescriptor",
+              "label": "oral cavity cancer",
+              "disease_id": "ncit:C9314",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D001932",
+              "type": "DiseaseDescriptor",
+              "label": "Brain Neoplasms",
+              "disease_id": "ncit:C3568",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D058922",
+              "type": "DiseaseDescriptor",
+              "label": "Inflammatory Breast Neoplasms",
+              "disease_id": "ncit:C4001",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D016543",
+              "type": "DiseaseDescriptor",
+              "label": "Central Nervous System Neoplasms",
+              "disease_id": "ncit:C4627",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D007012",
+              "type": "DiseaseDescriptor",
+              "label": "Hypopharyngeal Neoplasms",
+              "disease_id": "ncit:C7190",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D008223",
+              "type": "DiseaseDescriptor",
+              "label": "Lymphoma",
+              "disease_id": "ncit:C3208",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D000077192",
+              "type": "DiseaseDescriptor",
+              "label": "Adenocarcinoma of Lung",
+              "disease_id": "ncit:C3512",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D008527",
+              "type": "DiseaseDescriptor",
+              "label": "Medulloblastoma",
+              "disease_id": "ncit:C3222",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D018312",
+              "type": "DiseaseDescriptor",
+              "label": "Sex Cord-Gonadal Stromal Tumors",
+              "disease_id": "ncit:C3794",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D013280",
+              "type": "DiseaseDescriptor",
+              "label": "Stomatitis",
+              "disease_id": "ncit:C26887",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D064726",
+              "type": "DiseaseDescriptor",
+              "label": "Triple Negative Breast Neoplasms",
+              "disease_id": "ncit:C71732",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D009373",
+              "type": "DiseaseDescriptor",
+              "label": "Neoplasms, Germ Cell and Embryonal",
+              "disease_id": "ncit:C3708",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D021441",
+              "type": "DiseaseDescriptor",
+              "label": "Carcinoma, Pancreatic Ductal",
+              "disease_id": "ncit:C9120",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D018305",
+              "type": "DiseaseDescriptor",
+              "label": "Ganglioneuroblastoma",
+              "disease_id": "ncit:C3790",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D010534",
+              "type": "DiseaseDescriptor",
+              "label": "Peritoneal Neoplasms",
+              "disease_id": "ncit:C3322",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D007674",
+              "type": "DiseaseDescriptor",
+              "label": "Kidney Diseases",
+              "disease_id": "ncit:C3149",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_1"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D010412",
+              "type": "DiseaseDescriptor",
+              "label": "Penile Neoplasms",
+              "disease_id": "ncit:C3317",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D010255",
+              "type": "DiseaseDescriptor",
+              "label": "Paranasal Sinus Neoplasms",
+              "disease_id": "ncit:C6014",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D010996",
+              "type": "DiseaseDescriptor",
+              "label": "Pleural Effusion",
+              "disease_id": null,
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D001661",
+              "type": "DiseaseDescriptor",
+              "label": "Biliary Tract Neoplasms",
+              "disease_id": "mondo:0003060",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D012509",
+              "type": "DiseaseDescriptor",
+              "label": "Sarcoma",
+              "disease_id": "ncit:C9118",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D009325",
+              "type": "DiseaseDescriptor",
+              "label": "Nausea",
+              "disease_id": null,
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D018197",
+              "type": "DiseaseDescriptor",
+              "label": "Hepatoblastoma",
+              "disease_id": "ncit:C3728",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D012208",
+              "type": "DiseaseDescriptor",
+              "label": "Rhabdomyosarcoma",
+              "disease_id": "ncit:C3359",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_0"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D013274",
+              "type": "DiseaseDescriptor",
+              "label": "Stomach Neoplasms",
+              "disease_id": "ncit:C3387",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D014846",
+              "type": "DiseaseDescriptor",
+              "label": "Vulvar Neoplasms",
+              "disease_id": "ncit:C7502",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D013953",
+              "type": "DiseaseDescriptor",
+              "label": "Thymus Neoplasms",
+              "disease_id": "ncit:C4962",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D020522",
+              "type": "DiseaseDescriptor",
+              "label": "Lymphoma, Mantle-Cell",
+              "disease_id": "ncit:C4337",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D007938",
+              "type": "DiseaseDescriptor",
+              "label": "Leukemia",
+              "disease_id": "ncit:C3161",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D016411",
+              "type": "DiseaseDescriptor",
+              "label": "Lymphoma, T-Cell, Peripheral",
+              "disease_id": "ncit:C3468",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D015179",
+              "type": "DiseaseDescriptor",
+              "label": "Colorectal Neoplasms",
+              "disease_id": "ncit:C2956",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D013945",
+              "type": "DiseaseDescriptor",
+              "label": "Thymoma",
+              "disease_id": "ncit:C3411",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D018242",
+              "type": "DiseaseDescriptor",
+              "label": "Neuroectodermal Tumors, Primitive",
+              "disease_id": "ncit:C3222",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D004066",
+              "type": "DiseaseDescriptor",
+              "label": "Digestive System Diseases",
+              "disease_id": "ncit:C3959",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D008654",
+              "type": "DiseaseDescriptor",
+              "label": "Mesothelioma",
+              "disease_id": "ncit:C3234",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D013724",
+              "type": "DiseaseDescriptor",
+              "label": "Teratoma",
+              "disease_id": "ncit:C3403",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D016889",
+              "type": "DiseaseDescriptor",
+              "label": "Endometrial Neoplasms",
+              "disease_id": "ncit:C3012",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D008107",
+              "type": "DiseaseDescriptor",
+              "label": "Liver Diseases",
+              "disease_id": "ncit:C3196",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_1"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D015459",
+              "type": "DiseaseDescriptor",
+              "label": "Leukemia-Lymphoma, Adult T-Cell",
+              "disease_id": "ncit:C3184",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D016403",
+              "type": "DiseaseDescriptor",
+              "label": "Lymphoma, Large B-Cell, Diffuse",
+              "disease_id": "ncit:C8851",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D009959",
+              "type": "DiseaseDescriptor",
+              "label": "Oropharyngeal Neoplasms",
+              "disease_id": "ncit:C7398",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D014523",
+              "type": "DiseaseDescriptor",
+              "label": "Urethral Neoplasms",
+              "disease_id": "ncit:C3619",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D012516",
+              "type": "DiseaseDescriptor",
+              "label": "Osteosarcoma",
+              "disease_id": "ncit:C53707",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D014062",
+              "type": "DiseaseDescriptor",
+              "label": "Tongue Neoplasms",
+              "disease_id": "ncit:C9345",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D014565",
+              "type": "DiseaseDescriptor",
+              "label": "Urogenital Neoplasms",
+              "disease_id": "mondo:0025370",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D008113",
+              "type": "DiseaseDescriptor",
+              "label": "Liver Neoplasms",
+              "disease_id": "ncit:C34803",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D000077195",
+              "type": "DiseaseDescriptor",
+              "label": "Squamous Cell Carcinoma of Head and Neck",
+              "disease_id": "ncit:C4044",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D007119",
+              "type": "DiseaseDescriptor",
+              "label": "Immunoblastic Lymphadenopathy",
+              "disease_id": "ncit:C7528",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D013736",
+              "type": "DiseaseDescriptor",
+              "label": "Testicular Neoplasms",
+              "disease_id": "ncit:C7251",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D006528",
+              "type": "DiseaseDescriptor",
+              "label": "Carcinoma, Hepatocellular",
+              "disease_id": "ncit:C3099",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D018236",
+              "type": "DiseaseDescriptor",
+              "label": "Carcinoma, Embryonal",
+              "disease_id": "ncit:C3752",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D001943",
+              "type": "DiseaseDescriptor",
+              "label": "Breast Neoplasms",
+              "disease_id": "ncit:C2910",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D002294",
+              "type": "DiseaseDescriptor",
+              "label": "Carcinoma, Squamous Cell",
+              "disease_id": "ncit:C2929",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D000740",
+              "type": "DiseaseDescriptor",
+              "label": "Anemia",
+              "disease_id": "ncit:C2869",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D008175",
+              "type": "DiseaseDescriptor",
+              "label": "Lung Neoplasms",
+              "disease_id": "ncit:C3200",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D008228",
+              "type": "DiseaseDescriptor",
+              "label": "Lymphoma, Non-Hodgkin",
+              "disease_id": "ncit:C3211",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D017728",
+              "type": "DiseaseDescriptor",
+              "label": "Lymphoma, Large-Cell, Anaplastic",
+              "disease_id": "ncit:C3720",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D010051",
+              "type": "DiseaseDescriptor",
+              "label": "Ovarian Neoplasms",
+              "disease_id": "ncit:C7431",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D008224",
+              "type": "DiseaseDescriptor",
+              "label": "Lymphoma, Follicular",
+              "disease_id": "ncit:C3209",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D007680",
+              "type": "DiseaseDescriptor",
+              "label": "Kidney Neoplasms",
+              "disease_id": "ncit:C7548",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D004067",
+              "type": "DiseaseDescriptor",
+              "label": "Digestive System Neoplasms",
+              "disease_id": "ncit:C4890",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_1"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D002277",
+              "type": "DiseaseDescriptor",
+              "label": "Carcinoma",
+              "disease_id": "ncit:C2916",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D046152",
+              "type": "DiseaseDescriptor",
+              "label": "Gastrointestinal Stromal Tumors",
+              "disease_id": "ncit:C3868",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D004806",
+              "type": "DiseaseDescriptor",
+              "label": "Ependymoma",
+              "disease_id": "ncit:C3017",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D002289",
+              "type": "DiseaseDescriptor",
+              "label": "Carcinoma, Non-Small-Cell Lung",
+              "disease_id": "ncit:C2926",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D002583",
+              "type": "DiseaseDescriptor",
+              "label": "Uterine Cervical Neoplasms",
+              "disease_id": "ncit:C9311",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D008479",
+              "type": "DiseaseDescriptor",
+              "label": "Mediastinal Neoplasms",
+              "disease_id": "ncit:C3549",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D006103",
+              "type": "DiseaseDescriptor",
+              "label": "Granuloma, Lethal Midline",
+              "disease_id": "mondo:0006828",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D008288",
+              "type": "DiseaseDescriptor",
+              "label": "Malaria",
+              "disease_id": "ncit:C34797",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D000306",
+              "type": "DiseaseDescriptor",
+              "label": "Adrenal Cortex Neoplasms",
+              "disease_id": "ncit:C9325",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D018240",
+              "type": "DiseaseDescriptor",
+              "label": "Endodermal Sinus Tumor",
+              "disease_id": "ncit:C3011",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D004938",
+              "type": "DiseaseDescriptor",
+              "label": "Esophageal Neoplasms",
+              "disease_id": "ncit:C7478",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D012468",
+              "type": "DiseaseDescriptor",
+              "label": "Salivary Gland Neoplasms",
+              "disease_id": "ncit:C3811",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "EFO:0003868",
+              "type": "DiseaseDescriptor",
+              "label": "mouth neoplasm",
+              "disease_id": "ncit:C7606",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D002822",
+              "type": "DiseaseDescriptor",
+              "label": "Choriocarcinoma",
+              "disease_id": "ncit:C2948",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D018281",
+              "type": "DiseaseDescriptor",
+              "label": "Cholangiocarcinoma",
+              "disease_id": "ncit:C4436",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D016483",
+              "type": "DiseaseDescriptor",
+              "label": "Lymphoma, AIDS-Related",
+              "disease_id": "ncit:C3471",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_2"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D008545",
+              "type": "DiseaseDescriptor",
+              "label": "Melanoma",
+              "disease_id": "ncit:C3224",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            }
+          ]
+        }
+      },
+      {
+        "type": "Extension",
+        "name": "trade_names",
+        "value": [
+          "Platinol",
+          "Cisplatin",
+          "Platinol-aq",
+          "PLATINOL-AQ",
+          "PLATINOL"
+        ]
+      },
+      {
+        "type": "Extension",
+        "name": "associated_with",
+        "value": [
+          "ndc:0703-5748",
+          "ndc:63323-103",
+          "ndc:70860-206",
+          "ndc:44567-509",
+          "spl:5a24d5bd-c44a-43f7-a04c-76caf3475012",
+          "usp:m17910",
+          "ndc:44567-530",
+          "pubchem.substance:178102005",
+          "spl:9b008181-ab66-db2f-e053-2995a90aad57",
+          "ndc:16729-288",
+          "spl:a66eda32-1164-439a-ac8e-73138365ec06",
+          "spl:dd45d777-d4c1-40ee-b4f0-c9e001a15a8c",
+          "CHEBI:27899",
+          "ndc:44567-511",
+          "ndc:0703-5747",
+          "ndc:68083-162",
+          "atc:L01XA01",
+          "mesh:D002945",
+          "ndc:44567-510",
+          "mmsl:31747",
+          "spl:2c569ef0-588f-4828-8b2d-03a2120c9b4c",
+          "vandf:4018139",
+          "inchikey:LXZZYRPGZAFOLE-UHFFFAOYSA-L",
+          "ndc:68083-163",
+          "inchikey:MOTIYCLHZZLHHQ-UHFFFAOYSA-N",
+          "spl:54b3415c-c095-4c82-b216-e0e6e6bb8d03",
+          "mmsl:d00195",
+          "spl:01c7a680-ee0d-42da-85e8-8d56c6fe7006",
+          "spl:c43de769-d6d8-3bb9-e053-2995a90a5aa2",
+          "unii:H8MTN7XVC2",
+          "ndc:68001-283",
+          "unii:Q20Q21Q62J",
+          "pubchem.compound:5702198",
+          "pubchem.compound:441203",
+          "ndc:0143-9505",
+          "spl:c3ddc4a5-9f1b-a8ee-e053-2a95a90a2265",
+          "mmsl:4456",
+          "umls:C0008838",
+          "ndc:0143-9504"
+        ]
+      }
+    ],
+    "therapy_id": "rxcui:2555"
+  },
+  "phenobarbital": {
+    "id": "normalize.therapy:Phenobarbital",
+    "type": "TherapyDescriptor",
+    "label": "phenobarbital",
+    "description": null,
+    "xrefs": [
+      "ncit:C739",
+      "drugbank:DB01174",
+      "iuphar.ligand:2804",
+      "chembl:CHEMBL40",
+      "chemidplus:50-06-6",
+      "wikidata:Q407241"
+    ],
+    "alternate_labels": [
+      "fenobarbital",
+      "APRD00184",
+      "5-ethyl-5-phenyl-1,3-diazinane-2,4,6-trione",
+      "phenobarbitone",
+      "phenobarbital",
+      "PHENobarbital",
+      "PHENYLETHYLMALONYLUREA",
+      "5-Ethyl-5-phenyl-2,4,6(1H,3H,5H)-pyrimidinetrione",
+      "NSC-128143",
+      "Phenemal",
+      "Phenobarbital civ",
+      "5-Ethyl-5-phenyl-pyrimidine-2,4,6-trione",
+      "Fenobarbital",
+      "5-Phenyl-5-ethylbarbituric acid",
+      "phenobarbital sodium",
+      "Luminal®",
+      "Phenobarbital",
+      "Phenylbarbital",
+      "5-ethyl-5-phenyl-2,4,6(1H,3H,5H)-pyrimidinetrione",
+      "PHENO",
+      "Phenylethylbarbitursäure",
+      "phenylethylbarbiturate",
+      "PHENOBARBITAL",
+      "Phenylethylbarbiturate",
+      "NSC-128143-",
+      "Phenylaethylbarbitursaeure",
+      "Phenyläthylbarbitursäure",
+      "Phenobarbitone",
+      "Phenobarbitol",
+      "Phenylethylbarbituric Acid",
+      "Phenylethylbarbitursaeure",
+      "5-ethyl-5-phenylpyrimidine-2,4,6(1H,3H,5H)-trione",
+      "Luminal",
+      "5-Ethyl-5-phenylbarbituric acid",
+      "Acid, Phenylethylbarbituric",
+      "phenobarb",
+      "Phenylethylmalonylurea",
+      "NSC-9848",
+      "Phenobarbituric Acid"
+    ],
+    "extensions": [
+      {
+        "type": "Extension",
+        "name": "regulatory_approval",
+        "value": {
+          "approval_ratings": [
+            "chembl_phase_4",
+            "rxnorm_prescribable",
+            "gtopdb_approved"
+          ],
+          "has_indication": [
+            {
+              "id": "mesh:D009357",
+              "type": "DiseaseDescriptor",
+              "label": "Neonatal Abstinence Syndrome",
+              "disease_id": "ncit:C87101",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D012559",
+              "type": "DiseaseDescriptor",
+              "label": "Schizophrenia",
+              "disease_id": "mondo:0005090",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D001007",
+              "type": "DiseaseDescriptor",
+              "label": "Anxiety",
+              "disease_id": "mondo:0011918",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D012640",
+              "type": "DiseaseDescriptor",
+              "label": "Seizures",
+              "disease_id": "ncit:C3980",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D009503",
+              "type": "DiseaseDescriptor",
+              "label": "Neutropenia",
+              "disease_id": "mondo:0001475",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_1"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D008223",
+              "type": "DiseaseDescriptor",
+              "label": "Lymphoma",
+              "disease_id": "ncit:C3208",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_1"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D013226",
+              "type": "DiseaseDescriptor",
+              "label": "Status Epilepticus",
+              "disease_id": "ncit:C85079",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D003704",
+              "type": "DiseaseDescriptor",
+              "label": "Dementia",
+              "disease_id": "mondo:0001627",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D004827",
+              "type": "DiseaseDescriptor",
+              "label": "Epilepsy",
+              "disease_id": "ncit:C3020",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_4"
+                }
+              ]
+            },
+            {
+              "id": "mesh:D003866",
+              "type": "DiseaseDescriptor",
+              "label": "Depressive Disorder",
+              "disease_id": "mondo:0002050",
+              "extensions": [
+                {
+                  "type": "Extension",
+                  "name": "chembl_max_phase_for_ind",
+                  "value": "chembl_phase_3"
+                }
+              ]
+            }
+          ]
+        }
+      },
+      {
+        "type": "Extension",
+        "name": "trade_names",
+        "value": [
+          "Phenobarbitone",
+          "Luminal",
+          "Solfoton",
+          "Eskabarb",
+          "Talpheno",
+          "Noptil"
+        ]
+      },
+      {
+        "type": "Extension",
+        "name": "associated_with",
+        "value": [
+          "mmsl:d00340",
+          "inchikey:DDBREPKUVSBGFI-UHFFFAOYSA-N",
+          "pubchem.compound:4763",
+          "unii:YQE403BP4D",
+          "usp:m63400",
+          "atc:N03AA02",
+          "CHEBI:8069",
+          "mesh:D010634",
+          "mmsl:2390",
+          "drugcentral:2134",
+          "mmsl:5272",
+          "vandf:4017422",
+          "pubchem.substance:135650817",
+          "umls:C0031412"
+        ]
+      }
+    ],
+    "therapy_id": "rxcui:8134"
+  },
+  "spiramycin": {
+    "id": "normalize.therapy:Spiramycin",
+    "type": "TherapyDescriptor",
+    "label": "spiramycin",
+    "description": null,
+    "xrefs": [
+      "ncit:C839",
+      "drugbank:DB06145",
+      "chemidplus:8025-81-8",
+      "wikidata:Q422265"
+    ],
+    "alternate_labels": [
+      "Provamycin",
+      "Spiramycin A",
+      "Rovamycine",
+      "Rovamycin",
+      "(4R,5S,6R,7R,9R,10R,11E,13E,16R)-10-{[(2R,5S,6R)-5-(dimethylamino)-6-methyltetrahydro-2H-pyran-2-yl]oxy}-9,16-dimethyl-5-methoxy-2-oxo-7-(2-oxoethyl)oxacyclohexadeca-11,13-dien-6-yl 3,6-dideoxy-4-O-(2,6-dideoxy-3-C-methyl-alpha-L-ribo-hexopyranosyl)-3-(dimethylamino)-alpha-D-glucopyranoside",
+      "SPIRAMYCIN",
+      "Foromacidine A",
+      "RP 5337",
+      "spiramycin I",
+      "Spiramycin 1",
+      "Antibiotic 799",
+      "Spiramycine",
+      "Demycarosylturimycin H",
+      "Spiramycin I",
+      "Foromacidin A"
+    ],
+    "extensions": [
+      {
+        "type": "Extension",
+        "name": "associated_with",
+        "value": [
+          "pubchem.compound:5356392",
+          "mesh:D015572",
+          "mesh:C017186",
+          "inchikey:ACTOXUHEUCPTEW-CEUOBAOPSA-N",
+          "unii:71ODY0V87H",
+          "unii:033ECH6IFG",
+          "atc:J01FA02",
+          "umls:C0037962"
+        ]
+      }
+    ],
+    "therapy_id": "rxcui:9991"
+  },
+  "therapeutic_procedure": {
+    "id": "normalize.therapy:ncit%3AC49236",
+    "type": "TherapyDescriptor",
+    "label": "Therapeutic Procedure",
+    "description": null,
+    "xrefs": null,
+    "alternate_labels": [
+      "Therapeutic Interventions",
+      "any therapy",
+      "therapy",
+      "TX",
+      "TREAT",
+      "Therapeutic Method",
+      "Treatment",
+      "Therapeutic Technique",
+      "Therapy",
+      "treatment_or_therapy",
+      "treatment or therapy",
+      "any_therapy",
+      "treatment"
+    ],
+    "extensions": [
+      {
+        "type": "Extension",
+        "name": "associated_with",
+        "value": ["umls:C0087111"]
+      }
+    ],
+    "therapy_id": "ncit:C49236"
+  }
+}
diff --git a/tests/unit/data/therapies.json b/tests/unit/data/therapies.json
index a8c36e75..d9309029 100644
--- a/tests/unit/data/therapies.json
+++ b/tests/unit/data/therapies.json
@@ -1,25 +1,147 @@
 [
   {
     "label_and_type": "chembl:chembl11359##identity",
-    "src_name": "ChEMBL",
-    "item_type": "identity",
     "concept_id": "chembl:CHEMBL11359",
-    "label": "CISPLATIN",
     "aliases": [
-      "Cisplatin",
       "Cis-platinum ii",
-      "Cisplatinum",
+      "NSC-119875",
+      "Liplacis",
       "cis-diamminedichloroplatinum(II)",
-      "CIS-DDP",
-      "INT-230-6 COMPONENT CISPLATIN",
       "INT230-6 COMPONENT CISPLATIN",
-      "NSC-119875",
+      "Cisplatinum",
+      "CIS-DDP",
+      "INT-230-6 COMPONENT CISPLATIN"
+    ],
+    "approval_ratings": ["chembl_phase_4"],
+    "has_indication": [
+      "[\"mesh:D016545\", \"Choroid Plexus Neoplasms\", \"ncit:C4533\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D005910\", \"Glioma\", \"ncit:C3059\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D005185\", \"Fallopian Tube Neoplasms\", \"ncit:C3867\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009101\", \"Multiple Myeloma\", \"ncit:C3242\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D010190\", \"Pancreatic Neoplasms\", \"ncit:C3305\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009190\", \"Myelodysplastic Syndromes\", \"ncit:C3247\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D064129\", \"Prostatic Neoplasms, Castration-Resistant\", \"DOID:0080909\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D018285\", \"Klatskin Tumor\", \"ncit:C36077\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D012175\", \"Retinoblastoma\", \"ncit:C7541\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009303\", \"Nasopharyngeal Neoplasms\", \"ncit:C3257\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D055752\", \"Small Cell Lung Carcinoma\", \"ncit:C4917\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009369\", \"Neoplasms\", \"ncit:C3262\", {\"chembl_max_phase_for_ind\": \"chembl_phase_4\"}]",
+      "[\"mesh:D001005\", \"Anus Neoplasms\", \"ncit:C2877\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D031901\", \"Gestational Trophoblastic Disease\", \"ncit:C4699\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D006689\", \"Hodgkin Disease\", \"ncit:C9357\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D015266\", \"Carcinoma, Merkel Cell\", \"ncit:C9231\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"EFO:1000043\", \"ovarian serous cystadenocarcinoma\", \"ncit:C7978\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D010610\", \"Pharyngeal Neoplasms\", \"ncit:C7545\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D014594\", \"Uterine Neoplasms\", \"ncit:C3552\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D018273\", \"Carcinoma, Islet Cell\", \"ncit:C3770\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D018278\", \"Carcinoma, Neuroendocrine\", \"ncit:C3773\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D052016\", \"Mucositis\", \"ncit:C3853\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002280\", \"Carcinoma, Basal Cell\", \"ncit:C156767\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D005706\", \"Gallbladder Neoplasms\", \"ncit:C7481\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002276\", \"Carcinoid Tumor\", \"ncit:C2915\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D013964\", \"Thyroid Neoplasms\", \"ncit:C7510\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D002292\", \"Carcinoma, Renal Cell\", \"mondo:0005086\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D020250\", \"Postoperative Nausea and Vomiting\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009447\", \"Neuroblastoma\", \"ncit:C3270\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001749\", \"Urinary Bladder Neoplasms\", \"ncit:C9334\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"EFO:0009708\", \"metastasis\", \"ncit:C3261\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D018269\", \"Carcinoma, Endometrioid\", \"ncit:C7558\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D007822\", \"Laryngeal Neoplasms\", \"ncit:C3156\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D006258\", \"Head and Neck Neoplasms\", \"ncit:C4013\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D018239\", \"Seminoma\", \"ncit:C9309\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D000230\", \"Adenocarcinoma\", \"ncit:C2852\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D014987\", \"Xerostomia\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"EFO:0005570\", \"oral cavity cancer\", \"ncit:C9314\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001932\", \"Brain Neoplasms\", \"ncit:C3568\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D058922\", \"Inflammatory Breast Neoplasms\", \"ncit:C4001\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D016543\", \"Central Nervous System Neoplasms\", \"ncit:C4627\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D007012\", \"Hypopharyngeal Neoplasms\", \"ncit:C7190\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008223\", \"Lymphoma\", \"ncit:C3208\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D000077192\", \"Adenocarcinoma of Lung\", \"ncit:C3512\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008527\", \"Medulloblastoma\", \"ncit:C3222\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D018312\", \"Sex Cord-Gonadal Stromal Tumors\", \"ncit:C3794\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D013280\", \"Stomatitis\", \"ncit:C26887\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D064726\", \"Triple Negative Breast Neoplasms\", \"ncit:C71732\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D009373\", \"Neoplasms, Germ Cell and Embryonal\", \"ncit:C3708\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D021441\", \"Carcinoma, Pancreatic Ductal\", \"ncit:C9120\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D018305\", \"Ganglioneuroblastoma\", \"ncit:C3790\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D010534\", \"Peritoneal Neoplasms\", \"ncit:C3322\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D007674\", \"Kidney Diseases\", \"ncit:C3149\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D010412\", \"Penile Neoplasms\", \"ncit:C3317\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D010255\", \"Paranasal Sinus Neoplasms\", \"ncit:C6014\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D010996\", \"Pleural Effusion\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001661\", \"Biliary Tract Neoplasms\", \"mondo:0003060\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D012509\", \"Sarcoma\", \"ncit:C9118\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009325\", \"Nausea\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D018197\", \"Hepatoblastoma\", \"ncit:C3728\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D012208\", \"Rhabdomyosarcoma\", \"ncit:C3359\", {\"chembl_max_phase_for_ind\": \"chembl_phase_0\"}]",
+      "[\"mesh:D013274\", \"Stomach Neoplasms\", \"ncit:C3387\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D014846\", \"Vulvar Neoplasms\", \"ncit:C7502\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D013953\", \"Thymus Neoplasms\", \"ncit:C4962\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D020522\", \"Lymphoma, Mantle-Cell\", \"ncit:C4337\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D007938\", \"Leukemia\", \"ncit:C3161\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D016411\", \"Lymphoma, T-Cell, Peripheral\", \"ncit:C3468\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D015179\", \"Colorectal Neoplasms\", \"ncit:C2956\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D013945\", \"Thymoma\", \"ncit:C3411\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D018242\", \"Neuroectodermal Tumors, Primitive\", \"ncit:C3222\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D004066\", \"Digestive System Diseases\", \"ncit:C3959\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D008654\", \"Mesothelioma\", \"ncit:C3234\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D013724\", \"Teratoma\", \"ncit:C3403\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D016889\", \"Endometrial Neoplasms\", \"ncit:C3012\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008107\", \"Liver Diseases\", \"ncit:C3196\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D015459\", \"Leukemia-Lymphoma, Adult T-Cell\", \"ncit:C3184\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D016403\", \"Lymphoma, Large B-Cell, Diffuse\", \"ncit:C8851\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009959\", \"Oropharyngeal Neoplasms\", \"ncit:C7398\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D014523\", \"Urethral Neoplasms\", \"ncit:C3619\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D012516\", \"Osteosarcoma\", \"ncit:C53707\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D014062\", \"Tongue Neoplasms\", \"ncit:C9345\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D014565\", \"Urogenital Neoplasms\", \"mondo:0025370\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008113\", \"Liver Neoplasms\", \"ncit:C34803\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D000077195\", \"Squamous Cell Carcinoma of Head and Neck\", \"ncit:C4044\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D007119\", \"Immunoblastic Lymphadenopathy\", \"ncit:C7528\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D013736\", \"Testicular Neoplasms\", \"ncit:C7251\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D006528\", \"Carcinoma, Hepatocellular\", \"ncit:C3099\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D018236\", \"Carcinoma, Embryonal\", \"ncit:C3752\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001943\", \"Breast Neoplasms\", \"ncit:C2910\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002294\", \"Carcinoma, Squamous Cell\", \"ncit:C2929\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D000740\", \"Anemia\", \"ncit:C2869\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008175\", \"Lung Neoplasms\", \"ncit:C3200\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008228\", \"Lymphoma, Non-Hodgkin\", \"ncit:C3211\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D017728\", \"Lymphoma, Large-Cell, Anaplastic\", \"ncit:C3720\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D010051\", \"Ovarian Neoplasms\", \"ncit:C7431\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008224\", \"Lymphoma, Follicular\", \"ncit:C3209\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D007680\", \"Kidney Neoplasms\", \"ncit:C7548\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D004067\", \"Digestive System Neoplasms\", \"ncit:C4890\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D002277\", \"Carcinoma\", \"ncit:C2916\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D046152\", \"Gastrointestinal Stromal Tumors\", \"ncit:C3868\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D004806\", \"Ependymoma\", \"ncit:C3017\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002289\", \"Carcinoma, Non-Small-Cell Lung\", \"ncit:C2926\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002583\", \"Uterine Cervical Neoplasms\", \"ncit:C9311\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008479\", \"Mediastinal Neoplasms\", \"ncit:C3549\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D006103\", \"Granuloma, Lethal Midline\", \"mondo:0006828\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D008288\", \"Malaria\", \"ncit:C34797\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D000306\", \"Adrenal Cortex Neoplasms\", \"ncit:C9325\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D018240\", \"Endodermal Sinus Tumor\", \"ncit:C3011\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D004938\", \"Esophageal Neoplasms\", \"ncit:C7478\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D012468\", \"Salivary Gland Neoplasms\", \"ncit:C3811\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"EFO:0003868\", \"mouth neoplasm\", \"ncit:C7606\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002822\", \"Choriocarcinoma\", \"ncit:C2948\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D018281\", \"Cholangiocarcinoma\", \"ncit:C4436\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D016483\", \"Lymphoma, AIDS-Related\", \"ncit:C3471\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D008545\", \"Melanoma\", \"ncit:C3224\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]"
+    ],
+
+    "label": "CISPLATIN",
+    "merge_ref": "rxcui:2555",
+    "trade_names": [
+      "PLATINOL",
       "Platinol",
       "Platinol-aq",
-      "Liplacis"
+      "Cisplatin",
+      "PLATINOL-AQ"
     ],
-    "approval_rating": "chembl_phase_4",
-    "trade_names": ["PLATINOL", "PLATINOL-AQ"]
+    "item_type": "identity",
+    "src_name": "ChEMBL"
   },
   {
     "label_and_type": "cisplatin##label",
@@ -40,7 +162,7 @@
     "label_and_type": "chembl:chembl2068237##identity",
     "concept_id": "chembl:CHEMBL2068237",
     "label": "CISPLATIN",
-    "approval_rating": "chembl_phase_4",
+    "approval_ratings": ["chembl_phase_4"],
     "src_name": "ChEMBL"
   },
   {
@@ -52,7 +174,7 @@
     "label_and_type": "chembl:chembl1628046##identity",
     "concept_id": "chembl:CHEMBL1628046",
     "label": "CISPLATIN",
-    "approval_rating": "chembl_phase_4",
+    "approval_ratings": ["chembl_phase_4"],
     "src_name": "ChEMBL"
   },
   {
@@ -65,7 +187,7 @@
     "label": "L-745870",
     "concept_id": "chembl:CHEMBL267014",
     "src_name": "ChEMBL",
-    "approval_rating": "chembl_phase_0"
+    "approval_ratings": ["chembl_phase_0"]
   },
   {
     "label_and_type": "l-745870##label",
@@ -74,9 +196,156 @@
   },
   {
     "label_and_type": "chembl:chembl25##identity",
-    "label": "ASPIRIN",
     "concept_id": "chembl:CHEMBL25",
-    "approval_rating": "chembl_phase_4",
+    "aliases": [
+      "Acetylsalicylic Acid",
+      "NSC-406186",
+      "BAY1019036",
+      "NSC-27223",
+      "Acetylsalicylic acid",
+      "Aspirin"
+    ],
+    "approval_ratings": ["chembl_phase_4"],
+    "has_indication": [
+      "[\"mesh:D012214\", \"Rheumatic Heart Disease\", \"ncit:C34882\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D064129\", \"Prostatic Neoplasms, Castration-Resistant\", \"DOID:0080909\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D010051\", \"Ovarian Neoplasms\", \"ncit:C7431\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D010003\", \"Osteoarthritis\", \"ncit:C3293\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D010518\", \"Periodontitis\", \"ncit:C34918\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D002544\", \"Cerebral Infarction\", \"ncit:C50486\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D003930\", \"Diabetic Retinopathy\", \"ncit:C34538\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D010437\", \"Peptic Ulcer\", \"ncit:C3318\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D012559\", \"Schizophrenia\", \"mondo:0005090\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009101\", \"Multiple Myeloma\", \"ncit:C3242\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D014808\", \"Vitamin D Deficiency\", \"ncit:C114830\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D014652\", \"Vascular Diseases\", \"ncit:C35117\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009203\", \"Myocardial Infarction\", \"ncit:C27996\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D006261\", \"Headache\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D019851\", \"Thrombophilia\", \"ncit:C84479\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002386\", \"Cataract\", \"ncit:C26713\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001766\", \"Blindness\", \"ncit:C97109\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D017202\", \"Myocardial Ischemia\", \"ncit:C50625\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D011024\", \"Pneumonia, Viral\", \"mondo:0006012\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D012170\", \"Retinal Vein Occlusion\", \"ncit:C34981\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D007249\", \"Inflammation\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D006562\", \"Herpes Zoster\", \"ncit:C71079\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D011125\", \"Adenomatous Polyposis Coli\", \"ncit:C3339\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D014376\", \"Tuberculosis\", \"ncit:C3423\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D000083242\", \"Ischemic Stroke\", \"ncit:C95802\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D011471\", \"Prostatic Neoplasms\", \"ncit:C7378\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D000755\", \"Anemia, Sickle Cell\", \"ncit:C34383\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D017116\", \"Low Back Pain\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001471\", \"Barrett Esophagus\", \"ncit:C2891\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D006561\", \"Herpes Simplex\", \"mondo:0004609\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D011225\", \"Pre-Eclampsia\", \"ncit:C85021\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D004381\", \"Duodenal Ulcer\", \"ncit:C26755\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D058729\", \"Peripheral Arterial Disease\", \"ncit:C84496\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D006973\", \"Hypertension\", \"mondo:0005044\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D014456\", \"Ulcer\", \"mondo:0043839\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D005317\", \"Fetal Growth Retardation\", \"ncit:C114875\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002532\", \"Intracranial Aneurysm\", \"mondo:0005291\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D006937\", \"Hypercholesterolemia\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D001778\", \"Blood Coagulation Disorders\", \"ncit:C2902\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D014029\", \"Tobacco Use Disorder\", \"DOID:0050742\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D009303\", \"Nasopharyngeal Neoplasms\", \"ncit:C3257\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D007972\", \"Leukoplakia, Oral\", \"ncit:C3187\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D006976\", \"Hypertension, Pulmonary\", \"mondo:0005149\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D012128\", \"Respiratory Distress Syndrome\", \"mondo:0100130\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D010612\", \"Pharyngitis\", \"ncit:C26851\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002318\", \"Cardiovascular Diseases\", \"ncit:C2931\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D015228\", \"Hypertriglyceridemia\", \"mondo:0005347\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D016491\", \"Peripheral Vascular Diseases\", \"ncit:C35136\", {\"chembl_max_phase_for_ind\": \"chembl_phase_0\"}]",
+      "[\"mesh:D013927\", \"Thrombosis\", \"ncit:C26891\", {\"chembl_max_phase_for_ind\": \"chembl_phase_4\"}]",
+      "[\"mesh:D008268\", \"Macular Degeneration\", \"ncit:C123330\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D003139\", \"Common Cold\", \"ncit:C34500\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D000026\", \"Abortion, Habitual\", \"mondo:0006774\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D004211\", \"Disseminated Intravascular Coagulation\", \"ncit:C2992\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D010020\", \"Osteonecrosis\", \"ncit:C34880\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D003110\", \"Colonic Neoplasms\", \"ncit:C2953\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D054556\", \"Venous Thromboembolism\", \"ncit:C99537\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002537\", \"Intracranial Arteriosclerosis\", \"mondo:0001632\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D060050\", \"Angina, Stable\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D003920\", \"Diabetes Mellitus\", \"ncit:C2985\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D007319\", \"Sleep Initiation and Maintenance Disorders\", \"mondo:0013600\", {\"chembl_max_phase_for_ind\": \"chembl_phase_0\"}]",
+      "[\"mesh:D045169\", \"Severe Acute Respiratory Syndrome\", \"ncit:C85064\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D003327\", \"Coronary Disease\", \"ncit:C26732\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D003123\", \"Colorectal Neoplasms, Hereditary Nonpolyposis\", \"ncit:C8494\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D006333\", \"Heart Failure\", \"ncit:C50577\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D029424\", \"Pulmonary Disease, Chronic Obstructive\", \"ncit:C3199\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D014647\", \"Varicose Ulcer\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001714\", \"Bipolar Disorder\", \"mondo:0004985\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D018805\", \"Sepsis\", \"ncit:C3364\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D020246\", \"Venous Thrombosis\", \"mondo:0008559\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D012131\", \"Respiratory Insufficiency\", \"ncit:C26872\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D010146\", \"Pain\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_4\"}]",
+      "[\"mesh:D013274\", \"Stomach Neoplasms\", \"ncit:C3387\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D010927\", \"Placental Insufficiency\", \"mondo:0005919\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D008881\", \"Migraine Disorders\", \"ncit:C89715\", {\"chembl_max_phase_for_ind\": \"chembl_phase_4\"}]",
+      "[\"mesh:D006471\", \"Gastrointestinal Hemorrhage\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D013920\", \"Thrombocythemia, Essential\", \"ncit:C3407\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D054058\", \"Acute Coronary Syndrome\", \"ncit:C53652\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001249\", \"Asthma\", \"ncit:C28397\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D015179\", \"Colorectal Neoplasms\", \"ncit:C2956\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D005221\", \"Fatigue\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_0\"}]",
+      "[\"mesh:D005909\", \"Glioblastoma\", \"ncit:C3058\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D015658\", \"HIV Infections\", \"ncit:C3108\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D014947\", \"Wounds and Injuries\", \"mondo:0021178\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D020521\", \"Stroke\", \"ncit:C3390\", {\"chembl_max_phase_for_ind\": \"chembl_phase_4\"}]",
+      "[\"mesh:D004066\", \"Digestive System Diseases\", \"ncit:C3959\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D000077192\", \"Adenocarcinoma of Lung\", \"ncit:C3512\", {\"chembl_max_phase_for_ind\": \"chembl_phase_0\"}]",
+      "[\"mesh:D012004\", \"Rectal Neoplasms\", \"ncit:C3350\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D003093\", \"Colitis, Ulcerative\", \"ncit:C2952\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D011247\", \"Pregnancy\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D002583\", \"Uterine Cervical Neoplasms\", \"ncit:C9311\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D018781\", \"Tension-Type Headache\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D009369\", \"Neoplasms\", \"ncit:C3262\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D003924\", \"Diabetes Mellitus, Type 2\", \"ncit:C26747\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D006331\", \"Heart Diseases\", \"ncit:C3079\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D062788\", \"Adenomyosis\", \"ncit:C6996\", {\"chembl_max_phase_for_ind\": \"chembl_phase_0\"}]",
+      "[\"mesh:D006258\", \"Head and Neck Neoplasms\", \"ncit:C4013\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D011618\", \"Psychotic Disorders\", \"mondo:0001265\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D003865\", \"Depressive Disorder, Major\", \"mondo:0002009\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D001024\", \"Aortic Valve Stenosis\", \"mondo:0004978\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D056586\", \"Acute Chest Syndrome\", \"ncit:C138179\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009080\", \"Mucocutaneous Lymph Node Syndrome\", \"ncit:C34825\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D061218\", \"Depressive Disorder, Treatment-Resistant\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D051436\", \"Renal Insufficiency, Chronic\", \"ncit:C9438\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D050197\", \"Atherosclerosis\", \"ncit:C35768\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D020520\", \"Brain Infarction\", \"mondo:0005394\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D011087\", \"Polycythemia Vera\", \"ncit:C3336\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D055371\", \"Acute Lung Injury\", \"mondo:0015796\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D006528\", \"Carcinoma, Hepatocellular\", \"ncit:C3099\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D000072658\", \"Non-ST Elevated Myocardial Infarction\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002546\", \"Ischemic Attack, Transient\", \"ncit:C50781\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001943\", \"Breast Neoplasms\", \"ncit:C2910\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D016893\", \"Carotid Stenosis\", \"ncit:C95804\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D002312\", \"Cardiomyopathy, Hypertrophic\", \"ncit:C34449\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D006470\", \"Hemorrhage\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001281\", \"Atrial Fibrillation\", \"ncit:C50466\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002294\", \"Carcinoma, Squamous Cell\", \"ncit:C2929\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"EFO:0008585\", \"ST Elevation Myocardial Infarction\", \"mondo:0041656\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D007246\", \"Infertility\", \"mondo:0005047\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D015356\", \"Retinal Artery Occlusion\", \"ncit:C34978\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008545\", \"Melanoma\", \"ncit:C3224\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D007511\", \"Ischemia\", \"mondo:0005053\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"EFO:0000339\", \"chronic myelogenous leukemia\", \"ncit:C3174\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D011014\", \"Pneumonia\", \"ncit:C3333\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D008581\", \"Meningitis\", \"ncit:C79598\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D024821\", \"Metabolic Syndrome\", \"mondo:0011565\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D000236\", \"Adenoma\", \"ncit:C2855\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D005334\", \"Fever\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_4\"}]",
+      "[\"mesh:D002289\", \"Carcinoma, Non-Small-Cell Lung\", \"ncit:C2926\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002561\", \"Cerebrovascular Disorders\", \"ncit:C2938\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D013276\", \"Stomach Ulcer\", \"ncit:C3388\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008180\", \"Lupus Erythematosus, Systemic\", \"ncit:C3201\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D016889\", \"Endometrial Neoplasms\", \"ncit:C3012\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D050723\", \"Fractures, Bone\", \"mondo:0005315\", {\"chembl_max_phase_for_ind\": \"chembl_phase_0\"}]",
+      "[\"mesh:D004938\", \"Esophageal Neoplasms\", \"ncit:C7478\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"Orphanet:309005\", \"Disorder of lipid metabolism\", \"ncit:C97092\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]"
+    ],
+    "label": "ASPIRIN",
+    "merge_ref": "rxcui:1191",
+    "item_type": "identity",
     "src_name": "ChEMBL"
   },
   {
@@ -596,7 +865,7 @@
     "label_and_type": "rxcui:100213##identity",
     "concept_id": "rxcui:100213",
     "label": "Bifidobacterium Infantis",
-    "approval_rating": "rxnorm_prescribable",
+    "approval_ratings": ["rxnorm_prescribable"],
     "aliases": ["bifidobacterium infantis", "Bifidobacterium infantis"],
     "trade_names": ["Align", "Evivo"],
     "xrefs": ["drugbank:DB14222"],
@@ -633,7 +902,7 @@
     "label_and_type": "rxcui:2555##identity",
     "concept_id": "rxcui:2555",
     "label": "cisplatin",
-    "approval_rating": "rxnorm_prescribable",
+    "approval_ratings": ["rxnorm_prescribable"],
     "aliases": [
       "cis-Platinum",
       "CISplatin",
@@ -705,7 +974,7 @@
     "label_and_type": "rxcui:644##identity",
     "concept_id": "rxcui:644",
     "label": "amiloride",
-    "approval_rating": "rxnorm_prescribable",
+    "approval_ratings": ["rxnorm_prescribable"],
     "aliases": [
       "3,5-diamino-N-carbamimidoyl-6-chloropyrazine-2-carboxamide",
       "aMILoride",
@@ -762,7 +1031,7 @@
     "label_and_type": "rxcui:10600##identity",
     "concept_id": "rxcui:10600",
     "label": "timolol",
-    "approval_rating": "rxnorm_prescribable",
+    "approval_ratings": ["rxnorm_prescribable"],
     "aliases": [
       "(S)-1-((1,1-Dimethylethyl)amino)-3-((4-(4-morpholinyl)-1,2,5-thiadazol-3-yl)oxy)-2-propanol",
       "2-Propanol, 1-((1,1-dimethylethyl)amino)-3-((4-(4-morpholinyl)-1,2,5-thiadiazol-3-yl)oxy)-, (S)-",
@@ -812,7 +1081,7 @@
     "label_and_type": "rxcui:1011##identity",
     "concept_id": "rxcui:1011",
     "label": "lymphocyte immune globulin, anti-thymocyte globulin",
-    "approval_rating": "rxnorm_prescribable",
+    "approval_ratings": ["rxnorm_prescribable"],
     "aliases": [
       "Lymphocyte Immune Globulin, Anti-Thymocyte Globulin",
       "Anti-Thymocyte Globulin",
@@ -869,7 +1138,7 @@
       "mmsl:21336",
       "mmsl:d07642"
     ],
-    "approval_rating": "rxnorm_prescribable",
+    "approval_ratings": ["rxnorm_prescribable"],
     "trade_names": ["Thymoglobulin"]
   },
   {
@@ -906,7 +1175,7 @@
       "mmsl:d07641",
       "atc:L04AA03"
     ],
-    "approval_rating": "rxnorm_prescribable",
+    "approval_ratings": ["rxnorm_prescribable"],
     "trade_names": ["ATGAM"]
   },
   {
@@ -944,7 +1213,7 @@
     "label_and_type": "rxcui:1191##identity",
     "concept_id": "rxcui:1191",
     "label": "aspirin",
-    "approval_rating": "rxnorm_prescribable",
+    "approval_ratings": ["rxnorm_prescribable"],
     "aliases": [
       "Salicylic acid acetate",
       "Aspirin",
@@ -993,7 +1262,7 @@
     "label_and_type": "rxcui:44##identity",
     "concept_id": "rxcui:44",
     "label": "mesna",
-    "approval_rating": "rxnorm_prescribable",
+    "approval_ratings": ["rxnorm_prescribable"],
     "aliases": [
       "Mesnum",
       "Ethanesulfonic acid, 2-mercapto-, monosodium salt",
@@ -1039,7 +1308,7 @@
     "label_and_type": "rxcui:61##identity",
     "concept_id": "rxcui:61",
     "label": "beta-alanine",
-    "approval_rating": "rxnorm_prescribable",
+    "approval_ratings": ["rxnorm_prescribable"],
     "aliases": [
       "beta Alanine",
       "3 Aminopropionic Acid",
@@ -1086,7 +1355,7 @@
     "label_and_type": "rxcui:10582##identity",
     "concept_id": "rxcui:10582",
     "label": "levothyroxine",
-    "approval_rating": "rxnorm_prescribable",
+    "approval_ratings": ["rxnorm_prescribable"],
     "aliases": [
       "3,5,3',5'-Tetraiodo-L-thyronine",
       "Thyroxine",
@@ -1129,23 +1398,38 @@
     "label": "PHENOBARBITAL",
     "concept_id": "chembl:CHEMBL40",
     "aliases": [
-      "Luminal",
-      "Noptil",
-      "Phenobarbital civ",
-      "NSC-9848",
-      "Talpheno",
+      "NSC-128143",
+      "Phenobarbital",
+      "NSC-128143-",
       "Phenemal",
+      "NSC-9848",
       "Phenylethylmalonylurea",
-      "Solfoton",
-      "NSC-128143-",
-      "Phenobarbital",
-      "Phenobarbitone",
+      "Phenobarbital civ"
+    ],
+    "trade_names": [
+      "Talpheno",
+      "Luminal",
       "Eskabarb",
-      "NSC-128143"
+      "Solfoton",
+      "Noptil",
+      "Phenobarbitone"
     ],
-    "approval_rating": "chembl_phase_4",
+    "approval_ratings": ["chembl_phase_4"],
     "src_name": "ChEMBL",
-    "merge_ref": "rxcui:8134"
+    "merge_ref": "rxcui:8134",
+    "has_indication": [
+      "[\"mesh:D008223\", \"Lymphoma\", \"ncit:C3208\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D012559\", \"Schizophrenia\", \"mondo:0005090\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009503\", \"Neutropenia\", \"mondo:0001475\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D003866\", \"Depressive Disorder\", \"mondo:0002050\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001007\", \"Anxiety\", \"mondo:0011918\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D004827\", \"Epilepsy\", \"ncit:C3020\", {\"chembl_max_phase_for_ind\": \"chembl_phase_4\"}]",
+      "[\"mesh:D003704\", \"Dementia\", \"mondo:0001627\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009357\", \"Neonatal Abstinence Syndrome\", \"ncit:C87101\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D012640\", \"Seizures\", \"ncit:C3980\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D013226\", \"Status Epilepticus\", \"ncit:C85079\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001007\", \"Anxiety\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]"
+    ]
   },
   {
     "label_and_type": "PHENOBARBITAL##label",
@@ -1189,7 +1473,7 @@
       "atc:N03AA02"
     ],
     "src_name": "RxNorm",
-    "approval_rating": "rxnorm_prescribable",
+    "approval_ratings": ["rxnorm_prescribable"],
     "merge_ref": "rxcui:8134"
   },
   {
@@ -1229,7 +1513,7 @@
   {
     "label_and_type": "chemidplus:8025-81-8##identity",
     "src_name": "ChemIDplus",
-    "merge_ref": "ncit:c839",
+    "merge_ref": "rxcui:9991",
     "item_type": "identity",
     "label": "Spiramycin",
     "concept_id": "chemidplus:8025-81-8",
@@ -1306,7 +1590,14 @@
     "xrefs": ["chemidplus:8025-81-8"],
     "associated_with": ["umls:C0037962", "unii:71ODY0V87H"],
     "src_name": "NCIt",
-    "merge_ref": "ncit:c839"
+    "merge_ref": "rxcui:9991",
+    "item_type": "identity"
+  },
+  {
+    "label_and_type": "chemidplus:8025-81-8##xref",
+    "concept_id": "ncit:c839",
+    "src_name": "NCIt",
+    "item_type": "xref"
   },
   {
     "label_and_type": "rp 5337##alias",
@@ -1332,48 +1623,52 @@
       "chembl:CHEMBL40"
     ],
     "aliases": [
-      "5-Ethyl-5-phenyl-2,4,6(1H,3H,5H)-pyrimidinetrione",
+      "Phenylbarbital",
+      "PHENobarbital",
+      "Phenobarbitone",
+      "NSC-128143",
       "5-Ethyl-5-phenyl-pyrimidine-2,4,6-trione",
-      "5-Ethyl-5-phenylbarbituric acid",
       "5-Phenyl-5-ethylbarbituric acid",
-      "5-ethyl-5-phenyl-2,4,6(1H,3H,5H)-pyrimidinetrione",
-      "5-ethyl-5-phenylpyrimidine-2,4,6(1H,3H,5H)-trione",
-      "APRD00184",
+      "5-ethyl-5-phenyl-1,3-diazinane-2,4,6-trione",
+      "Phenobarbituric Acid",
+      "Phenylethylbarbituric Acid",
       "Acid, Phenylethylbarbituric",
-      "Fenobarbital",
-      "Luminal®",
-      "PHENO",
       "PHENOBARBITAL",
+      "phenobarbitone",
+      "Phenylethylbarbiturs\u00e4ure",
+      "5-Ethyl-5-phenylbarbituric acid",
+      "NSC-128143-",
+      "phenobarb",
+      "Luminal",
+      "5-ethyl-5-phenyl-2,4,6(1H,3H,5H)-pyrimidinetrione",
       "PHENYLETHYLMALONYLUREA",
-      "PHENobarbital",
-      "Phenemal",
-      "Phenobarbital",
-      "Phenobarbitol",
-      "Phenobarbitone",
-      "Phenobarbituric Acid",
-      "Phenylaethylbarbitursaeure",
-      "Phenylbarbital",
       "Phenylethylbarbiturate",
-      "Phenylethylbarbituric Acid",
-      "Phenylethylbarbitursaeure",
-      "Phenylethylbarbitursäure",
-      "Phenylethylmalonylurea",
-      "Phenyläthylbarbitursäure",
+      "Luminal\u00ae",
+      "Phenemal",
       "fenobarbital",
-      "phenobarbital",
-      "phenobarbital sodium",
+      "Fenobarbital",
+      "Phenylethylbarbitursaeure",
+      "5-Ethyl-5-phenyl-2,4,6(1H,3H,5H)-pyrimidinetrione",
       "phenylethylbarbiturate",
-      "5-ethyl-5-phenyl-1,3-diazinane-2,4,6-trione",
-      "phenobarb",
-      "phenobarbitone",
-      "NSC-128143",
-      "NSC-128143-",
-      "NSC-9848",
       "Phenobarbital civ",
-      "Solfoton",
-      "Luminal",
+      "Phenylaethylbarbitursaeure",
+      "Phenobarbitol",
+      "NSC-9848",
+      "Phenyl\u00e4thylbarbiturs\u00e4ure",
+      "phenobarbital",
+      "5-ethyl-5-phenylpyrimidine-2,4,6(1H,3H,5H)-trione",
+      "APRD00184",
+      "Phenylethylmalonylurea",
+      "PHENO",
+      "phenobarbital sodium",
+      "Phenobarbital"
+    ],
+    "trade_names": [
       "Eskabarb",
+      "Solfoton",
+      "Phenobarbitone",
       "Noptil",
+      "Luminal",
       "Talpheno"
     ],
     "associated_with": [
@@ -1396,6 +1691,18 @@
       "rxnorm_prescribable",
       "chembl_phase_4",
       "gtopdb_approved"
+    ],
+    "has_indication": [
+      "[\"mesh:D013226\", \"Status Epilepticus\", \"ncit:C85079\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D012559\", \"Schizophrenia\", \"mondo:0005090\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D004827\", \"Epilepsy\", \"ncit:C3020\", {\"chembl_max_phase_for_ind\": \"chembl_phase_4\"}]",
+      "[\"mesh:D003866\", \"Depressive Disorder\", \"mondo:0002050\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009357\", \"Neonatal Abstinence Syndrome\", \"ncit:C87101\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D012640\", \"Seizures\", \"ncit:C3980\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009503\", \"Neutropenia\", \"mondo:0001475\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D001007\", \"Anxiety\", \"mondo:0011918\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008223\", \"Lymphoma\", \"ncit:C3208\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D003704\", \"Dementia\", \"mondo:0001627\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]"
     ]
   },
   {
@@ -1417,7 +1724,13 @@
       "drugsatfda.anda:075036",
       "drugsatfda.nda:018057"
     ],
-    "trade_names": ["Cisplatin", "Platinol", "PLATINOL", "PLATINOL-AQ"],
+    "trade_names": [
+      "Cisplatin",
+      "Platinol",
+      "PLATINOL",
+      "PLATINOL-AQ",
+      "Platinol-aq"
+    ],
     "aliases": [
       "1,2-Diaminocyclohexaneplatinum II citrate",
       "APRD00359",
@@ -1440,13 +1753,11 @@
       "Platinol-AQ",
       "Platinol",
       "cisplatino",
-      "Cisplatin",
       "Cis-platinum ii",
       "Cisplatinum",
       "INT-230-6 COMPONENT CISPLATIN",
       "INT230-6 COMPONENT CISPLATIN",
       "NSC-119875",
-      "Platinol-aq",
       "DACP",
       "NSC 119875",
       "cis-diamminedichloroplatinum III",
@@ -1500,35 +1811,168 @@
       "rxnorm_prescribable",
       "hemonc_approved",
       "fda_prescription",
-      "chembl_phase_4"
+      "chembl_phase_4",
+      "gtopdb_approved"
     ],
     "approval_year": ["1978"],
     "has_indication": [
-      ["hemonc:671", "Testicular cancer", "ncit:C7251"],
-      ["hemonc:645", "Ovarian cancer", "ncit:C7431"],
-      ["hemonc:569", "Bladder cancer", "ncit:C9334"]
+      "[\"hemonc:671\", \"Testicular cancer\", \"ncit:C7251\", {\"regulatory_body\": \"FDA\"}]",
+      "[\"hemonc:569\", \"Bladder cancer\", \"ncit:C9334\", {\"regulatory_body\": \"FDA\"}]",
+      "[\"hemonc:645\", \"Ovarian cancer\", \"ncit:C7431\", {\"regulatory_body\": \"FDA\"}]",
+      "[\"mesh:D016545\", \"Choroid Plexus Neoplasms\", \"ncit:C4533\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D005910\", \"Glioma\", \"ncit:C3059\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D005185\", \"Fallopian Tube Neoplasms\", \"ncit:C3867\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009101\", \"Multiple Myeloma\", \"ncit:C3242\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D010190\", \"Pancreatic Neoplasms\", \"ncit:C3305\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009190\", \"Myelodysplastic Syndromes\", \"ncit:C3247\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D064129\", \"Prostatic Neoplasms, Castration-Resistant\", \"DOID:0080909\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D018285\", \"Klatskin Tumor\", \"ncit:C36077\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D012175\", \"Retinoblastoma\", \"ncit:C7541\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009303\", \"Nasopharyngeal Neoplasms\", \"ncit:C3257\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D055752\", \"Small Cell Lung Carcinoma\", \"ncit:C4917\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009369\", \"Neoplasms\", \"ncit:C3262\", {\"chembl_max_phase_for_ind\": \"chembl_phase_4\"}]",
+      "[\"mesh:D001005\", \"Anus Neoplasms\", \"ncit:C2877\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D031901\", \"Gestational Trophoblastic Disease\", \"ncit:C4699\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D006689\", \"Hodgkin Disease\", \"ncit:C9357\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D015266\", \"Carcinoma, Merkel Cell\", \"ncit:C9231\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"EFO:1000043\", \"ovarian serous cystadenocarcinoma\", \"ncit:C7978\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D010610\", \"Pharyngeal Neoplasms\", \"ncit:C7545\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D014594\", \"Uterine Neoplasms\", \"ncit:C3552\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D018273\", \"Carcinoma, Islet Cell\", \"ncit:C3770\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D018278\", \"Carcinoma, Neuroendocrine\", \"ncit:C3773\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D052016\", \"Mucositis\", \"ncit:C3853\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002280\", \"Carcinoma, Basal Cell\", \"ncit:C156767\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D005706\", \"Gallbladder Neoplasms\", \"ncit:C7481\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002276\", \"Carcinoid Tumor\", \"ncit:C2915\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D013964\", \"Thyroid Neoplasms\", \"ncit:C7510\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D002292\", \"Carcinoma, Renal Cell\", \"mondo:0005086\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D020250\", \"Postoperative Nausea and Vomiting\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009447\", \"Neuroblastoma\", \"ncit:C3270\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001749\", \"Urinary Bladder Neoplasms\", \"ncit:C9334\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"EFO:0009708\", \"metastasis\", \"ncit:C3261\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D018269\", \"Carcinoma, Endometrioid\", \"ncit:C7558\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D007822\", \"Laryngeal Neoplasms\", \"ncit:C3156\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D006258\", \"Head and Neck Neoplasms\", \"ncit:C4013\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D018239\", \"Seminoma\", \"ncit:C9309\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D000230\", \"Adenocarcinoma\", \"ncit:C2852\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D014987\", \"Xerostomia\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"EFO:0005570\", \"oral cavity cancer\", \"ncit:C9314\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001932\", \"Brain Neoplasms\", \"ncit:C3568\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D058922\", \"Inflammatory Breast Neoplasms\", \"ncit:C4001\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D016543\", \"Central Nervous System Neoplasms\", \"ncit:C4627\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D007012\", \"Hypopharyngeal Neoplasms\", \"ncit:C7190\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008223\", \"Lymphoma\", \"ncit:C3208\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D000077192\", \"Adenocarcinoma of Lung\", \"ncit:C3512\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008527\", \"Medulloblastoma\", \"ncit:C3222\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D018312\", \"Sex Cord-Gonadal Stromal Tumors\", \"ncit:C3794\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D013280\", \"Stomatitis\", \"ncit:C26887\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D064726\", \"Triple Negative Breast Neoplasms\", \"ncit:C71732\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D009373\", \"Neoplasms, Germ Cell and Embryonal\", \"ncit:C3708\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D021441\", \"Carcinoma, Pancreatic Ductal\", \"ncit:C9120\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D018305\", \"Ganglioneuroblastoma\", \"ncit:C3790\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D010534\", \"Peritoneal Neoplasms\", \"ncit:C3322\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D007674\", \"Kidney Diseases\", \"ncit:C3149\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D010412\", \"Penile Neoplasms\", \"ncit:C3317\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D010255\", \"Paranasal Sinus Neoplasms\", \"ncit:C6014\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D010996\", \"Pleural Effusion\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001661\", \"Biliary Tract Neoplasms\", \"mondo:0003060\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D012509\", \"Sarcoma\", \"ncit:C9118\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009325\", \"Nausea\", null, {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D018197\", \"Hepatoblastoma\", \"ncit:C3728\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D012208\", \"Rhabdomyosarcoma\", \"ncit:C3359\", {\"chembl_max_phase_for_ind\": \"chembl_phase_0\"}]",
+      "[\"mesh:D013274\", \"Stomach Neoplasms\", \"ncit:C3387\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D014846\", \"Vulvar Neoplasms\", \"ncit:C7502\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D013953\", \"Thymus Neoplasms\", \"ncit:C4962\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D020522\", \"Lymphoma, Mantle-Cell\", \"ncit:C4337\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D007938\", \"Leukemia\", \"ncit:C3161\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D016411\", \"Lymphoma, T-Cell, Peripheral\", \"ncit:C3468\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D015179\", \"Colorectal Neoplasms\", \"ncit:C2956\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D013945\", \"Thymoma\", \"ncit:C3411\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D018242\", \"Neuroectodermal Tumors, Primitive\", \"ncit:C3222\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D004066\", \"Digestive System Diseases\", \"ncit:C3959\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D008654\", \"Mesothelioma\", \"ncit:C3234\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D013724\", \"Teratoma\", \"ncit:C3403\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D016889\", \"Endometrial Neoplasms\", \"ncit:C3012\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008107\", \"Liver Diseases\", \"ncit:C3196\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D015459\", \"Leukemia-Lymphoma, Adult T-Cell\", \"ncit:C3184\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D016403\", \"Lymphoma, Large B-Cell, Diffuse\", \"ncit:C8851\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D009959\", \"Oropharyngeal Neoplasms\", \"ncit:C7398\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D014523\", \"Urethral Neoplasms\", \"ncit:C3619\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D012516\", \"Osteosarcoma\", \"ncit:C53707\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D014062\", \"Tongue Neoplasms\", \"ncit:C9345\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D014565\", \"Urogenital Neoplasms\", \"mondo:0025370\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008113\", \"Liver Neoplasms\", \"ncit:C34803\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D000077195\", \"Squamous Cell Carcinoma of Head and Neck\", \"ncit:C4044\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D007119\", \"Immunoblastic Lymphadenopathy\", \"ncit:C7528\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D013736\", \"Testicular Neoplasms\", \"ncit:C7251\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D006528\", \"Carcinoma, Hepatocellular\", \"ncit:C3099\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D018236\", \"Carcinoma, Embryonal\", \"ncit:C3752\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D001943\", \"Breast Neoplasms\", \"ncit:C2910\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002294\", \"Carcinoma, Squamous Cell\", \"ncit:C2929\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D000740\", \"Anemia\", \"ncit:C2869\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008175\", \"Lung Neoplasms\", \"ncit:C3200\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008228\", \"Lymphoma, Non-Hodgkin\", \"ncit:C3211\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D017728\", \"Lymphoma, Large-Cell, Anaplastic\", \"ncit:C3720\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D010051\", \"Ovarian Neoplasms\", \"ncit:C7431\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008224\", \"Lymphoma, Follicular\", \"ncit:C3209\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D007680\", \"Kidney Neoplasms\", \"ncit:C7548\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D004067\", \"Digestive System Neoplasms\", \"ncit:C4890\", {\"chembl_max_phase_for_ind\": \"chembl_phase_1\"}]",
+      "[\"mesh:D002277\", \"Carcinoma\", \"ncit:C2916\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D046152\", \"Gastrointestinal Stromal Tumors\", \"ncit:C3868\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D004806\", \"Ependymoma\", \"ncit:C3017\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002289\", \"Carcinoma, Non-Small-Cell Lung\", \"ncit:C2926\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002583\", \"Uterine Cervical Neoplasms\", \"ncit:C9311\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D008479\", \"Mediastinal Neoplasms\", \"ncit:C3549\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D006103\", \"Granuloma, Lethal Midline\", \"mondo:0006828\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D008288\", \"Malaria\", \"ncit:C34797\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D000306\", \"Adrenal Cortex Neoplasms\", \"ncit:C9325\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D018240\", \"Endodermal Sinus Tumor\", \"ncit:C3011\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D004938\", \"Esophageal Neoplasms\", \"ncit:C7478\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D012468\", \"Salivary Gland Neoplasms\", \"ncit:C3811\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"EFO:0003868\", \"mouth neoplasm\", \"ncit:C7606\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D002822\", \"Choriocarcinoma\", \"ncit:C2948\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D018281\", \"Cholangiocarcinoma\", \"ncit:C4436\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]",
+      "[\"mesh:D016483\", \"Lymphoma, AIDS-Related\", \"ncit:C3471\", {\"chembl_max_phase_for_ind\": \"chembl_phase_2\"}]",
+      "[\"mesh:D008545\", \"Melanoma\", \"ncit:C3224\", {\"chembl_max_phase_for_ind\": \"chembl_phase_3\"}]"
     ]
   },
   {
-    "label_and_type": "ncit:c839##merger",
+    "label_and_type": "rxcui:9991##merger",
     "item_type": "merger",
-    "concept_id": "ncit:C839",
-    "xrefs": ["chemidplus:8025-81-8", "wikidata:Q422265"],
-    "label": "Spiramycin",
+    "concept_id": "rxcui:9991",
+    "xrefs": [
+      "ncit:C839",
+      "drugbank:DB06145",
+      "chemidplus:8025-81-8",
+      "wikidata:Q422265"
+    ],
     "aliases": [
+      "RP 5337",
       "SPIRAMYCIN",
+      "Foromacidine A",
+      "Spiramycine",
+      "Provamycin",
+      "Foromacidin A",
       "Antibiotic 799",
+      "spiramycin I",
       "Rovamycin",
-      "Provamycin",
-      "Rovamycine",
-      "RP 5337",
+      "Spiramycin A",
+      "Spiramycin 1",
       "(4R,5S,6R,7R,9R,10R,11E,13E,16R)-10-{[(2R,5S,6R)-5-(dimethylamino)-6-methyltetrahydro-2H-pyran-2-yl]oxy}-9,16-dimethyl-5-methoxy-2-oxo-7-(2-oxoethyl)oxacyclohexadeca-11,13-dien-6-yl 3,6-dideoxy-4-O-(2,6-dideoxy-3-C-methyl-alpha-L-ribo-hexopyranosyl)-3-(dimethylamino)-alpha-D-glucopyranoside",
-      "spiramycin I"
+      "Spiramycin I",
+      "Rovamycine",
+      "Demycarosylturimycin H"
     ],
+    "label": "spiramycin",
     "associated_with": [
+      "pubchem.compound:5356392",
       "umls:C0037962",
       "unii:71ODY0V87H",
-      "pubchem.compound:5356392"
+      "inchikey:ACTOXUHEUCPTEW-CEUOBAOPSA-N",
+      "mesh:C017186",
+      "atc:J01FA02",
+      "mesh:D015572",
+      "unii:033ECH6IFG"
     ]
   },
   {
@@ -1580,7 +2024,7 @@
     "label_and_type": "rxcui:142424##identity",
     "concept_id": "rxcui:142424",
     "label": "amiloride hydrochloride",
-    "approval_rating": "rxnorm_prescribable",
+    "approval_ratings": ["rxnorm_prescribable"],
     "aliases": [
       "aMILoride hydrochloride",
       "Amiloride Hydrochloride",
@@ -1620,7 +2064,7 @@
     "label_and_type": "rxcui:4493##identity",
     "concept_id": "rxcui:4493",
     "label": "fluoxetine",
-    "approval_rating": "rxnorm_prescribable",
+    "approval_ratings": ["rxnorm_prescribable"],
     "aliases": [
       "FLUoxetine",
       "N-Methyl-gamma-(4-(trifluoromethyl)phenoxy)benzenepropanamine",
@@ -1656,7 +2100,7 @@
     "label_and_type": "rxcui:227224##identity",
     "concept_id": "rxcui:227224",
     "label": "fluoxetine hydrochloride",
-    "approval_rating": "rxnorm_prescribable",
+    "approval_ratings": ["rxnorm_prescribable"],
     "aliases": ["FLUoxetine hydrochloride", "Fluoxetine Hydrochloride"],
     "associated_with": [
       "usp:m33780",
@@ -1693,7 +2137,7 @@
     "merge_ref": "rxcui:4126",
     "concept_id": "rxcui:4126",
     "label_and_type": "rxcui:4126##identity",
-    "approval_rating": "rxnorm_prescribable",
+    "approval_ratings": ["rxnorm_prescribable"],
     "associated_with": [
       "usp:m2600",
       "mesh:D004999",
@@ -1799,12 +2243,12 @@
       "CDDP"
     ],
     "xrefs": ["rxcui:2555"],
-    "approval_rating": "hemonc_approved",
+    "approval_ratings": ["hemonc_approved"],
     "approval_year": ["1978"],
     "has_indication": [
-      ["hemonc:671", "Testicular cancer", "ncit:C7251"],
-      ["hemonc:645", "Ovarian cancer", "ncit:C7431"],
-      ["hemonc:569", "Bladder cancer", "ncit:C9334"]
+      "[\"hemonc:569\", \"Bladder cancer\", \"ncit:C9334\", {\"regulatory_body\": \"FDA\"}]",
+      "[\"hemonc:645\", \"Ovarian cancer\", \"ncit:C7431\", {\"regulatory_body\": \"FDA\"}]",
+      "[\"hemonc:671\", \"Testicular cancer\", \"ncit:C7251\", {\"regulatory_body\": \"FDA\"}]"
     ]
   },
   {
@@ -1869,11 +2313,11 @@
       "Treanda",
       "Xyotin"
     ],
-    "approval_rating": "hemonc_approved",
+    "approval_ratings": ["hemonc_approved"],
     "approval_year": ["2008", "2015"],
     "has_indication": [
-      ["hemonc:581", "Chronic lymphocytic leukemia", "ncit:C3163"],
-      ["hemonc:46094", "Indolent lymphoma", "ncit:C8504"]
+      "[\"hemonc:581\", \"Chronic lymphocytic leukemia\", \"ncit:C3163\", {\"regulatory_body\": \"FDA\"}]",
+      "[\"hemonc:46094\", \"Indolent lymphoma\", \"ncit:C8504\", {\"regulatory_body\": \"FDA\"}]"
     ]
   },
   {
@@ -1942,11 +2386,11 @@
       "Treanda",
       "Xyotin"
     ],
-    "approval_rating": "hemonc_approved",
+    "approval_ratings": ["hemonc_approved"],
     "approval_year": ["2008", "2015"],
     "has_indication": [
-      ["hemonc:581", "Chronic lymphocytic leukemia", "ncit:C3163"],
-      ["hemonc:46094", "Indolent lymphoma", "ncit:C8504"]
+      "[\"hemonc:581\", \"Chronic lymphocytic leukemia\", \"ncit:C3163\", {\"regulatory_body\": \"FDA\"}]",
+      "[\"hemonc:46094\", \"Indolent lymphoma\", \"ncit:C8504\", {\"regulatory_body\": \"FDA\"}]"
     ]
   },
   {
@@ -1958,9 +2402,11 @@
     "aliases": ["degarelix acetate", "FE200486", "ASP3550"],
     "xrefs": ["rxcui:475230"],
     "trade_names": ["Firmagon"],
-    "approval_rating": "hemonc_approved",
+    "approval_ratings": ["hemonc_approved"],
     "approval_year": ["2008"],
-    "has_indication": [["hemonc:658", "Prostate cancer", "ncit:C7378"]]
+    "has_indication": [
+      "[\"hemonc:658\", \"Prostate cancer\", \"ncit:C7378\", {\"regulatory_body\": \"FDA\"}]"
+    ]
   },
   {
     "label_and_type": "rxcui:475230##xref",
@@ -2083,7 +2529,7 @@
     "item_type": "identity",
     "concept_id": "iuphar.ligand:5343",
     "label": "cisplatin",
-    "approval_rating": "gtopdb_approved",
+    "approval_ratings": ["gtopdb_approved"],
     "xrefs": [
       "chembl:CHEMBL11359",
       "chemidplus:15663-27-1",
@@ -2182,7 +2628,7 @@
     "item_type": "identity",
     "concept_id": "iuphar.ligand:2804",
     "label": "phenobarbital",
-    "approval_rating": "gtopdb_approved",
+    "approval_ratings": ["gtopdb_approved"],
     "xrefs": ["chembl:CHEMBL40", "chemidplus:50-06-6", "drugbank:DB01174"],
     "associated_with": [
       "pubchem.substance:135650817",
@@ -2264,7 +2710,7 @@
     "item_type": "identity",
     "concept_id": "iuphar.ligand:240",
     "label": "cisapride",
-    "approval_rating": "gtopdb_withdrawn",
+    "approval_ratings": ["gtopdb_withdrawn"],
     "xrefs": ["chembl:CHEMBL1729", "chemidplus:81098-60-4", "drugbank:DB00604"],
     "associated_with": [
       "pubchem.substance:135650104",
@@ -2341,7 +2787,7 @@
       "ndc:0143-9505",
       "spl:2c569ef0-588f-4828-8b2d-03a2120c9b4c"
     ],
-    "approval_rating": "fda_prescription"
+    "approval_ratings": ["fda_prescription"]
   },
   {
     "label_and_type": "rxcui:309311##xref",
@@ -2376,7 +2822,7 @@
       "spl:c3ddc4a5-9f1b-a8ee-e053-2a95a90a2265",
       "spl:c43de769-d6d8-3bb9-e053-2995a90a5aa2"
     ],
-    "approval_rating": "fda_prescription"
+    "approval_ratings": ["fda_prescription"]
   },
   {
     "label_and_type": "rxcui:309311##xref",
@@ -2412,7 +2858,7 @@
       "spl:01c7a680-ee0d-42da-85e8-8d56c6fe7006",
       "spl:5a24d5bd-c44a-43f7-a04c-76caf3475012"
     ],
-    "approval_rating": "fda_prescription"
+    "approval_ratings": ["fda_prescription"]
   },
   {
     "label_and_type": "rxcui:309311##xref",
@@ -2445,7 +2891,7 @@
       "ndc:63323-103",
       "spl:9b008181-ab66-db2f-e053-2995a90aad57"
     ],
-    "approval_rating": "fda_prescription"
+    "approval_ratings": ["fda_prescription"]
   },
   {
     "label_and_type": "rxcui:309311##xref",
@@ -2479,7 +2925,7 @@
       "ndc:0703-5748",
       "spl:54b3415c-c095-4c82-b216-e0e6e6bb8d03"
     ],
-    "approval_rating": "fda_prescription"
+    "approval_ratings": ["fda_prescription"]
   },
   {
     "label_and_type": "unii:q20q21q62j##associated_with",
@@ -2552,7 +2998,7 @@
       "rxcui:2205094"
     ],
     "associated_with": ["unii:UQW7UF9N91", "unii:W34SHF8J2K"],
-    "approval_rating": "fda_prescription",
+    "approval_ratings": ["fda_prescription"],
     "trade_names": ["DUAKLIR PRESSAIR"]
   },
   {
@@ -2580,7 +3026,7 @@
       "rxcui:1303107"
     ],
     "associated_with": ["unii:UQW7UF9N91"],
-    "approval_rating": "fda_prescription",
+    "approval_ratings": ["fda_prescription"],
     "trade_names": ["TUDORZA PRESSAIR"]
   },
   {
@@ -2597,7 +3043,7 @@
     "label": "FORMOTEROL FUMARATE",
     "xrefs": ["rxcui:1246319"],
     "associated_with": ["unii:W34SHF8J2K"],
-    "approval_rating": "fda_prescription"
+    "approval_ratings": ["fda_prescription"]
   },
   {
     "label_and_type": "unii:w34shf8j2k##associated_with",
@@ -2614,7 +3060,7 @@
     "aliases": ["FORMOTEROL FUMARATE DIHYDRATE"],
     "xrefs": ["rxcui:1246321", "rxcui:1246319"],
     "associated_with": ["unii:W34SHF8J2K"],
-    "approval_rating": "fda_prescription",
+    "approval_ratings": ["fda_prescription"],
     "trade_names": ["PERFOROMIST"]
   },
   {
@@ -2650,14 +3096,14 @@
       "ndc:0078-0566",
       "ndc:0078-0594",
       "ndc:0078-0566",
-      "spl:8ad662ec-6e9b-4650-9f5a-78dda1f9f8f0",
+      "spl:e42ff4e2-3984-443d-be20-17b96e63da53",
       "ndc:0078-0567",
       "ndc:0078-0620",
       "ndc:0078-0628",
       "ndc:0078-0626",
       "ndc:0078-0627"
     ],
-    "approval_rating": "fda_prescription",
+    "approval_ratings": ["fda_prescription"],
     "trade_names": ["AFINITOR"]
   },
   {
@@ -2716,7 +3162,7 @@
       "spl:137c07d7-e2bf-4f59-8b8f-4ebe119e576d",
       "spl:b92f5536-179c-6234-e053-2995a90a0f25"
     ],
-    "approval_rating": "fda_prescription",
+    "approval_ratings": ["fda_prescription"],
     "trade_names": ["COSMEGEN"]
   },
   {
@@ -2763,7 +3209,7 @@
       "spl:c1bfb82a-814b-23f3-e053-2995a90ae9cf",
       "spl:c1bfb82a-8192-23f3-e053-2995a90ae9cf"
     ],
-    "approval_rating": "fda_prescription",
+    "approval_ratings": ["fda_prescription"],
     "trade_names": ["NALFON"]
   },
   {
@@ -2791,20 +3237,28 @@
     "label": "FENOPROFEN CALCIUM",
     "concept_id": "drugsatfda.nda:017604",
     "associated_with": [
-      "unii:0X2CW1QABJ",
+      "ndc:0276-0501",
+      "ndc:0276-0502",
+      "ndc:0276-0503",
       "ndc:15014-400",
       "ndc:42195-100",
       "ndc:42195-308",
       "ndc:42195-600",
       "ndc:69336-113",
-      "ndc:69336-124",
-      "spl:81a0da5b-6078-413e-b6d0-d31c1073b3f7",
       "spl:bedf1661-b811-3d85-e053-2995a90acd59",
       "spl:c1721025-8af3-5451-e053-2a95a90a7dc0",
       "spl:c1829550-d270-e13d-e053-2995a90a4aa5",
-      "spl:c187dfec-eec5-4227-e053-2995a90ab55c"
+      "spl:c187dfec-eec5-4227-e053-2995a90ab55c",
+      "spl:d33ad32a-f205-5df2-e053-2995a90ab978",
+      "unii:0X2CW1QABJ"
+    ],
+    "xrefs": [
+      "rxcui:197694",
+      "rxcui:197695",
+      "rxcui:858118",
+      "rxcui:858116",
+      "rxcui:260323"
     ],
-    "xrefs": ["rxcui:197694", "rxcui:858118", "rxcui:858116", "rxcui:260323"],
     "trade_names": ["NALFON", "FENORTHO"]
   },
   {
@@ -2864,7 +3318,7 @@
       "mmsl:52894",
       "mmsl:d00333"
     ],
-    "approval_rating": "rxnorm_prescribable"
+    "approval_ratings": ["rxnorm_prescribable"]
   },
   {
     "label_and_type": "penicillamine##label",
@@ -2877,5 +3331,80 @@
     "src_name": "RxNorm",
     "concept_id": "rxcui:7975",
     "item_type": "trade_name"
+  },
+  {
+    "label_and_type": "drugbank:db06145##identity",
+    "concept_id": "drugbank:DB06145",
+    "aliases": [
+      "Foromacidin A",
+      "Spiramycin A",
+      "Spiramycin 1",
+      "Spiramycin I",
+      "Foromacidine A",
+      "Demycarosylturimycin H"
+    ],
+    "associated_with": [
+      "inchikey:ACTOXUHEUCPTEW-KWBWCIJSSA-N",
+      "unii:033ECH6IFG"
+    ],
+    "label": "Spiramycin",
+    "merge_ref": "rxcui:9991",
+    "xrefs": ["chemidplus:24916-50-5"],
+    "item_type": "identity",
+    "src_name": "DrugBank"
+  },
+  {
+    "label_and_type": "chemidplus:24916-50-5##xref",
+    "concept_id": "drugbank:db06145",
+    "src_name": "DrugBank",
+    "item_type": "xref"
+  },
+  {
+    "label_and_type": "wikidata:q422265##identity",
+    "concept_id": "wikidata:Q422265",
+    "aliases": ["spiramycin I"],
+    "associated_with": ["pubchem.compound:5356392"],
+    "label": "spiramycin",
+    "merge_ref": "rxcui:9991",
+    "xrefs": ["rxcui:9991", "chembl:CHEMBL1256397", "chemidplus:8025-81-8"],
+    "item_type": "identity",
+    "src_name": "Wikidata"
+  },
+  {
+    "label_and_type": "chemidplus:8025-81-8##xref",
+    "item_type": "xref",
+    "concept_id": "wikidata:q422265",
+    "src_name": "wikidata"
+  },
+  {
+    "label_and_type": "rxcui:9991##xref",
+    "item_type": "xref",
+    "concept_id": "wikidata:q422265",
+    "src_name": "wikidata"
+  },
+  {
+    "label_and_type": "rxcui:9991##identity",
+    "concept_id": "rxcui:9991",
+    "aliases": [
+      "Spiramycine",
+      "Foromacidin A",
+      "Spiramycin A",
+      "Spiramycin 1",
+      "Spiramycin I",
+      "Foromacidine A",
+      "Demycarosylturimycin H"
+    ],
+    "associated_with": ["mesh:C017186", "atc:J01FA02", "mesh:D015572"],
+    "label": "spiramycin",
+    "merge_ref": "rxcui:9991",
+    "xrefs": ["drugbank:DB06145"],
+    "item_type": "identity",
+    "src_name": "RxNorm"
+  },
+  {
+    "label_and_type": "drugbank:db06145##xref",
+    "item_type": "xref",
+    "src_name": "RxNorm",
+    "concept_id": "rxcui:9991"
   }
 ]
diff --git a/tests/unit/test_chembl.py b/tests/unit/test_chembl.py
index daed638d..8883290b 100644
--- a/tests/unit/test_chembl.py
+++ b/tests/unit/test_chembl.py
@@ -1,5 +1,7 @@
 """Test that the therapy normalizer works as intended for the ChEMBL source."""
 import re
+import json
+from pathlib import Path
 
 import pytest
 
@@ -17,71 +19,34 @@ def __init__(self):
             self.query_handler = QueryHandler()
 
         def search(self, query_str):
-            resp = self.query_handler.search_sources(query_str, keyed=True,
-                                                     incl="chembl")
-            return resp["source_matches"]["ChEMBL"]
+            resp = self.query_handler.search(query_str, keyed=True, incl="chembl")
+            return resp.source_matches["ChEMBL"]
     return QueryGetter()
 
 
 @pytest.fixture(scope="module")
-def cisplatin():
+def fixture_data(test_data: Path):
+    """Fetch fixture data"""
+    return json.load(open(test_data / "test_chembl_data.json", "r"))
+
+
+@pytest.fixture(scope="module")
+def cisplatin(fixture_data):
     """Create a cisplatin drug fixture."""
-    params = {
-        "label": "CISPLATIN",
-        "concept_id": "chembl:CHEMBL11359",
-        "aliases": [
-            "Cisplatin",
-            "Cis-platinum ii",
-            "Cisplatinum",
-            "cis-diamminedichloroplatinum(II)",
-            "CIS-DDP",
-            "INT-230-6 COMPONENT CISPLATIN",
-            "INT230-6 COMPONENT CISPLATIN",
-            "Liplacis",
-            "NSC-119875",
-            "Platinol",
-            "Platinol-aq",
-        ],
-        "approval_rating": "chembl_phase_4",
-        "xrefs": [],
-        "associated_with": [],
-        "trade_names": [
-            "PLATINOL",
-            "PLATINOL-AQ"
-        ]
-    }
-    return Drug(**params)
+    return Drug(**fixture_data["cisplatin"])
 
 
 @pytest.fixture(scope="module")
-def l745870():
+def l745870(fixture_data):
     """Create a L-745870 drug fixture."""
-    params = {
-        "label": "L-745870",
-        "concept_id": "chembl:CHEMBL267014",
-        "aliases": [],
-        "approval_rating": "chembl_phase_0",
-        "xrefs": [],
-        "associated_with": [],
-        "trade_names": []
-    }
-    return Drug(**params)
+    return Drug(**fixture_data["l745870"])
 
 
 # Test with aliases and trade names > 20
 @pytest.fixture(scope="module")
-def aspirin():
+def aspirin(fixture_data):
     """Create an aspirin drug fixture."""
-    params = {
-        "label": "ASPIRIN",
-        "concept_id": "chembl:CHEMBL25",
-        "aliases": [],
-        "approval_rating": "chembl_phase_4",
-        "xrefs": [],
-        "associated_with": [],
-        "trade_names": []
-    }
-    return Drug(**params)
+    return Drug(**fixture_data["aspirin"])
 
 
 def test_concept_id_cisplatin(cisplatin, chembl):
@@ -89,31 +54,31 @@ def test_concept_id_cisplatin(cisplatin, chembl):
     as a CONCEPT_ID match.
     """
     response = chembl.search("chembl:CHEMBL11359")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = chembl.search("CHEMBL11359")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = chembl.search("chembl:chembl11359")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = chembl.search("cHEmbl:chembl11359")
-    assert response["match_type"] == \
+    assert response.match_type == \
            MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = chembl.search("cHEmbl:CHEMBL11359")
-    assert response["match_type"] == \
+    assert response.match_type == \
            MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
 
 def test_cisplatin_label(cisplatin, chembl):
@@ -121,22 +86,22 @@ def test_cisplatin_label(cisplatin, chembl):
     as a LABEL match.
     """
     response = chembl.search("CISPLATIN")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 2
-    if len(response["records"][0]["aliases"]) > len(response["records"][1]["aliases"]):
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 2
+    if len(response.records[0].aliases) > len(response.records[1].aliases):
         ind = 0
     else:
         ind = 1
-    compare_records(response["records"][ind], cisplatin)
+    compare_records(response.records[ind], cisplatin)
 
     response = chembl.search("cisplatin")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 2
-    if len(response["records"][0]["aliases"]) > len(response["records"][1]["aliases"]):
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 2
+    if len(response.records[0].aliases) > len(response.records[1].aliases):
         ind = 0
     else:
         ind = 1
-    compare_records(response["records"][ind], cisplatin)
+    compare_records(response.records[ind], cisplatin)
 
 
 def test_cisplatin_alias(cisplatin, chembl):
@@ -144,30 +109,30 @@ def test_cisplatin_alias(cisplatin, chembl):
     ALIAS match.
     """
     response = chembl.search("cis-diamminedichloroplatinum(II)")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = chembl.search("INT230-6 COMPONENT CISPLATIn")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
 
 def test_no_match(chembl):
     """Test that a term normalizes to correct drug concept as a NO match."""
     response = chembl.search("cisplati")
-    assert response["match_type"] == MatchType.NO_MATCH
-    assert len(response["records"]) == 0
+    assert response.match_type == MatchType.NO_MATCH
+    assert len(response.records) == 0
 
     # Test white space in between label
     response = chembl.search("L - 745870")
-    assert response["match_type"] == MatchType.NO_MATCH
+    assert response.match_type == MatchType.NO_MATCH
 
     # Test empty query
     response = chembl.search("")
-    assert response["match_type"] == MatchType.NO_MATCH
-    assert len(response["records"]) == 0
+    assert response.match_type == MatchType.NO_MATCH
+    assert len(response.records) == 0
 
 
 def test_l745870_concept_id(l745870, chembl):
@@ -175,29 +140,29 @@ def test_l745870_concept_id(l745870, chembl):
     as a CONCEPT_ID match.
     """
     response = chembl.search("chembl:CHEMBL267014")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], l745870)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], l745870)
 
     response = chembl.search("CHEMBL267014")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], l745870)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], l745870)
 
     response = chembl.search("chembl:chembl267014")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], l745870)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], l745870)
 
     response = chembl.search("cHEmbl:chembl267014")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], l745870)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], l745870)
 
     response = chembl.search("cHEmbl:CHEMBL267014")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], l745870)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], l745870)
 
 
 def test_l745870_label(l745870, chembl):
@@ -205,14 +170,14 @@ def test_l745870_label(l745870, chembl):
     as a LABEL match.
     """
     response = chembl.search("L-745870")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], l745870)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], l745870)
 
     response = chembl.search("l-745870")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], l745870)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], l745870)
 
 
 def test_aspirin_concept_id(aspirin, chembl):
@@ -220,29 +185,29 @@ def test_aspirin_concept_id(aspirin, chembl):
     as a CONCEPT_ID match.
     """
     response = chembl.search("chembl:CHEMBL25")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], aspirin)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], aspirin)
 
     response = chembl.search("CHEMBL25")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], aspirin)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], aspirin)
 
     response = chembl.search("chembl:chembl25")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], aspirin)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], aspirin)
 
     response = chembl.search("cHEmbl:chembl25")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], aspirin)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], aspirin)
 
     response = chembl.search("cHEmbl:CHEMBL25")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], aspirin)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], aspirin)
 
 
 def test_aspirin_label(aspirin, chembl):
@@ -250,27 +215,27 @@ def test_aspirin_label(aspirin, chembl):
     as a LABEL match.
     """
     response = chembl.search("ASPIRIN")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], aspirin)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], aspirin)
 
     response = chembl.search("aspirin")
-    assert response["match_type"] ==\
+    assert response.match_type ==\
            MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], aspirin)
+    assert len(response.records) == 1
+    compare_records(response.records[0], aspirin)
 
 
 def test_meta_info(chembl):
     """Test that the meta field is correct."""
     response = chembl.search("cisplatin")
-    assert response["source_meta_"]["data_license"] == "CC BY-SA 3.0"
-    assert response["source_meta_"]["data_license_url"] == \
+    assert response.source_meta_.data_license == "CC BY-SA 3.0"
+    assert response.source_meta_.data_license_url == \
            "https://creativecommons.org/licenses/by-sa/3.0/"
-    assert re.match(r"[0-3][0-9]", response["source_meta_"]["version"])
-    assert response["source_meta_"]["data_url"].startswith("ftp://ftp.ebi.ac.uk/pub/databases/chembl/ChEMBLdb")  # noqa: E501
-    assert response["source_meta_"]["rdp_url"] == "http://reusabledata.org/chembl.html"
-    assert response["source_meta_"]["data_license_attributes"] == {
+    assert re.match(r"[0-3][0-9]", response.source_meta_.version)
+    assert response.source_meta_.data_url.startswith("ftp://ftp.ebi.ac.uk/pub/databases/chembl/ChEMBLdb")  # noqa: E501
+    assert response.source_meta_.rdp_url == "http://reusabledata.org/chembl.html"
+    assert response.source_meta_.data_license_attributes == {
         "non_commercial": False,
         "share_alike": True,
         "attribution": True
diff --git a/tests/unit/test_chemidplus.py b/tests/unit/test_chemidplus.py
index 9dccba71..f85dff9b 100644
--- a/tests/unit/test_chemidplus.py
+++ b/tests/unit/test_chemidplus.py
@@ -16,9 +16,8 @@ def __init__(self):
             self.normalizer = QueryHandler()
 
         def search(self, query_str):
-            resp = self.normalizer.search_sources(query_str, keyed=True,
-                                                  incl="chemidplus")
-            return resp["source_matches"]["ChemIDplus"]
+            resp = self.normalizer.search(query_str, keyed=True, incl="chemidplus")
+            return resp.source_matches["ChemIDplus"]
     return QueryGetter()
 
 
@@ -109,95 +108,95 @@ def glycopyrronium_bromide():
 def test_penicillin(chemidplus, penicillin_v):
     """Test record retrieval for Penicillin V."""
     response = chemidplus.search("chemidplus:87-08-1")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], penicillin_v)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], penicillin_v)
 
     response = chemidplus.search("CHemidplus:87-08-1")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], penicillin_v)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], penicillin_v)
 
     response = chemidplus.search("Penicillin V")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], penicillin_v)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], penicillin_v)
 
     response = chemidplus.search("Phenoxymethylpenicillin")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], penicillin_v)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], penicillin_v)
 
     response = chemidplus.search("drugbank:DB00417")
-    assert response["match_type"] == MatchType.XREF
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], penicillin_v)
+    assert response.match_type == MatchType.XREF
+    assert len(response.records) == 1
+    compare_records(response.records[0], penicillin_v)
 
     response = chemidplus.search("unii:Z61I075U2W")
-    assert response["match_type"] == MatchType.ASSOCIATED_WITH
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], penicillin_v)
+    assert response.match_type == MatchType.ASSOCIATED_WITH
+    assert len(response.records) == 1
+    compare_records(response.records[0], penicillin_v)
 
     response = chemidplus.search("87081")
-    assert response["match_type"] == MatchType.NO_MATCH
+    assert response.match_type == MatchType.NO_MATCH
 
     response = chemidplus.search("PenicillinV")
-    assert response["match_type"] == MatchType.NO_MATCH
+    assert response.match_type == MatchType.NO_MATCH
 
 
 def test_imatinib(chemidplus, imatinib, other_imatinib):
     """Test record retrieval for imatinib."""
     response = chemidplus.search("Imatinib")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], imatinib)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], imatinib)
 
     response = chemidplus.search("imatiniB")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], imatinib)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], imatinib)
 
     response = chemidplus.search("drugbank:DB00619")
-    assert response["match_type"] == MatchType.XREF
-    assert len(response["records"]) == 2
-    for record in response["records"]:
-        if record["concept_id"] == "chemidplus:152459-95-5":
+    assert response.match_type == MatchType.XREF
+    assert len(response.records) == 2
+    for record in response.records:
+        if record.concept_id == "chemidplus:152459-95-5":
             compare_records(record, imatinib)
-        elif record["concept_id"] == "chemidplus:220127-57-1":
+        elif record.concept_id == "chemidplus:220127-57-1":
             compare_records(record, other_imatinib)
         else:
             assert False  # retrieved incorrect record
 
     response = chemidplus.search("unii:BKJ8M8G5HI")
-    assert response["match_type"] == MatchType.ASSOCIATED_WITH
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], imatinib)
+    assert response.match_type == MatchType.ASSOCIATED_WITH
+    assert len(response.records) == 1
+    compare_records(response.records[0], imatinib)
 
 
 def test_cisplatin(chemidplus, cisplatin):
     """Test record retrieval for cisplatin."""
     response = chemidplus.search("chemidplus:15663-27-1")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = chemidplus.search("Cisplatin")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = chemidplus.search("cis-Diaminedichloroplatinum")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = chemidplus.search("drugbank:DB00515")
-    assert response["match_type"] == MatchType.XREF
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.XREF
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = chemidplus.search("Cisplatine")
-    assert response["match_type"] == MatchType.NO_MATCH
+    assert response.match_type == MatchType.NO_MATCH
 
 
 def test_glycopyrronium_bromide(chemidplus, glycopyrronium_bromide):
@@ -205,20 +204,20 @@ def test_glycopyrronium_bromide(chemidplus, glycopyrronium_bromide):
     to check on input QC.
     """
     response = chemidplus.search("chemidplus:51186-83-5")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], glycopyrronium_bromide)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], glycopyrronium_bromide)
 
 
 def test_meta(chemidplus):
     """Test correctness of source metadata."""
     response = chemidplus.search("incoherent-string-of-text")
-    assert response["source_meta_"]["data_license"] == "custom"
-    assert response["source_meta_"]["data_license_url"] == "https://www.nlm.nih.gov/databases/download/terms_and_conditions.html"  # noqa: E501
-    assert isodate.parse_date(response["source_meta_"]["version"])
-    assert response["source_meta_"]["data_url"] == "ftp://ftp.nlm.nih.gov/nlmdata/.chemidlease/"  # noqa: E501
-    assert response["source_meta_"]["rdp_url"] is None
-    assert response["source_meta_"]["data_license_attributes"] == {
+    assert response.source_meta_.data_license == "custom"
+    assert response.source_meta_.data_license_url == "https://www.nlm.nih.gov/databases/download/terms_and_conditions.html"  # noqa: E501
+    assert isodate.parse_date(response.source_meta_.version)
+    assert response.source_meta_.data_url == "ftp://ftp.nlm.nih.gov/nlmdata/.chemidlease/"  # noqa: E501
+    assert response.source_meta_.rdp_url is None
+    assert response.source_meta_.data_license_attributes == {
         "non_commercial": False,
         "share_alike": False,
         "attribution": True
diff --git a/tests/unit/test_database.py b/tests/unit/test_database.py
index 51937401..f722147b 100644
--- a/tests/unit/test_database.py
+++ b/tests/unit/test_database.py
@@ -48,7 +48,7 @@ def test_item_type(db):  # noqa: F811
     assert "item_type" in item
     assert item["item_type"] == "trade_name"
 
-    filter_exp = Key("label_and_type").eq("ncit:c839##merger")
+    filter_exp = Key("label_and_type").eq("rxcui:9991##merger")
     item = db.therapies.query(KeyConditionExpression=filter_exp)["Items"][0]
     assert "item_type" in item
     assert item["item_type"] == "merger"
diff --git a/tests/unit/test_drugbank.py b/tests/unit/test_drugbank.py
index b75ab9f7..925843a6 100644
--- a/tests/unit/test_drugbank.py
+++ b/tests/unit/test_drugbank.py
@@ -19,9 +19,8 @@ def __init__(self):
             self.query_handler = QueryHandler()
 
         def search(self, query_str):
-            resp = self.query_handler.search_sources(query_str, keyed=True,
-                                                     incl="drugbank")
-            return resp["source_matches"]["DrugBank"]
+            resp = self.query_handler.search(query_str, keyed=True, incl="drugbank")
+            return resp.source_matches["DrugBank"]
 
         def fetch_meta(self):
             return self.query_handler._fetch_meta("DrugBank")
@@ -149,7 +148,7 @@ def test_label_match(drugbank, cisplatin, bentiromide, aloe_ferox_leaf):
     compare_response(response, MatchType.LABEL, aloe_ferox_leaf)
 
 
-def test_alias_match(drugbank, cisplatin, bentiromide, aloe_ferox_leaf):
+def test_alias_match(drugbank, cisplatin, bentiromide):
     """Test that alias query resolves to correct record."""
     response = drugbank.search("CISPLATINO")
     compare_response(response, MatchType.ALIAS, cisplatin)
@@ -165,10 +164,10 @@ def test_alias_match(drugbank, cisplatin, bentiromide, aloe_ferox_leaf):
 
     # verify aliases > 20 not stored
     response = drugbank.search("Aloe Capensis")
-    assert response["match_type"] == MatchType.NO_MATCH
+    assert response.match_type == MatchType.NO_MATCH
 
     response = drugbank.search("Aloe Ferox Juice")
-    assert response["match_type"] == MatchType.NO_MATCH
+    assert response.match_type == MatchType.NO_MATCH
 
 
 def test_xref_match(drugbank, cisplatin, bentiromide):
@@ -195,17 +194,17 @@ def test_assoc_with_match(drugbank, cisplatin, bentiromide, aloe_ferox_leaf):
 def test_no_match(drugbank):
     """Test that a term normalizes to correct drug concept as a NO match."""
     response = drugbank.search("lepirudi")
-    assert response["match_type"] == MatchType.NO_MATCH
-    assert len(response["records"]) == 0
+    assert response.match_type == MatchType.NO_MATCH
+    assert len(response.records) == 0
 
     # Test white space in between id
     response = drugbank.search("DB 00001")
-    assert response["match_type"] == MatchType.NO_MATCH
+    assert response.match_type == MatchType.NO_MATCH
 
     # Test empty query
     response = drugbank.search("")
-    assert response["match_type"] == MatchType.NO_MATCH
-    assert len(response["records"]) == 0
+    assert response.match_type == MatchType.NO_MATCH
+    assert len(response.records) == 0
 
 
 def test_meta_info(drugbank):
diff --git a/tests/unit/test_drugsatfda.py b/tests/unit/test_drugsatfda.py
index 511d35b6..661f23f1 100644
--- a/tests/unit/test_drugsatfda.py
+++ b/tests/unit/test_drugsatfda.py
@@ -18,9 +18,8 @@ def __init__(self):
             self.normalizer = QueryHandler()
 
         def search(self, query_str):
-            resp = self.normalizer.search_sources(query_str, keyed=True,
-                                                  incl="drugsatfda")
-            return resp["source_matches"]["DrugsAtFDA"]
+            resp = self.normalizer.search(query_str, keyed=True, incl="drugsatfda")
+            return resp.source_matches["DrugsAtFDA"]
     return QueryGetter()
 
 
@@ -55,10 +54,10 @@ def everolimus() -> Drug:
             "ndc:0078-0626",
             "ndc:0078-0627",
             "ndc:0078-0628",
-            "spl:8ad662ec-6e9b-4650-9f5a-78dda1f9f8f0",
+            "spl:e42ff4e2-3984-443d-be20-17b96e63da53",
             "unii:9HW64Q8G6G",
         ],
-        "approval_rating": "fda_prescription",
+        "approval_ratings": ["fda_prescription"],
         "trade_names": ["AFINITOR"]
     })
 
@@ -80,7 +79,7 @@ def dactinomycin() -> Drug:
             "spl:b92f5536-179c-6234-e053-2995a90a0f25",
             "unii:1CC1JFE158",
         ],
-        "approval_rating": "fda_prescription",
+        "approval_ratings": ["fda_prescription"],
         "trade_names": ["COSMEGEN"]
     })
 
@@ -99,7 +98,7 @@ def cisplatin() -> List[Drug]:
                 "spl:54b3415c-c095-4c82-b216-e0e6e6bb8d03",
                 "unii:Q20Q21Q62J",
             ],
-            "approval_rating": "fda_prescription",
+            "approval_ratings": ["fda_prescription"],
         }),
         Drug(**{
             "label": "CISPLATIN",
@@ -111,7 +110,7 @@ def cisplatin() -> List[Drug]:
                 "spl:2c569ef0-588f-4828-8b2d-03a2120c9b4c",
                 "unii:Q20Q21Q62J",
             ],
-            "approval_rating": "fda_prescription",
+            "approval_ratings": ["fda_prescription"],
         }),
         Drug(**{
             "label": "CISPLATIN",
@@ -122,7 +121,7 @@ def cisplatin() -> List[Drug]:
                 "spl:9b008181-ab66-db2f-e053-2995a90aad57",
                 "unii:Q20Q21Q62J",
             ],
-            "approval_rating": "fda_prescription",
+            "approval_ratings": ["fda_prescription"],
         }),
         Drug(**{
             "label": "CISPLATIN",
@@ -135,7 +134,7 @@ def cisplatin() -> List[Drug]:
                 "spl:c43de769-d6d8-3bb9-e053-2995a90a5aa2",
                 "unii:Q20Q21Q62J",
             ],
-            "approval_rating": "fda_prescription",
+            "approval_ratings": ["fda_prescription"],
         }),
         Drug(**{
             "label": "CISPLATIN",
@@ -149,7 +148,7 @@ def cisplatin() -> List[Drug]:
                 "spl:5a24d5bd-c44a-43f7-a04c-76caf3475012",
                 "unii:Q20Q21Q62J",
             ],
-            "approval_rating": "fda_prescription",
+            "approval_ratings": ["fda_prescription"],
         }),
         Drug(**{
             "label": "CISPLATIN",
@@ -172,7 +171,7 @@ def cisplatin() -> List[Drug]:
 @pytest.fixture(scope="module")
 def fenortho() -> List[Drug]:
     """Provide fenortho fixture. Tests for correct handling of conflicting
-    approval_rating values.
+    approval_ratings values.
     """
     return [
         Drug(**{
@@ -186,7 +185,7 @@ def fenortho() -> List[Drug]:
                 "spl:c1bfb82a-8192-23f3-e053-2995a90ae9cf",
                 "unii:0X2CW1QABJ",
             ],
-            "approval_rating": "fda_prescription",
+            "approval_ratings": ["fda_prescription"],
             "trade_names": ["NALFON"]
         }),
         Drug(**{
@@ -194,22 +193,25 @@ def fenortho() -> List[Drug]:
             "concept_id": "drugsatfda.nda:017604",
             "xrefs": [
                 "rxcui:197694",
+                "rxcui:197695",
                 "rxcui:260323",
                 "rxcui:858116",
                 "rxcui:858118",
             ],
             "associated_with": [
+                "ndc:0276-0501",
+                "ndc:0276-0502",
+                "ndc:0276-0503",
                 "ndc:15014-400",
                 "ndc:42195-100",
                 "ndc:42195-308",
                 "ndc:42195-600",
                 "ndc:69336-113",
-                "ndc:69336-124",
-                "spl:81a0da5b-6078-413e-b6d0-d31c1073b3f7",
                 "spl:bedf1661-b811-3d85-e053-2995a90acd59",
                 "spl:c1721025-8af3-5451-e053-2a95a90a7dc0",
                 "spl:c1829550-d270-e13d-e053-2995a90a4aa5",
                 "spl:c187dfec-eec5-4227-e053-2995a90ab55c",
+                "spl:d33ad32a-f205-5df2-e053-2995a90ab978",
                 "unii:0X2CW1QABJ",
             ],
             "trade_names": ["NALFON", "FENORTHO"]
@@ -223,50 +225,50 @@ def test_everolimus(drugsatfda, everolimus):
 
     # test concept ID
     response = drugsatfda.search(concept_id)
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], everolimus)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], everolimus)
 
     response = drugsatfda.search("drugsatfda.anda:022334")
-    assert response["match_type"] == MatchType.NO_MATCH
+    assert response.match_type == MatchType.NO_MATCH
 
     # test label
     response = drugsatfda.search("everolimus")
-    assert response["match_type"] == MatchType.LABEL
-    records = [r for r in response["records"] if r["concept_id"] == concept_id]
+    assert response.match_type == MatchType.LABEL
+    records = [r for r in response.records if r.concept_id == concept_id]
     compare_records(records[0], everolimus)
 
     # test trade name
     response = drugsatfda.search("afinitor")
-    assert response["match_type"] == MatchType.TRADE_NAME
-    records = [r for r in response["records"] if r["concept_id"] == concept_id]
+    assert response.match_type == MatchType.TRADE_NAME
+    records = [r for r in response.records if r.concept_id == concept_id]
     compare_records(records[0], everolimus)
 
     # test xref
     response = drugsatfda.search("rxcui:998191")
-    assert response["match_type"] == MatchType.XREF
-    records = [r for r in response["records"] if r["concept_id"] == concept_id]
+    assert response.match_type == MatchType.XREF
+    records = [r for r in response.records if r.concept_id == concept_id]
     compare_records(records[0], everolimus)
 
     response = drugsatfda.search("rxcui:845507")
-    assert response["match_type"] == MatchType.XREF
-    records = [r for r in response["records"] if r["concept_id"] == concept_id]
+    assert response.match_type == MatchType.XREF
+    records = [r for r in response.records if r.concept_id == concept_id]
     compare_records(records[0], everolimus)
 
     response = drugsatfda.search("rxcui:998189")
-    assert response["match_type"] == MatchType.XREF
-    records = [r for r in response["records"] if r["concept_id"] == concept_id]
+    assert response.match_type == MatchType.XREF
+    records = [r for r in response.records if r.concept_id == concept_id]
     compare_records(records[0], everolimus)
 
     response = drugsatfda.search("rxcui:1308432")
-    assert response["match_type"] == MatchType.XREF
-    records = [r for r in response["records"] if r["concept_id"] == concept_id]
+    assert response.match_type == MatchType.XREF
+    records = [r for r in response.records if r.concept_id == concept_id]
     compare_records(records[0], everolimus)
 
     # test assoc_with
     response = drugsatfda.search("unii:9HW64Q8G6G")
-    assert response["match_type"] == MatchType.ASSOCIATED_WITH
-    records = [r for r in response["records"] if r["concept_id"] == concept_id]
+    assert response.match_type == MatchType.ASSOCIATED_WITH
+    records = [r for r in response.records if r.concept_id == concept_id]
     compare_records(records[0], everolimus)
 
 
@@ -276,37 +278,37 @@ def test_dactinomycin(drugsatfda, dactinomycin):
 
     # test concept ID
     response = drugsatfda.search(concept_id)
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], dactinomycin)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], dactinomycin)
 
     # test label
     response = drugsatfda.search("DACTINOMYCIN")
-    assert response["match_type"] == MatchType.LABEL
-    records = [r for r in response["records"] if r["concept_id"] == concept_id]
+    assert response.match_type == MatchType.LABEL
+    records = [r for r in response.records if r.concept_id == concept_id]
     compare_records(records[0], dactinomycin)
 
     # test trade name
     response = drugsatfda.search("cosmegen")
-    assert response["match_type"] == MatchType.TRADE_NAME
-    records = [r for r in response["records"] if r["concept_id"] == concept_id]
+    assert response.match_type == MatchType.TRADE_NAME
+    records = [r for r in response.records if r.concept_id == concept_id]
     compare_records(records[0], dactinomycin)
 
     # test xref
     response = drugsatfda.search("rxcui:105569")
-    assert response["match_type"] == MatchType.XREF
-    records = [r for r in response["records"] if r["concept_id"] == concept_id]
+    assert response.match_type == MatchType.XREF
+    records = [r for r in response.records if r.concept_id == concept_id]
     compare_records(records[0], dactinomycin)
 
     response = drugsatfda.search("rxcui:239179")
-    assert response["match_type"] == MatchType.XREF
-    records = [r for r in response["records"] if r["concept_id"] == concept_id]
+    assert response.match_type == MatchType.XREF
+    records = [r for r in response.records if r.concept_id == concept_id]
     compare_records(records[0], dactinomycin)
 
     # test assoc_with
     response = drugsatfda.search("unii:1cc1jfe158")
-    assert response["match_type"] == MatchType.XREF
-    records = [r for r in response["records"] if r["concept_id"] == concept_id]
+    assert response.match_type == MatchType.XREF
+    records = [r for r in response.records if r.concept_id == concept_id]
     compare_records(records[0], dactinomycin)
 
 
@@ -315,94 +317,94 @@ def test_cisplatin(drugsatfda, cisplatin):
     # test concept IDs
     concept_id = "drugsatfda.anda:074656"
     response = drugsatfda.search(concept_id)
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0],
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0],
                     [c for c in cisplatin if c.concept_id == concept_id][0])
 
     concept_id = "drugsatfda.anda:075036"
     response = drugsatfda.search(concept_id)
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0],
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0],
                     [c for c in cisplatin
                      if c.concept_id.lower() == concept_id.lower()][0])
 
     concept_id = "drugsatfda.anda:074735"
     response = drugsatfda.search(concept_id)
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0],
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0],
                     [c for c in cisplatin if c.concept_id == concept_id][0])
 
     concept_id = "drugsatfda.anda:206774"
     response = drugsatfda.search(concept_id)
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0],
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0],
                     [c for c in cisplatin if c.concept_id == concept_id][0])
 
     concept_id = "drugsatfda.anda:207323"
     response = drugsatfda.search(concept_id)
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0],
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0],
                     [c for c in cisplatin if c.concept_id == concept_id][0])
 
     # test label
     response = drugsatfda.search("cisplatin")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 6
-    for r in response["records"]:
-        fixture = [c for c in cisplatin if r["concept_id"] == c.concept_id][0]
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 6
+    for r in response.records:
+        fixture = [c for c in cisplatin if r.concept_id == c.concept_id][0]
         compare_records(r, fixture)
 
     # test xref
     response = drugsatfda.search("rxcui:309311")
-    assert response["match_type"] == MatchType.XREF
-    assert len(response["records"]) == 6
-    for r in response["records"]:
-        fixture = [c for c in cisplatin if r["concept_id"] == c.concept_id][0]
+    assert response.match_type == MatchType.XREF
+    assert len(response.records) == 6
+    for r in response.records:
+        fixture = [c for c in cisplatin if r.concept_id == c.concept_id][0]
         compare_records(r, fixture)
 
     # test assoc_with
     response = drugsatfda.search("unii:q20q21q62j")
-    assert response["match_type"] == MatchType.ASSOCIATED_WITH
-    assert len(response["records"]) == 6
-    for r in response["records"]:
-        fixture = [c for c in cisplatin if r["concept_id"] == c.concept_id][0]
+    assert response.match_type == MatchType.ASSOCIATED_WITH
+    assert len(response.records) == 6
+    for r in response.records:
+        fixture = [c for c in cisplatin if r.concept_id == c.concept_id][0]
         compare_records(r, fixture)
 
 
 def test_fenortho(fenortho, drugsatfda):
     """Test fenortho."""
     response = drugsatfda.search("drugsatfda.anda:072267")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], fenortho[0])
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], fenortho[0])
 
     response = drugsatfda.search("drugsatfda.nda:017604")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], fenortho[1])
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], fenortho[1])
 
     response = drugsatfda.search("fenoprofen calcium")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 2
-    for r in response["records"]:
-        fixture = [f for f in fenortho if r["concept_id"] == f.concept_id][0]
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 2
+    for r in response.records:
+        fixture = [f for f in fenortho if r.concept_id == f.concept_id][0]
         compare_records(r, fixture)
 
     response = drugsatfda.search("rxcui:310291")
-    assert response["match_type"] == MatchType.XREF
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], fenortho[0])
+    assert response.match_type == MatchType.XREF
+    assert len(response.records) == 1
+    compare_records(response.records[0], fenortho[0])
 
     response = drugsatfda.search("unii:0X2CW1QABJ")
-    assert response["match_type"] == MatchType.ASSOCIATED_WITH
-    assert len(response["records"]) == 2
-    for r in response["records"]:
-        fixture = [f for f in fenortho if r["concept_id"] == f.concept_id][0]
+    assert response.match_type == MatchType.ASSOCIATED_WITH
+    assert len(response.records) == 2
+    for r in response.records:
+        fixture = [f for f in fenortho if r.concept_id == f.concept_id][0]
         compare_records(r, fixture)
 
 
@@ -412,18 +414,18 @@ def test_other_parameters(drugsatfda):
     """
     # test dropping BLA records
     response = drugsatfda.search("drugsatfda:BLA020725")
-    assert response["match_type"] == MatchType.NO_MATCH
+    assert response.match_type == MatchType.NO_MATCH
 
 
 def test_meta(drugsatfda):
     """Test correctness of source metadata."""
     response = drugsatfda.search("incoherent-string-of-text")
-    assert response["source_meta_"]["data_license"] == "CC0"
-    assert response["source_meta_"]["data_license_url"] == "https://creativecommons.org/publicdomain/zero/1.0/legalcode"  # noqa: E501
-    assert isodate.parse_date(response["source_meta_"]["version"])
-    assert response["source_meta_"]["data_url"] == "https://open.fda.gov/apis/drug/drugsfda/download/"  # noqa: E501
-    assert response["source_meta_"]["rdp_url"] is None
-    assert response["source_meta_"]["data_license_attributes"] == {
+    assert response.source_meta_.data_license == "CC0"
+    assert response.source_meta_.data_license_url == "https://creativecommons.org/publicdomain/zero/1.0/legalcode"  # noqa: E501
+    assert isodate.parse_date(response.source_meta_.version)
+    assert response.source_meta_.data_url == "https://open.fda.gov/apis/drug/drugsfda/download/"  # noqa: E501
+    assert response.source_meta_.rdp_url is None
+    assert response.source_meta_.data_license_attributes == {
         "non_commercial": False,
         "share_alike": False,
         "attribution": False,
diff --git a/tests/unit/test_guidetopharmacology.py b/tests/unit/test_guidetopharmacology.py
index bb72c7d4..8dff1113 100644
--- a/tests/unit/test_guidetopharmacology.py
+++ b/tests/unit/test_guidetopharmacology.py
@@ -17,9 +17,9 @@ def __init__(self):
             self.query_handler = QueryHandler()
 
         def search(self, query_str):
-            resp = self.query_handler.search_sources(
+            resp = self.query_handler.search(
                 query_str, keyed=True, incl="guidetopharmacology")
-            return resp["source_matches"]["GuideToPHARMACOLOGY"]
+            return resp.source_matches["GuideToPHARMACOLOGY"]
 
         def fetch_meta(self):
             return self.query_handler._fetch_meta("GuideToPHARMACOLOGY")
@@ -32,7 +32,7 @@ def cisplatin():
     params = {
         "concept_id": "iuphar.ligand:5343",
         "label": "cisplatin",
-        "approval_rating": "gtopdb_approved",
+        "approval_ratings": ["gtopdb_approved"],
         "xrefs": [
             "chembl:CHEMBL11359",
             "chemidplus:15663-27-1",
@@ -80,7 +80,7 @@ def phenobarbital():
     params = {
         "concept_id": "iuphar.ligand:2804",
         "label": "phenobarbital",
-        "approval_rating": "gtopdb_approved",
+        "approval_ratings": ["gtopdb_approved"],
         "xrefs": [
             "chembl:CHEMBL40",
             "chemidplus:50-06-6",
@@ -112,7 +112,7 @@ def cisapride():
     params = {
         "concept_id": "iuphar.ligand:240",
         "label": "cisapride",
-        "approval_rating": "gtopdb_withdrawn",
+        "approval_ratings": ["gtopdb_withdrawn"],
         "xrefs": [
             "chembl:CHEMBL1729",
             "chemidplus:81098-60-4",
@@ -235,16 +235,16 @@ def test_associated_with_match(guidetopharmacology, cisplatin,
 def test_no_match(guidetopharmacology):
     """Test that no match queries work correctly."""
     resp = guidetopharmacology.search("178102005")
-    assert resp["match_type"] == MatchType.NO_MATCH
-    assert len(resp["records"]) == 0
+    assert resp.match_type == MatchType.NO_MATCH
+    assert len(resp.records) == 0
 
     resp = guidetopharmacology.search("guidetopharmacology:5343")
-    assert resp["match_type"] == MatchType.NO_MATCH
-    assert len(resp["records"]) == 0
+    assert resp.match_type == MatchType.NO_MATCH
+    assert len(resp.records) == 0
 
     resp = guidetopharmacology.search("")
-    assert resp["match_type"] == MatchType.NO_MATCH
-    assert len(resp["records"]) == 0
+    assert resp.match_type == MatchType.NO_MATCH
+    assert len(resp.records) == 0
 
 
 def test_meta_info(guidetopharmacology):
diff --git a/tests/unit/test_hemonc.py b/tests/unit/test_hemonc.py
index 8afda779..3067f1c0 100644
--- a/tests/unit/test_hemonc.py
+++ b/tests/unit/test_hemonc.py
@@ -18,9 +18,8 @@ def __init__(self):
             self.query_handler = QueryHandler()
 
         def search(self, query_str):
-            resp = self.query_handler.search_sources(query_str, keyed=True,
-                                                     incl="hemonc")
-            return resp["source_matches"]["HemOnc"]
+            resp = self.query_handler.search(query_str, keyed=True, incl="hemonc")
+            return resp.source_matches["HemOnc"]
 
         def fetch_meta(self):
             return self.query_handler._fetch_meta("HemOnc")
@@ -46,23 +45,32 @@ def cisplatin():
         "trade_names": [],
         "xrefs": ["rxcui:2555"],
         "associated_with": [],
-        "approval_rating": "hemonc_approved",
-        "approval_year": [1978],
+        "approval_ratings": ["hemonc_approved"],
+        "approval_year": ["1978"],
         "has_indication": [
             {
-                "disease_id": "hemonc:671",
-                "disease_label": "Testicular cancer",
-                "normalized_disease_id": "ncit:C7251"
+                "disease_id": "hemonc:569",
+                "disease_label": "Bladder cancer",
+                "normalized_disease_id": "ncit:C9334",
+                "supplemental_info": {
+                    "regulatory_body": "FDA"
+                }
             },
             {
                 "disease_id": "hemonc:645",
                 "disease_label": "Ovarian cancer",
-                "normalized_disease_id": "ncit:C7431"
+                "normalized_disease_id": "ncit:C7431",
+                "supplemental_info": {
+                    "regulatory_body": "FDA"
+                }
             },
             {
-                "disease_id": "hemonc:569",
-                "disease_label": "Bladder cancer",
-                "normalized_disease_id": "ncit:C9334"
+                "disease_id": "hemonc:671",
+                "disease_label": "Testicular cancer",
+                "normalized_disease_id": "ncit:C7251",
+                "supplemental_info": {
+                    "regulatory_body": "FDA"
+                }
             }
         ]
     })
@@ -100,18 +108,24 @@ def bendamustine():
             "Treanda",
             "Xyotin"
         ],
-        "approval_rating": "hemonc_approved",
+        "approval_ratings": ["hemonc_approved"],
         "approval_year": ["2008", "2015"],
         "has_indication": [
             {
                 "disease_id": "hemonc:581",
                 "disease_label": "Chronic lymphocytic leukemia",
-                "normalized_disease_id": "ncit:C3163"
+                "normalized_disease_id": "ncit:C3163",
+                "supplemental_info": {
+                    "regulatory_body": "FDA"
+                }
             },
             {
                 "disease_id": "hemonc:46094",
                 "disease_label": "Indolent lymphoma",
-                "normalized_disease_id": "ncit:C8504"
+                "normalized_disease_id": "ncit:C8504",
+                "supplemental_info": {
+                    "regulatory_body": "FDA"
+                }
             }
         ]
     })
@@ -131,15 +145,18 @@ def degarelix():
         "xrefs": ["rxcui:475230"],
         "associated_with": [],
         "trade_names": ["Firmagon"],
-        "approval_rating": "hemonc_approved",
+        "approval_ratings": ["hemonc_approved"],
         "approval_year": ["2008"],
         "has_indication": [
             {
                 "disease_id": "hemonc:658",
                 "disease_label": "Prostate cancer",
-                "normalized_disease_id": "ncit:C7378"
+                "normalized_disease_id": "ncit:C7378",
+                "supplemental_info": {
+                    "regulatory_body": "FDA"
+                }
             }
-        ],
+        ]
     })
 
 
@@ -201,7 +218,7 @@ def test_trade_name(hemonc, bendamustine, degarelix):
 
     # no trade names for records with > 20
     response = hemonc.search("platinol")
-    assert response["match_type"] == MatchType.NO_MATCH
+    assert response.match_type == MatchType.NO_MATCH
 
 
 def test_xref_match(hemonc, cisplatin, bendamustine, degarelix):
diff --git a/tests/unit/test_merge.py b/tests/unit/test_merge.py
index d1e75653..dfb41e8f 100644
--- a/tests/unit/test_merge.py
+++ b/tests/unit/test_merge.py
@@ -1,6 +1,8 @@
 """Test merged record generation."""
 from typing import Dict
 import random
+import json
+from pathlib import Path
 
 import pytest
 
@@ -57,13 +59,11 @@ def compare_merged_records(actual: Dict, fixture: Dict):
         assert set(actual["xrefs"]) == set(fixture["xrefs"])
     assert ("associated_with" in actual) == ("associated_with" in fixture)
     if "associated_with" in actual or "associated_with" in fixture:
-        assert set(actual["associated_with"]) == \
-            set(fixture["associated_with"])
+        assert set(actual["associated_with"]) == set(fixture["associated_with"])
 
     assert ("approval_ratings" in actual) == ("approval_ratings" in fixture)
     if "approval_ratings" in actual or "approval_ratings" in fixture:
-        assert set(actual["approval_ratings"]) == \
-            set(fixture["approval_ratings"])
+        assert set(actual["approval_ratings"]) == set(fixture["approval_ratings"])
     assert ("approval_year" in actual) == ("approval_year" in fixture)
     if "approval_year" in actual or "approval_year" in fixture:
         assert set(actual["approval_year"]) == set(fixture["approval_year"])
@@ -79,237 +79,29 @@ def compare_merged_records(actual: Dict, fixture: Dict):
 
 
 @pytest.fixture(scope="module")
-def phenobarbital_merged():
+def fixture_data(test_data: Path):
+    """Fetch fixture data"""
+    return json.load(open(test_data / "test_merge_data.json", "r"))
+
+
+@pytest.fixture(scope="module")
+def phenobarbital_merged(fixture_data):
     """Create phenobarbital fixture."""
-    return {
-        "label_and_type": "rxcui:8134##merger",
-        "concept_id": "rxcui:8134",
-        "xrefs": [
-            "ncit:C739",
-            "drugbank:DB01174",
-            "chemidplus:50-06-6",
-            "wikidata:Q407241",
-            "chembl:CHEMBL40",
-            "iuphar.ligand:2804"
-        ],
-        "aliases": [
-            "5-Ethyl-5-phenyl-2,4,6(1H,3H,5H)-pyrimidinetrione",
-            "5-Ethyl-5-phenyl-pyrimidine-2,4,6-trione",
-            "5-Ethyl-5-phenylbarbituric acid",
-            "5-Phenyl-5-ethylbarbituric acid",
-            "5-ethyl-5-phenyl-1,3-diazinane-2,4,6-trione",
-            "5-ethyl-5-phenyl-2,4,6(1H,3H,5H)-pyrimidinetrione",
-            "5-ethyl-5-phenylpyrimidine-2,4,6(1H,3H,5H)-trione",
-            "APRD00184",
-            "Acid, Phenylethylbarbituric",
-            "Eskabarb",
-            "Fenobarbital",
-            "Luminal",
-            "Luminal®",
-            "NSC-128143",
-            "NSC-128143-",
-            "NSC-9848",
-            "Noptil",
-            "PHENO",
-            "PHENOBARBITAL",
-            "PHENYLETHYLMALONYLUREA",
-            "PHENobarbital",
-            "Phenemal",
-            "Phenobarbital",
-            "Phenobarbital civ",
-            "Phenobarbitol",
-            "Phenobarbitone",
-            "Phenobarbituric Acid",
-            "Phenylaethylbarbitursaeure",
-            "Phenylbarbital",
-            "Phenylethylbarbiturate",
-            "Phenylethylbarbituric Acid",
-            "Phenylethylbarbitursaeure",
-            "Phenylethylbarbitursäure",
-            "Phenylethylmalonylurea",
-            "Phenyläthylbarbitursäure",
-            "Solfoton",
-            "Talpheno",
-            "fenobarbital",
-            "phenobarb",
-            "phenobarbital",
-            "phenobarbital sodium",
-            "phenobarbitone",
-            "phenylethylbarbiturate"
-        ],
-        "associated_with": [
-            "pubchem.compound:4763",
-            "usp:m63400",
-            "gsddb:2179",
-            "snomedct:51073002",
-            "vandf:4017422",
-            "mmsl:2390",
-            "msh:D010634",
-            "snomedct:373505007",
-            "mmsl:5272",
-            "unii:YQE403BP4D",
-            "fdbmk:001406",
-            "mmsl:d00340",
-            "atc:N03AA02",
-            "umls:C0031412",
-            "CHEBI:8069",
-            "inchikey:DDBREPKUVSBGFI-UHFFFAOYSA-N",
-            "drugcentral:2134",
-            "pubchem.substance:135650817"
-        ],
-        "label": "Phenobarbital",
-        "approval_ratings": [
-            "rxnorm_prescribable",
-            "chembl_phase_4",
-            "gtopdb_approved"
-        ]
-    }
+    return fixture_data["phenobarbital"]
 
 
 @pytest.fixture(scope="module")
-def cisplatin_merged():
+def cisplatin_merged(fixture_data):
     """Create cisplatin fixture."""
-    return {
-        "label_and_type": "rxcui:2555##merger",
-        "concept_id": "rxcui:2555",
-        "xrefs": [
-            "ncit:C376",
-            "drugbank:DB00515",
-            "drugbank:DB12117",
-            "hemonc:105",
-            "chemidplus:15663-27-1",
-            "wikidata:Q412415",
-            "chembl:CHEMBL11359",
-            "drugsatfda.anda:074656",
-            "drugsatfda.anda:074735",
-            "drugsatfda.anda:206774",
-            "drugsatfda.anda:207323",
-            "drugsatfda.anda:075036",
-            "drugsatfda.nda:018057"
-        ],
-        "trade_names": [
-            "Cisplatin",
-            "Platinol",
-            "PLATINOL",
-            "PLATINOL-AQ"
-        ],
-        "aliases": [
-            "1,2-Diaminocyclohexaneplatinum II citrate",
-            "APRD00359",
-            "CDDP",
-            "CISplatin",
-            "Cisplatin",
-            "Cisplatinum",
-            "Cis-platinum ii",
-            "Cis-DDP",
-            "CIS-DDP",
-            "DACP",
-            "DDP",
-            "Diamminodichloride, Platinum",
-            "Dichlorodiammineplatinum",
-            "INT-230-6 COMPONENT CISPLATIN",
-            "INT230-6 COMPONENT CISPLATIN",
-            "Platinum Diamminodichloride",
-            "cis Diamminedichloroplatinum",
-            "cis Platinum",
-            "cis-Diaminedichloroplatinum",
-            "cis-Diamminedichloroplatinum",
-            "cis-diamminedichloroplatinum(II)",
-            "cis-Diamminedichloroplatinum(II)",
-            "cis-Dichlorodiammineplatinum(II)",
-            "cisplatinum",
-            "cis-Platinum",
-            "cis-platinum",
-            "cisplatino",
-            "cis-diamminedichloroplatinum(II)",
-            "cis-diamminedichloroplatinum III",
-            "NSC 119875",
-            "NSC-119875",
-            "Platinol-AQ",
-            "Platinol-aq",
-            "Platinol",
-            "Liplacis"
-        ],
-        "label": "cisplatin",
-        "associated_with": [
-            "mmsl:31747",
-            "mmsl:4456",
-            "mmsl:d00195",
-            "usp:m17910",
-            "inchikey:LXZZYRPGZAFOLE-UHFFFAOYSA-L",
-            "inchikey:MOTIYCLHZZLHHQ-UHFFFAOYSA-N",
-            "mesh:D002945",
-            "atc:L01XA01",
-            "vandf:4018139",
-            "pubchem.compound:5702198",
-            "umls:C0008838",
-            "unii:H8MTN7XVC2",
-            "unii:Q20Q21Q62J",
-            "ndc:0143-9504",
-            "ndc:0143-9505",
-            "ndc:0703-5747",
-            "ndc:0703-5748",
-            "ndc:16729-288",
-            "ndc:44567-509",
-            "ndc:44567-510",
-            "ndc:44567-511",
-            "ndc:44567-530",
-            "ndc:63323-103",
-            "ndc:68001-283",
-            "ndc:68083-162",
-            "ndc:68083-163",
-            "ndc:70860-206",
-            "spl:01c7a680-ee0d-42da-85e8-8d56c6fe7006",
-            "spl:5a24d5bd-c44a-43f7-a04c-76caf3475012",
-            "spl:a66eda32-1164-439a-ac8e-73138365ec06",
-            "spl:dd45d777-d4c1-40ee-b4f0-c9e001a15a8c",
-            "spl:2c569ef0-588f-4828-8b2d-03a2120c9b4c",
-            "spl:54b3415c-c095-4c82-b216-e0e6e6bb8d03",
-            "spl:9b008181-ab66-db2f-e053-2995a90aad57",
-            "spl:c3ddc4a5-9f1b-a8ee-e053-2a95a90a2265",
-            "spl:c43de769-d6d8-3bb9-e053-2995a90a5aa2"
-        ],
-        "approval_ratings": [
-            "rxnorm_prescribable",
-            "hemonc_approved",
-            "fda_prescription",
-            "chembl_phase_4"
-        ],
-        "approval_year": ["1978"],
-        "has_indication": [
-            ["hemonc:671", "Testicular cancer", "ncit:C7251"],
-            ["hemonc:645", "Ovarian cancer", "ncit:C7431"],
-            ["hemonc:569", "Bladder cancer", "ncit:C9334"]
-        ],
-    }
+    return fixture_data["cisplatin"]
 
 
 @pytest.fixture(scope="module")
-def spiramycin_merged():
+def spiramycin_merged(fixture_data):
     """Create fixture for spiramycin. The RxNorm entry should be inaccessible
     to this group.
     """
-    return {
-        "label_and_type": "ncit:c839##merger",
-        "concept_id": "ncit:C839",
-        "xrefs": [
-            "chemidplus:8025-81-8",
-        ],
-        "label": "Spiramycin",
-        "aliases": [
-            "SPIRAMYCIN",
-            "Antibiotic 799",
-            "Rovamycin",
-            "Provamycin",
-            "Rovamycine",
-            "RP 5337",
-            "(4R,5S,6R,7R,9R,10R,11E,13E,16R)-10-{[(2R,5S,6R)-5-(dimethylamino)-6-methyltetrahydro-2H-pyran-2-yl]oxy}-9,16-dimethyl-5-methoxy-2-oxo-7-(2-oxoethyl)oxacyclohexadeca-11,13-dien-6-yl 3,6-dideoxy-4-O-(2,6-dideoxy-3-C-methyl-alpha-L-ribo-hexopyranosyl)-3-(dimethylamino)-alpha-D-glucopyranoside"  # noqa: E501
-        ],
-        "associated_with": [
-            "umls:C0037962",
-            "unii:71ODY0V87H"
-        ],
-    }
+    return fixture_data["spiramycin"]
 
 
 @pytest.fixture(scope="module")
@@ -379,13 +171,40 @@ def record_id_groups():
             "chembl:CHEMBL40",
             "iuphar.ligand:2804"
         },
+        "rxcui:9991": {  # Spiramycin
+            "rxcui:9991",
+            "ncit:C839",
+            "chemidplus:8025-81-8",
+            "drugbank:DB06145",
+            "wikidata:Q422265"
+        },
         "ncit:C839": {  # Spiramycin
+            "rxcui:9991",
             "ncit:C839",
             "chemidplus:8025-81-8",
+            "drugbank:DB06145",
+            "wikidata:Q422265"
         },
         "chemidplus:8025-81-8": {  # Spiramycin
+            "rxcui:9991",
+            "ncit:C839",
+            "chemidplus:8025-81-8",
+            "drugbank:DB06145",
+            "wikidata:Q422265"
+        },
+        "drugbank:DB06145": {  # Spiramycin
+            "rxcui:9991",
+            "ncit:C839",
+            "chemidplus:8025-81-8",
+            "drugbank:DB06145",
+            "wikidata:Q422265"
+        },
+        "wikidata:Q422265": {  # Spiramycin
+            "rxcui:9991",
             "ncit:C839",
             "chemidplus:8025-81-8",
+            "drugbank:DB06145",
+            "wikidata:Q422265"
         },
         "rxcui:2555": {  # Cisplatin
             "rxcui:2555",
@@ -401,7 +220,8 @@ def record_id_groups():
             "drugsatfda.anda:206774",
             "drugsatfda.anda:207323",
             "drugsatfda.anda:075036",
-            "drugsatfda.nda:018057"
+            "drugsatfda.nda:018057",
+            "iuphar.ligand:5343"
         },
         "ncit:C376": {  # Cisplatin
             "rxcui:2555",
@@ -417,6 +237,7 @@ def record_id_groups():
             "drugsatfda.anda:206774",
             "drugsatfda.anda:207323",
             "drugsatfda.anda:075036",
+            "iuphar.ligand:5343",
             "drugsatfda.nda:018057"
         },
         "chemidplus:15663-27-1": {  # Cisplatin
@@ -433,6 +254,7 @@ def record_id_groups():
             "drugsatfda.anda:206774",
             "drugsatfda.anda:207323",
             "drugsatfda.anda:075036",
+            "iuphar.ligand:5343",
             "drugsatfda.nda:018057"
         },
         "wikidata:Q412415": {  # Cisplatin
@@ -449,6 +271,7 @@ def record_id_groups():
             "drugsatfda.anda:206774",
             "drugsatfda.anda:207323",
             "drugsatfda.anda:075036",
+            "iuphar.ligand:5343",
             "drugsatfda.nda:018057"
         },
         "drugbank:DB00515": {  # Cisplatin
@@ -465,6 +288,7 @@ def record_id_groups():
             "drugsatfda.anda:206774",
             "drugsatfda.anda:207323",
             "drugsatfda.anda:075036",
+            "iuphar.ligand:5343",
             "drugsatfda.nda:018057"
         },
         "hemonc:105": {  # Cisplatin
@@ -481,6 +305,7 @@ def record_id_groups():
             "drugsatfda.anda:206774",
             "drugsatfda.anda:207323",
             "drugsatfda.anda:075036",
+            "iuphar.ligand:5343",
             "drugsatfda.nda:018057"
         },
         "chembl:CHEMBL11359": {  # Cisplatin
@@ -497,6 +322,7 @@ def record_id_groups():
             "drugsatfda.anda:206774",
             "drugsatfda.anda:207323",
             "drugsatfda.anda:075036",
+            "iuphar.ligand:5343",
             "drugsatfda.nda:018057"
         },
         "drugsatfda.anda:074656": {  # Cisplatin
@@ -513,6 +339,7 @@ def record_id_groups():
             "drugsatfda.anda:206774",
             "drugsatfda.anda:207323",
             "drugsatfda.anda:075036",
+            "iuphar.ligand:5343",
             "drugsatfda.nda:018057"
         },
         "drugsatfda.anda:074735": {  # Cisplatin
@@ -529,6 +356,7 @@ def record_id_groups():
             "drugsatfda.anda:206774",
             "drugsatfda.anda:207323",
             "drugsatfda.anda:075036",
+            "iuphar.ligand:5343",
             "drugsatfda.nda:018057"
         },
         "drugsatfda.anda:206774": {  # Cisplatin
@@ -545,6 +373,7 @@ def record_id_groups():
             "drugsatfda.anda:206774",
             "drugsatfda.anda:207323",
             "drugsatfda.anda:075036",
+            "iuphar.ligand:5343",
             "drugsatfda.nda:018057"
         },
         "drugsatfda.anda:207323": {  # Cisplatin
@@ -561,6 +390,7 @@ def record_id_groups():
             "drugsatfda.anda:206774",
             "drugsatfda.anda:207323",
             "drugsatfda.anda:075036",
+            "iuphar.ligand:5343",
             "drugsatfda.nda:018057"
         },
         "drugsatfda.anda:075036": {  # Cisplatin
@@ -577,6 +407,7 @@ def record_id_groups():
             "drugsatfda.anda:206774",
             "drugsatfda.anda:207323",
             "drugsatfda.anda:075036",
+            "iuphar.ligand:5343",
             "drugsatfda.nda:018057"
         },
         "drugbank:DB12117": {  # Cisplatin
@@ -593,6 +424,7 @@ def record_id_groups():
             "drugsatfda.anda:206774",
             "drugsatfda.anda:207323",
             "drugsatfda.anda:075036",
+            "iuphar.ligand:5343",
             "drugsatfda.nda:018057"
         },
         "drugsatfda.nda:018057": {  # Cisplatin
@@ -609,6 +441,24 @@ def record_id_groups():
             "drugsatfda.anda:206774",
             "drugsatfda.anda:207323",
             "drugsatfda.anda:075036",
+            "iuphar.ligand:5343",
+            "drugsatfda.nda:018057"
+        },
+        "iuphar.ligand:5343": {  # Cisplatin
+            "rxcui:2555",
+            "ncit:C376",
+            "chemidplus:15663-27-1",
+            "wikidata:Q412415",
+            "drugbank:DB00515",
+            "drugbank:DB12117",
+            "hemonc:105",
+            "chembl:CHEMBL11359",
+            "drugsatfda.anda:074656",
+            "drugsatfda.anda:074735",
+            "drugsatfda.anda:206774",
+            "drugsatfda.anda:207323",
+            "drugsatfda.anda:075036",
+            "iuphar.ligand:5343",
             "drugsatfda.nda:018057"
         },
         # tests lookup of wikidata reference to rxnorm brand record, and
diff --git a/tests/unit/test_ncit.py b/tests/unit/test_ncit.py
index f19a7ee6..370c6a19 100644
--- a/tests/unit/test_ncit.py
+++ b/tests/unit/test_ncit.py
@@ -17,8 +17,8 @@ def __init__(self):
             self.query_handler = QueryHandler()
 
         def search(self, query_str):
-            resp = self.query_handler.search_sources(query_str, keyed=True, incl="ncit")
-            return resp["source_matches"]["NCIt"]
+            resp = self.query_handler.search(query_str, keyed=True, incl="ncit")
+            return resp.source_matches["NCIt"]
 
         def fetch_meta(self):
             return self.query_handler._fetch_meta("NCIt")
@@ -36,7 +36,7 @@ def voglibose():
                     "N-(1,3-Dihydroxy-2-Propyl)Valiolamine", "VOGLIBOSE"],
         "xrefs": ["chemidplus:83480-29-9"],
         "associated_with": ["unii:S77P977AG8", "umls:C0532578"],
-        "approval_rating": None,
+        "approval_ratings": None,
         "trade_names": []
     }
     return Drug(**params)
@@ -54,7 +54,7 @@ def apricoxib():
         ],
         "xrefs": ["chemidplus:197904-84-0"],
         "associated_with": ["unii:5X5HB3VZ3Z", "umls:C1737955"],
-        "approval_rating": None,
+        "approval_ratings": None,
         "trade_names": []
     }
     return Drug(**params)
@@ -70,7 +70,7 @@ def trastuzumab():
         "aliases": [],
         "xrefs": ["chemidplus:180288-69-1"],
         "associated_with": ["umls:C0728747", "unii:P188ANX8CK"],
-        "approval_rating": None,
+        "approval_ratings": None,
         "trade_names": []
     }
     return Drug(**params)
@@ -239,17 +239,17 @@ def test_assoc_with_match(ncit, voglibose, apricoxib, trastuzumab):
 def test_no_match(ncit):
     """Test that a term normalizes to NO match."""
     response = ncit.search("voglibo")
-    assert response["match_type"] == MatchType.NO_MATCH
-    assert len(response["records"]) == 0
+    assert response.match_type == MatchType.NO_MATCH
+    assert len(response.records) == 0
 
     # Test white space in between label
     response = ncit.search("Volgibo")
-    assert response["match_type"] == MatchType.NO_MATCH
+    assert response.match_type == MatchType.NO_MATCH
 
     # Test empty query
     response = ncit.search("")
-    assert response["match_type"] == MatchType.NO_MATCH
-    assert len(response["records"]) == 0
+    assert response.match_type == MatchType.NO_MATCH
+    assert len(response.records) == 0
 
 
 def test_meta_info(ncit):
diff --git a/tests/unit/test_query.py b/tests/unit/test_query.py
index 39788364..f9314618 100644
--- a/tests/unit/test_query.py
+++ b/tests/unit/test_query.py
@@ -1,11 +1,13 @@
 """Test the therapy querying method."""
 from datetime import datetime
 import os
+import json
+from pathlib import Path
 
 import pytest
 
 from therapy.query import QueryHandler, InvalidParameterException
-from therapy.schemas import MatchType
+from therapy.schemas import MatchType, SourceName, ValueObjectDescriptor
 
 
 @pytest.fixture(scope="module")
@@ -16,19 +18,15 @@ class QueryGetter:
         def __init__(self):
             self.query_handler = QueryHandler()
 
-        def search_sources(self, query_str, keyed=False, incl="", excl="",
-                           infer=True):
-            resp = self.query_handler.search_sources(query_str=query_str,
-                                                     keyed=keyed,
-                                                     incl=incl, excl=excl,
-                                                     infer=infer)
-            return resp
+        def search(self, query_str, keyed=False, incl="", excl="", infer=True):
+            return self.query_handler.search(query_str=query_str, keyed=keyed,
+                                             incl=incl, excl=excl, infer=infer)
 
     return QueryGetter()
 
 
 @pytest.fixture(scope="module")
-def merge_query_handler(mock_database):
+def normalize_query_handler(mock_database):
     """Provide Merge instance to test cases."""
     class QueryGetter:
         def __init__(self):
@@ -36,324 +34,42 @@ def __init__(self):
             if os.environ.get("TEST") is not None:
                 self.query_handler.db = mock_database()  # replace initial DB
 
-        def search_groups(self, query_str, infer=True):
-            return self.query_handler.search_groups(query_str, infer)
+        def normalize(self, query_str, infer=True):
+            return self.query_handler.normalize(query_str, infer)
 
     return QueryGetter()
 
 
 @pytest.fixture(scope="module")
-def phenobarbital():
+def fixture_data(test_data: Path):
+    """Fetch fixture data"""
+    return json.load(open(test_data / "test_query_data.json", "r"))
+
+
+@pytest.fixture(scope="module")
+def phenobarbital(fixture_data):
     """Create phenobarbital VOD fixture."""
-    return {
-        "id": "normalize.therapy:Phenobarbital",
-        "type": "TherapyDescriptor",
-        "therapy_id": "rxcui:8134",
-        "label": "phenobarbital",
-        "xrefs": [
-            "ncit:C739",
-            "drugbank:DB01174",
-            "chemidplus:50-06-6",
-            "wikidata:Q407241",
-            "iuphar.ligand:2804",
-            "chembl:CHEMBL40"
-        ],
-        "alternate_labels": [
-            "5-Ethyl-5-phenyl-2,4,6(1H,3H,5H)-pyrimidinetrione",
-            "5-Ethyl-5-phenyl-pyrimidine-2,4,6-trione",
-            "5-Ethyl-5-phenylbarbituric acid",
-            "5-Phenyl-5-ethylbarbituric acid",
-            "5-ethyl-5-phenyl-2,4,6(1H,3H,5H)-pyrimidinetrione",
-            "5-ethyl-5-phenylpyrimidine-2,4,6(1H,3H,5H)-trione",
-            "APRD00184",
-            "Acid, Phenylethylbarbituric",
-            "Fenobarbital",
-            "Luminal®",
-            "PHENO",
-            "PHENOBARBITAL",
-            "PHENYLETHYLMALONYLUREA",
-            "PHENobarbital",
-            "Phenemal",
-            "Phenobarbital",
-            "Phenobarbitol",
-            "Phenobarbitone",
-            "Phenobarbituric Acid",
-            "Phenylaethylbarbitursaeure",
-            "Phenylbarbital",
-            "Phenylethylbarbiturate",
-            "Phenylethylbarbituric Acid",
-            "Phenylethylbarbitursaeure",
-            "Phenylethylbarbitursäure",
-            "Phenylethylmalonylurea",
-            "Phenyläthylbarbitursäure",
-            "fenobarbital",
-            "phenobarbital",
-            "phenobarbital sodium",
-            "phenylethylbarbiturate",
-            "5-ethyl-5-phenyl-1,3-diazinane-2,4,6-trione",
-            "phenobarb",
-            "phenobarbitone",
-            "NSC-128143",
-            "NSC-128143-",
-            "NSC-9848",
-            "Phenobarbital civ",
-            "Solfoton",
-            "Luminal",
-            "Eskabarb",
-            "Noptil",
-            "Talpheno"
-        ],
-        "extensions": [
-            {
-                "type": "Extension",
-                "name": "associated_with",
-                "value": [
-                    "usp:m63400",
-                    "vandf:4017422",
-                    "mmsl:2390",
-                    "mesh:D010634",
-                    "mmsl:5272",
-                    "mmsl:d00340",
-                    "atc:N03AA02",
-                    "unii:YQE403BP4D",
-                    "umls:C0031412",
-                    "CHEBI:8069",
-                    "pubchem.substance:135650817",
-                    "pubchem.compound:4763",
-                    "inchikey:DDBREPKUVSBGFI-UHFFFAOYSA-N",
-                    "drugcentral:2134"
-                ]
-            },
-            {
-                "type": "Extension",
-                "name": "regulatory_approval",
-                "value": {
-                    "approval_ratings": [],
-                    "approval_year": [],
-                    "has_indication": []
-                }
-            }
-        ]
-    }
+    return fixture_data["phenobarbital"]
 
 
 @pytest.fixture(scope="module")
-def cisplatin():
+def cisplatin(fixture_data):
     """Create cisplatin fixture."""
-    return {
-        "id": "normalize.therapy:Cisplatin",
-        "type": "TherapyDescriptor",
-        "therapy_id": "rxcui:2555",
-        "label": "cisplatin",
-        "xrefs": [
-            "ncit:C376",
-            "hemonc:105",
-            "drugbank:DB00515",
-            "chemidplus:15663-27-1",
-            "wikidata:Q412415",
-            "iuphar.ligand:5343",
-            "drugbank:DB12117",
-            "chembl:CHEMBL11359",
-            "drugsatfda.anda:074656",
-            "drugsatfda.anda:074735",
-            "drugsatfda.anda:206774",
-            "drugsatfda.anda:207323",
-            "drugsatfda.anda:075036",
-            "drugsatfda.nda:018057",
-        ],
-        "alternate_labels": [
-            "1,2-Diaminocyclohexaneplatinum II citrate",
-            "APRD00359",
-            "CDDP",
-            "CISplatin",
-            "Cis-DDP",
-            "CIS-DDP",
-            "DDP",
-            "Diamminodichloride, Platinum",
-            "Dichlorodiammineplatinum",
-            "Platinum Diamminodichloride",
-            "cis Diamminedichloroplatinum",
-            "cis Platinum",
-            "cis-Diaminedichloroplatinum",
-            "cis-Diamminedichloroplatinum",
-            "cis-Diamminedichloroplatinum(II)",
-            "cis-Dichlorodiammineplatinum(II)",
-            "cis-Platinum",
-            "cis-diamminedichloroplatinum(II)",
-            "Platinol-AQ",
-            "Platinol",
-            "cisplatino",
-            "Cisplatin",
-            "Cis-platinum ii",
-            "Cisplatinum",
-            "INT-230-6 COMPONENT CISPLATIN",
-            "INT230-6 COMPONENT CISPLATIN",
-            "NSC-119875",
-            "Platinol-aq",
-            "DACP",
-            "NSC 119875",
-            "cis-diamminedichloroplatinum III",
-            "cis-platinum",
-            "cisplatinum",
-            "Liplacis"
-        ],
-        "extensions": [
-            {
-                "type": "Extension",
-                "name": "trade_names",
-                "value": [
-                    "Cisplatin",
-                    "Platinol",
-                    "PLATINOL",
-                    "PLATINOL-AQ"
-                ],
-            },
-            {
-                "type": "Extension",
-                "name": "associated_with",
-                "value": [
-                    "mmsl:31747",
-                    "mmsl:4456",
-                    "mmsl:d00195",
-                    "usp:m17910",
-                    "CHEBI:27899",
-                    "inchikey:LXZZYRPGZAFOLE-UHFFFAOYSA-L",
-                    "inchikey:MOTIYCLHZZLHHQ-UHFFFAOYSA-N",
-                    "mesh:D002945",
-                    "atc:L01XA01",
-                    "vandf:4018139",
-                    "pubchem.substance:178102005",
-                    "pubchem.compound:441203",
-                    "pubchem.compound:5702198",
-                    "umls:C0008838",
-                    "unii:H8MTN7XVC2",
-                    "unii:Q20Q21Q62J",
-                    "ndc:0143-9504",
-                    "ndc:0143-9505",
-                    "ndc:0703-5747",
-                    "ndc:0703-5748",
-                    "ndc:16729-288",
-                    "ndc:44567-509",
-                    "ndc:44567-510",
-                    "ndc:44567-511",
-                    "ndc:44567-530",
-                    "ndc:63323-103",
-                    "ndc:68001-283",
-                    "ndc:68083-162",
-                    "ndc:68083-163",
-                    "ndc:70860-206",
-                    "spl:01c7a680-ee0d-42da-85e8-8d56c6fe7006",
-                    "spl:5a24d5bd-c44a-43f7-a04c-76caf3475012",
-                    "spl:a66eda32-1164-439a-ac8e-73138365ec06",
-                    "spl:dd45d777-d4c1-40ee-b4f0-c9e001a15a8c",
-                    "spl:2c569ef0-588f-4828-8b2d-03a2120c9b4c",
-                    "spl:54b3415c-c095-4c82-b216-e0e6e6bb8d03",
-                    "spl:9b008181-ab66-db2f-e053-2995a90aad57",
-                    "spl:c3ddc4a5-9f1b-a8ee-e053-2a95a90a2265",
-                    "spl:c43de769-d6d8-3bb9-e053-2995a90a5aa2"
-                ]
-            },
-            {
-                "type": "Extension",
-                "name": "regulatory_approval",
-                "value": {
-                    "approval_ratings": [],
-                    "approval_year": ["1978"],
-                    "has_indication": [
-                        {
-                            "id": "hemonc:671",
-                            "type": "DiseaseDescriptor",
-                            "disease_id": "ncit:C7251",
-                            "label": "Testicular cancer"
-                        },
-                        {
-                            "id": "hemonc:645",
-                            "type": "DiseaseDescriptor",
-                            "disease_id": "ncit:C7431",
-                            "label": "Ovarian cancer"
-                        },
-                        {
-                            "id": "hemonc:569",
-                            "type": "DiseaseDescriptor",
-                            "disease_id": "ncit:C9334",
-                            "label": "Bladder cancer"
-                        }
-                    ]
-                }
-            }
-        ]
-    }
+    return fixture_data["cisplatin"]
 
 
 @pytest.fixture(scope="module")
-def spiramycin():
-    """Create fixture for spiramycin."""
-    return {
-        "id": "normalize.therapy:Spiramycin",
-        "type": "TherapyDescriptor",
-        "therapy_id": "ncit:C839",
-        "label": "Spiramycin",
-        "xrefs": [
-            "chemidplus:8025-81-8",
-            "wikidata:Q422265"
-        ],
-        "alternate_labels": [
-            "SPIRAMYCIN",
-            "Antibiotic 799",
-            "Rovamycin",
-            "Provamycin",
-            "Rovamycine",
-            "RP 5337",
-            "(4R,5S,6R,7R,9R,10R,11E,13E,16R)-10-{[(2R,5S,6R)-5-(dimethylamino)-6-methyltetrahydro-2H-pyran-2-yl]oxy}-9,16-dimethyl-5-methoxy-2-oxo-7-(2-oxoethyl)oxacyclohexadeca-11,13-dien-6-yl 3,6-dideoxy-4-O-(2,6-dideoxy-3-C-methyl-alpha-L-ribo-hexopyranosyl)-3-(dimethylamino)-alpha-D-glucopyranoside",  # noqa: E501
-            "spiramycin I"
-        ],
-        "extensions": [
-            {
-                "type": "Extension",
-                "name": "associated_with",
-                "value": [
-                    "umls:C0037962",
-                    "unii:71ODY0V87H",
-                    "pubchem.compound:5356392"
-                ]
-            }
-        ]
-    }
+def spiramycin(fixture_data):
+    """Create fixture for normalized spiramycin record."""
+    return fixture_data["spiramycin"]
 
 
 @pytest.fixture(scope="module")
-def therapeutic_procedure():
+def therapeutic_procedure(fixture_data):
     """Create a fixture for the Therapeutic Procedure concept. Used to validate
     single-member concept groups for the normalize endpoint.
     """
-    return {
-        "id": "normalize.therapy:ncit%3AC49236",
-        "therapy_id": "ncit:C49236",
-        "label": "Therapeutic Procedure",
-        "alternate_labels": [
-            "any therapy",
-            "any_therapy",
-            "Therapeutic Interventions",
-            "Therapeutic Method",
-            "Therapeutic Technique",
-            "therapy",
-            "Therapy",
-            "TREAT",
-            "Treatment",
-            "TX",
-            "treatment",
-            "treatment or therapy",
-            "treatment_or_therapy",
-        ],
-        "extensions": [
-            {
-                "name": "associated_with",
-                "value": ["umls:C0087111"],
-                "type": "Extension"
-            }
-        ],
-        "type": "TherapyDescriptor"
-    }
+    return fixture_data["therapeutic_procedure"]
 
 
 def compare_vod(response, fixture, query, match_type, response_id,
@@ -370,13 +86,13 @@ def compare_vod(response, fixture, query, match_type, response_id,
     if warnings is None:
         warnings = []
 
-    assert response["query"] == query
+    assert response.query == query
 
     # check warnings
     if warnings:
-        assert len(response["warnings"]) == len(warnings), "warnings len"
+        assert len(response.warnings) == len(warnings), "warnings len"
         for e_warnings in warnings:
-            for r_warnings in response["warnings"]:
+            for r_warnings in response.warnings:
                 for e_key, e_val in e_warnings.items():
                     for _, r_val in r_warnings.items():
                         if e_key == r_val:
@@ -385,33 +101,29 @@ def compare_vod(response, fixture, query, match_type, response_id,
                             else:
                                 assert r_val == e_val, "warnings val"
     else:
-        assert response["warnings"] == [], "warnings != []"
+        assert response.warnings == [], "warnings != []"
 
-    assert response["match_type"] == match_type
+    assert response.match_type == match_type
 
-    fixture = fixture.copy()
-    fixture["id"] = response_id
-    actual = response["therapy_descriptor"]
+    fixture = ValueObjectDescriptor(**fixture.copy())
+    fixture.id = response_id
+    actual = response.therapy_descriptor
 
-    assert actual["id"] == fixture["id"]
-    assert actual["type"] == fixture["type"]
-    assert actual["therapy_id"] == fixture["therapy_id"]
-    assert actual["label"] == fixture["label"]
+    assert actual.id == fixture.id
+    assert actual.type == fixture.type
+    assert actual.therapy_id == fixture.therapy_id
+    assert actual.label == fixture.label
 
-    assert ("xrefs" in actual.keys()) == ("xrefs" in fixture.keys())
-    if "xrefs" in actual:
-        print(actual["xrefs"])
-        print(fixture["xrefs"])
-        assert set(actual["xrefs"]) == set(fixture["xrefs"])
+    assert bool(actual.xrefs) == bool(fixture.xrefs)
+    if bool(actual.xrefs) and bool(fixture.xrefs):
+        assert set(actual.xrefs) == set(fixture.xrefs)
 
-    assert ("alternate_labels" in actual.keys()) == ("alternate_labels" in
-                                                     fixture.keys())
-    if "alternate_labels" in actual:
-        assert set(actual["alternate_labels"]) == \
-            set(fixture["alternate_labels"])
+    assert bool(actual.alternate_labels) == bool(fixture.alternate_labels)
+    if bool(actual.alternate_labels) and bool(fixture.alternate_labels):
+        assert set(actual.alternate_labels) == set(fixture.alternate_labels)
 
     def get_extension(extensions, name):
-        matches = [e for e in extensions if e["name"] == name]
+        matches = [e for e in extensions if e.name == name]
         if len(matches) > 1:
             assert False
         elif len(matches) == 1:
@@ -419,109 +131,109 @@ def get_extension(extensions, name):
         else:
             return None
 
-    assert ("extensions" in actual.keys()) == ("extensions" in fixture.keys())
-    if "extensions" in actual:
-        ext_actual = actual["extensions"]
-        ext_fixture = fixture["extensions"]
-
-        fda_actual = get_extension(ext_actual, "regulatory_approval")
-        fda_fixture = get_extension(ext_fixture, "regulatory_approval")
-        assert (fda_actual is None) == (fda_fixture is None), "regulatory_approval"
-        if fda_actual and fda_fixture:
-            ratings_actual = fda_actual.get("approval_ratings")
-            ratings_fixture = fda_fixture.get("approval_ratings")
+    assert bool(actual.extensions) == bool(fixture.extensions)
+    if bool(actual.extensions) == bool(fixture.extensions):
+        ext_actual = actual.extensions
+        ext_fixture = fixture.extensions
+
+        approv_actual = get_extension(ext_actual, "regulatory_approval")
+        approv_fixture = get_extension(ext_fixture, "regulatory_approval")
+        assert (approv_actual is None) == \
+            (approv_fixture is None), "regulatory_approval"
+        if approv_actual and approv_fixture:
+            ratings_actual = approv_actual.value.get("approval_ratings")
+            ratings_fixture = approv_fixture.value.get("approval_ratings")
             if ratings_actual or ratings_fixture:
                 assert set(ratings_actual) == set(ratings_fixture)
-            assert set(fda_actual.get("approval_year", [])) == \
-                set(fda_fixture.get("approval_year", []))
-            assert set(fda_actual.get("has_indication", [])) == \
-                set(fda_fixture.get("has_indication", []))
+            assert set(approv_actual.value.get("approval_year", [])) == \
+                set(approv_fixture.value.get("approval_year", []))
+            approv_inds = [json.dumps(ind) for ind
+                           in approv_actual.value.get("has_indication", [])]
+            fixture_inds = [json.dumps(ind) for ind
+                            in approv_fixture.value.get("has_indication", [])]
+            assert set(approv_inds) == set(fixture_inds)
 
         assoc_actual = get_extension(ext_actual, "associated_with")
         assoc_fixture = get_extension(ext_fixture, "associated_with")
         assert (assoc_actual is None) == (assoc_fixture is None)
         if assoc_actual:
-            assert assoc_fixture is not None
-            assert set(assoc_actual["value"]) == set(assoc_fixture["value"])
-            assert assoc_actual["value"]
+            assert assoc_fixture
+            assert assoc_actual.value
+            assert set(assoc_actual.value) == set(assoc_fixture.value)
 
         tn_actual = get_extension(ext_actual, "trade_names")
         tn_fixture = get_extension(ext_fixture, "trade_names")
         assert (tn_actual is None) == (tn_fixture is None)
         if tn_fixture:
-            assert tn_actual is not None
-            assert set(tn_actual["value"]) == set(tn_fixture["value"])
-            assert tn_actual["value"]
+            assert tn_actual
+            assert tn_actual.value
+            assert set(tn_actual.value) == set(tn_fixture.value)
 
         fda_actual = get_extension(ext_actual, "fda_approval")
         fda_fixture = get_extension(ext_fixture, "fda_approval")
         assert (fda_actual is None) == (fda_fixture is None)
         if fda_fixture:
-            assert fda_actual is not None
-            assert fda_actual.get("approval_status") == \
-                fda_fixture.get("approval_status")
-            assert set(fda_actual.get("approval_year", [])) == \
-                set(fda_fixture.get("approval_year", []))
-            assert set(fda_actual.get("has_indication", [])) == \
-                set(fda_fixture.get("has_indication", []))
+            assert fda_actual
+            assert fda_actual.value.get("approval_status") == \
+                fda_fixture.value.get("approval_status")
+            assert set(fda_actual.value.get("approval_year", [])) == \
+                set(fda_fixture.value.get("approval_year", []))
+            assert set(fda_actual.value.get("has_indication", [])) == \
+                set(fda_fixture.value.get("has_indication", []))
 
 
 def test_query(query_handler):
     """Test that query returns properly-structured response."""
-    resp = query_handler.search_sources("cisplatin", keyed=False)
-    assert resp["query"] == "cisplatin"
-    matches = resp["source_matches"]
+    resp = query_handler.search("cisplatin", keyed=False)
+    assert resp.query == "cisplatin"
+    matches = resp.source_matches
     assert isinstance(matches, list)
     assert len(matches) == 9
-    wikidata = list(filter(lambda m: m["source"] == "Wikidata",
-                           matches))[0]
-    assert len(wikidata["records"]) == 1
-    wikidata_record = wikidata["records"][0]
-    assert wikidata_record["label"] == "cisplatin"
+    wikidata = list(filter(lambda m: m.source == "Wikidata", matches))[0]
+    assert len(wikidata.records) == 1
+    wikidata_record = wikidata.records[0]
+    assert wikidata_record.label == "cisplatin"
 
     # test for not including redundant records w/ same match_type
-    resp = query_handler.search_sources("penicillamine", keyed=True)
-    matches = resp["source_matches"]["RxNorm"]
-    assert len(matches["records"]) == 1
+    resp = query_handler.search("penicillamine", keyed=True)
+    matches = resp.source_matches[SourceName.RXNORM]
+    assert len(matches.records) == 1
 
 
 def test_query_keyed(query_handler):
     """Test that query structures matches as dict when requested."""
-    resp = query_handler.search_sources("penicillin v", keyed=True)
-    matches = resp["source_matches"]
+    resp = query_handler.search("penicillin v", keyed=True)
+    matches = resp.source_matches
     assert isinstance(matches, dict)
-    chemidplus = matches["ChemIDplus"]
-    chemidplus_record = chemidplus["records"][0]
-    assert chemidplus_record["label"] == "Penicillin V"
+    chemidplus = matches[SourceName.CHEMIDPLUS]
+    chemidplus_record = chemidplus.records[0]
+    assert chemidplus_record.label == "Penicillin V"
 
 
 def test_query_specify_sources(query_handler):
     """Test inclusion and exclusion of sources in query."""
     # test blank params
-    resp = query_handler.search_sources("cisplatin", keyed=True)
-    assert set(resp["source_matches"].keys()) == {
+    resp = query_handler.search("cisplatin", keyed=True)
+    assert set(resp.source_matches.keys()) == {
         "Wikidata", "ChEMBL", "NCIt", "DrugBank", "ChemIDplus", "RxNorm", "HemOnc",
         "GuideToPHARMACOLOGY", "DrugsAtFDA"
     }
 
     # test partial inclusion
-    resp = query_handler.search_sources("cisplatin", keyed=True,
-                                        incl="chembl,ncit")
-    assert set(resp["source_matches"].keys()) == {"ChEMBL", "NCIt"}
+    resp = query_handler.search("cisplatin", keyed=True, incl="chembl,ncit")
+    assert set(resp.source_matches.keys()) == {"ChEMBL", "NCIt"}
 
     # test full inclusion
     sources = "chembl,ncit,drugbank,wikidata,rxnorm,chemidplus,hemonc,guidetopharmacology,drugsatfda"  # noqa: E501
-    resp = query_handler.search_sources("cisplatin", keyed=True,
-                                        incl=sources, excl="")
-    assert set(resp["source_matches"].keys()) == {
+    resp = query_handler.search("cisplatin", keyed=True, incl=sources, excl="")
+    assert set(resp.source_matches.keys()) == {
         "Wikidata", "ChEMBL", "NCIt", "DrugBank", "ChemIDplus", "RxNorm", "HemOnc",
         "GuideToPHARMACOLOGY", "DrugsAtFDA"
     }
 
     # test partial exclusion
-    resp = query_handler.search_sources("cisplatin", keyed=True,
-                                        excl="chemidplus")
-    assert set(resp["source_matches"].keys()) == {
+    resp = query_handler.search("cisplatin", keyed=True, excl="chemidplus")
+    assert set(resp.source_matches.keys()) == {
         "Wikidata", "ChEMBL", "NCIt", "DrugBank", "RxNorm", "HemOnc",
         "GuideToPHARMACOLOGY", "DrugsAtFDA"
     }
@@ -529,35 +241,33 @@ def test_query_specify_sources(query_handler):
     # test full exclusion
     sources = "chembl, wikidata, drugbank, ncit, rxnorm, chemidplus, hemonc, " \
         "guidetopharmacology,drugsatfda"  # noqa: E501
-    resp = query_handler.search_sources(
+    resp = query_handler.search(
         "cisplatin", keyed=True,
         excl=sources
     )
-    assert set(resp["source_matches"].keys()) == set()
+    assert set(resp.source_matches.keys()) == set()
 
     # test case insensitive
-    resp = query_handler.search_sources("cisplatin", keyed=True, excl="ChEmBl")
-    assert set(resp["source_matches"].keys()) == {
+    resp = query_handler.search("cisplatin", keyed=True, excl="ChEmBl")
+    assert set(resp.source_matches.keys()) == {
         "Wikidata", "NCIt", "DrugBank", "ChemIDplus", "RxNorm", "HemOnc",
         "GuideToPHARMACOLOGY", "DrugsAtFDA"
     }
 
-    resp = query_handler.search_sources("cisplatin", keyed=True,
-                                        incl="wIkIdAtA,cHeMbL")
-    assert set(resp["source_matches"].keys()) == {"Wikidata", "ChEMBL"}
+    resp = query_handler.search("cisplatin", keyed=True, incl="wIkIdAtA,cHeMbL")
+    assert set(resp.source_matches.keys()) == {"Wikidata", "ChEMBL"}
 
     # test error on invalid source names
     with pytest.raises(InvalidParameterException):
-        resp = query_handler.search_sources("cisplatin", keyed=True,
-                                            incl="chambl")
+        resp = query_handler.search("cisplatin", keyed=True, incl="chambl")
 
     # test error for supplying both incl and excl args
     with pytest.raises(InvalidParameterException):
-        resp = query_handler.search_sources("cisplatin", keyed=True,
-                                            incl="chembl", excl="wikidata")
+        resp = query_handler.search("cisplatin", keyed=True, incl="chembl",
+                                    excl="wikidata")
 
 
-def test_infer_option(query_handler, merge_query_handler):
+def test_infer_option(query_handler, normalize_query_handler):
     """Test infer_namespace boolean option"""
     # drugbank
     query = "DB01174"
@@ -567,13 +277,14 @@ def test_infer_option(query_handler, merge_query_handler):
         "alternate_inferred_matches": []
     }]
 
-    response = query_handler.search_sources(query, keyed=True)
-    assert response["source_matches"]["DrugBank"]["match_type"] == MatchType.CONCEPT_ID
-    assert response["warnings"] == expected_warnings
+    response = query_handler.search(query, keyed=True)
+    assert response.source_matches[SourceName.DRUGBANK].match_type == \
+        MatchType.CONCEPT_ID
+    assert response.warnings == expected_warnings
 
-    response = merge_query_handler.search_groups(query)
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert response["warnings"] == expected_warnings
+    response = normalize_query_handler.normalize(query)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert response.warnings == expected_warnings
 
     # ncit
     query = "c739"
@@ -583,13 +294,13 @@ def test_infer_option(query_handler, merge_query_handler):
         "alternate_inferred_matches": []
     }]
 
-    response = query_handler.search_sources(query, keyed=True)
-    assert response["source_matches"]["NCIt"]["match_type"] == MatchType.CONCEPT_ID
-    assert response["warnings"] == expected_warnings
+    response = query_handler.search(query, keyed=True)
+    assert response.source_matches["NCIt"].match_type == MatchType.CONCEPT_ID
+    assert response.warnings == expected_warnings
 
-    response = merge_query_handler.search_groups(query)
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert response["warnings"] == expected_warnings
+    response = normalize_query_handler.normalize(query)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert response.warnings == expected_warnings
 
     # chemidplus
     query = "15663-27-1"
@@ -599,14 +310,14 @@ def test_infer_option(query_handler, merge_query_handler):
         "alternate_inferred_matches": [],
     }]
 
-    response = query_handler.search_sources(query, keyed=True)
-    assert response["source_matches"]["ChemIDplus"]["match_type"] == \
+    response = query_handler.search(query, keyed=True)
+    assert response.source_matches["ChemIDplus"].match_type == \
         MatchType.CONCEPT_ID
-    assert response["warnings"] == expected_warnings
+    assert response.warnings == expected_warnings
 
-    response = merge_query_handler.search_groups(query)
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert response["warnings"] == expected_warnings
+    response = normalize_query_handler.normalize(query)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert response.warnings == expected_warnings
 
     # chembl
     query = "chembl11359"
@@ -616,14 +327,14 @@ def test_infer_option(query_handler, merge_query_handler):
         "alternate_inferred_matches": [],
     }]
 
-    response = query_handler.search_sources(query, keyed=True)
-    assert response["source_matches"]["ChEMBL"]["match_type"] == \
+    response = query_handler.search(query, keyed=True)
+    assert response.source_matches["ChEMBL"].match_type == \
         MatchType.CONCEPT_ID
-    assert response["warnings"] == expected_warnings
+    assert response.warnings == expected_warnings
 
-    response = merge_query_handler.search_groups(query)
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert response["warnings"] == expected_warnings
+    response = normalize_query_handler.normalize(query)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert response.warnings == expected_warnings
 
     # wikidata
     query = "q412415"
@@ -633,14 +344,14 @@ def test_infer_option(query_handler, merge_query_handler):
         "alternate_inferred_matches": [],
     }]
 
-    response = query_handler.search_sources(query, keyed=True)
-    assert response["source_matches"]["Wikidata"]["match_type"] == \
+    response = query_handler.search(query, keyed=True)
+    assert response.source_matches["Wikidata"].match_type == \
         MatchType.CONCEPT_ID
-    assert response["warnings"] == expected_warnings
+    assert response.warnings == expected_warnings
 
-    response = merge_query_handler.search_groups(query)
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert response["warnings"] == expected_warnings
+    response = normalize_query_handler.normalize(query)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert response.warnings == expected_warnings
 
     # drugs@fda
     query = "ANDA075036"
@@ -650,14 +361,14 @@ def test_infer_option(query_handler, merge_query_handler):
         "alternate_inferred_matches": [],
     }]
 
-    response = query_handler.search_sources(query, keyed=True)
-    assert response["source_matches"]["DrugsAtFDA"]["match_type"] == \
+    response = query_handler.search(query, keyed=True)
+    assert response.source_matches["DrugsAtFDA"].match_type == \
         MatchType.CONCEPT_ID
-    assert response["warnings"] == expected_warnings
+    assert response.warnings == expected_warnings
 
-    response = merge_query_handler.search_groups(query)
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert response["warnings"] == expected_warnings
+    response = normalize_query_handler.normalize(query)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert response.warnings == expected_warnings
 
     query = "nda018057"
     expected_warnings = [{
@@ -666,132 +377,132 @@ def test_infer_option(query_handler, merge_query_handler):
         "alternate_inferred_matches": [],
     }]
 
-    response = query_handler.search_sources(query, keyed=True)
-    assert response["source_matches"]["DrugsAtFDA"]["match_type"] == \
+    response = query_handler.search(query, keyed=True)
+    assert response.source_matches["DrugsAtFDA"].match_type == \
         MatchType.CONCEPT_ID
-    assert response["warnings"] == expected_warnings
+    assert response.warnings == expected_warnings
 
-    response = merge_query_handler.search_groups(query)
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert response["warnings"] == expected_warnings
+    response = normalize_query_handler.normalize(query)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert response.warnings == expected_warnings
 
     # test disabling namespace inference
     query = "DB01174"
-    response = merge_query_handler.search_groups(query, infer=False)
-    assert response["query"] == query
-    assert response["warnings"] == []
+    response = normalize_query_handler.normalize(query, infer=False)
+    assert response.query == query
+    assert response.warnings == []
     assert "record" not in response
-    assert response["match_type"] == MatchType.NO_MATCH
+    assert response.match_type == MatchType.NO_MATCH
 
 
-def test_query_merged(merge_query_handler, phenobarbital, cisplatin,
-                      spiramycin, therapeutic_procedure):
-    """Test that the merged concept endpoint handles queries correctly."""
+def test_query_normalize(normalize_query_handler, phenobarbital, cisplatin,
+                         spiramycin, therapeutic_procedure):
+    """Test that the normalized concept endpoint handles queries correctly."""
     # test merged id match
     query = "rxcui:2555"
-    response = merge_query_handler.search_groups(query)
+    response = normalize_query_handler.normalize(query)
     compare_vod(response, cisplatin, query, MatchType.CONCEPT_ID,
                 "normalize.therapy:rxcui%3A2555")
 
     # test concept id match
     query = "chemidplus:50-06-6"
-    response = merge_query_handler.search_groups(query)
+    response = normalize_query_handler.normalize(query)
     compare_vod(response, phenobarbital, query, MatchType.CONCEPT_ID,
                 "normalize.therapy:chemidplus%3A50-06-6")
 
     query = "hemonc:105"
-    response = merge_query_handler.search_groups(query)
+    response = normalize_query_handler.normalize(query)
     compare_vod(response, cisplatin, query, MatchType.CONCEPT_ID,
                 "normalize.therapy:hemonc%3A105")
 
     # test label match
     query = "Phenobarbital"
-    response = merge_query_handler.search_groups(query)
+    response = normalize_query_handler.normalize(query)
     compare_vod(response, phenobarbital, query, MatchType.LABEL,
                 "normalize.therapy:Phenobarbital")
 
     # test trade name match
     query = "Platinol"
-    response = merge_query_handler.search_groups(query)
+    response = normalize_query_handler.normalize(query)
     compare_vod(response, cisplatin, query, MatchType.TRADE_NAME,
                 "normalize.therapy:Platinol")
 
     # test alias match
     query = "cis Diamminedichloroplatinum"
-    response = merge_query_handler.search_groups(query)
+    response = normalize_query_handler.normalize(query)
     compare_vod(response, cisplatin, query, MatchType.ALIAS,
                 "normalize.therapy:cis%20Diamminedichloroplatinum")
 
     query = "Rovamycine"
-    response = merge_query_handler.search_groups(query)
+    response = normalize_query_handler.normalize(query)
     compare_vod(response, spiramycin, query, MatchType.ALIAS,
                 "normalize.therapy:Rovamycine")
 
     # test normalized group with single member
     query = "any therapy"
-    response = merge_query_handler.search_groups(query)
+    response = normalize_query_handler.normalize(query)
     compare_vod(response, therapeutic_procedure, query, MatchType.ALIAS,
                 "normalize.therapy:any%20therapy")
 
     # test that term with multiple possible resolutions resolves at highest
     # match
     query = "Cisplatin"
-    response = merge_query_handler.search_groups(query)
+    response = normalize_query_handler.normalize(query)
     compare_vod(response, cisplatin, query, MatchType.TRADE_NAME,
                 "normalize.therapy:Cisplatin")
 
     # test whitespace stripping
     query = "   Cisplatin "
-    response = merge_query_handler.search_groups(query)
+    response = normalize_query_handler.normalize(query)
     compare_vod(response, cisplatin, query, MatchType.TRADE_NAME,
                 "normalize.therapy:Cisplatin")
 
     # test no match
     query = "zzzz fake therapy zzzz"
-    response = merge_query_handler.search_groups(query)
-    assert response["query"] == query
-    assert response["warnings"] == []
+    response = normalize_query_handler.normalize(query)
+    assert response.query == query
+    assert response.warnings == []
     assert "record" not in response
-    assert response["match_type"] == MatchType.NO_MATCH
+    assert response.match_type == MatchType.NO_MATCH
 
 
-def test_merged_meta(merge_query_handler):
+def test_merged_meta(normalize_query_handler):
     """Test population of source and resource metadata in merged querying."""
     query = "phenobarbital"
-    response = merge_query_handler.search_groups(query)
-    meta_items = response["source_meta_"]
-    assert "RxNorm" in meta_items.keys()
-    assert "Wikidata" in meta_items.keys()
-    assert "NCIt" in meta_items.keys()
-    assert "ChemIDplus" in meta_items.keys()
+    response = normalize_query_handler.normalize(query)
+    meta_items = response.source_meta_
+    assert SourceName.RXNORM in meta_items
+    assert SourceName.WIKIDATA in meta_items
+    assert SourceName.NCIT in meta_items
+    assert SourceName.CHEMIDPLUS in meta_items
 
     query = "RP 5337"
-    response = merge_query_handler.search_groups(query)
-    meta_items = response["source_meta_"]
-    assert "NCIt" in meta_items.keys()
-    assert "ChemIDplus" in meta_items.keys()
+    response = normalize_query_handler.normalize(query)
+    meta_items = response.source_meta_
+    assert SourceName.NCIT in meta_items
+    assert SourceName.CHEMIDPLUS in meta_items
 
 
-def test_service_meta(query_handler, merge_query_handler):
+def test_service_meta(query_handler, normalize_query_handler):
     """Test service meta info in response."""
     query = "pheno"
 
-    response = query_handler.search_sources(query)
-    service_meta = response["service_meta_"]
-    assert service_meta["name"] == "thera-py"
-    assert service_meta["version"] >= "0.2.13"
-    assert isinstance(service_meta["response_datetime"], datetime)
-    assert service_meta["url"] == "https://github.com/cancervariants/therapy-normalization"  # noqa: E501
+    response = query_handler.search(query)
+    service_meta = response.service_meta_
+    assert service_meta.name == "thera-py"
+    assert service_meta.version >= "0.2.13"
+    assert isinstance(service_meta.response_datetime, datetime)
+    assert service_meta.url == "https://github.com/cancervariants/therapy-normalization"  # noqa: E501
 
-    response = merge_query_handler.search_groups(query)
-    service_meta = response["service_meta_"]
-    assert service_meta["name"] == "thera-py"
-    assert service_meta["version"] >= "0.2.13"
-    assert isinstance(service_meta["response_datetime"], datetime)
-    assert service_meta["url"] == "https://github.com/cancervariants/therapy-normalization"  # noqa: E501
+    response = normalize_query_handler.normalize(query)
+    service_meta = response.service_meta_
+    assert service_meta.name == "thera-py"
+    assert service_meta.version >= "0.2.13"
+    assert isinstance(service_meta.response_datetime, datetime)
+    assert service_meta.url == "https://github.com/cancervariants/therapy-normalization"  # noqa: E501
 
 
-def test_broken_db_handling(merge_query_handler):
+def test_broken_db_handling(normalize_query_handler):
     """Test that query fails gracefully if mission-critical DB references are
     broken.
 
@@ -800,4 +511,4 @@ def test_broken_db_handling(merge_query_handler):
     exception.
     """
     query = "fake:00001"
-    assert merge_query_handler.search_groups(query)
+    assert normalize_query_handler.normalize(query)
diff --git a/tests/unit/test_rxnorm.py b/tests/unit/test_rxnorm.py
index 9c25b159..93fa727a 100644
--- a/tests/unit/test_rxnorm.py
+++ b/tests/unit/test_rxnorm.py
@@ -25,9 +25,8 @@ def __init__(self):
             self.db = Database(db_url=db_url)
 
         def search(self, query_str):
-            resp = self.normalizer.search_sources(query_str, keyed=True,
-                                                  incl="rxnorm")
-            return resp["source_matches"]["RxNorm"]
+            resp = self.normalizer.search(query_str, keyed=True, incl="rxnorm")
+            return resp.source_matches["RxNorm"]
 
         def fetch_meta(self):
             return self.normalizer._fetch_meta("RxNorm")
@@ -45,7 +44,7 @@ def bifidobacterium_infantis():
             "bifidobacterium infantis",
             "Bifidobacterium infantis"
         ],
-        "approval_rating": "rxnorm_prescribable",
+        "approval_ratings": ["rxnorm_prescribable"],
         "xrefs": [
             "drugbank:DB14222"
         ],
@@ -82,7 +81,7 @@ def cisplatin():
             "CDDP",
             "Cis-DDP",
         ],
-        "approval_rating": "rxnorm_prescribable",
+        "approval_ratings": ["rxnorm_prescribable"],
         "xrefs": [
             "drugbank:DB00515",
             "drugbank:DB12117"
@@ -116,7 +115,7 @@ def amiloride_hydrochloride():
             "Amiloride Hydrochloride",
             "Hydrochloride, Amiloride"
         ],
-        "approval_rating": "rxnorm_prescribable",
+        "approval_ratings": ["rxnorm_prescribable"],
         "xrefs": [],
         "associated_with": [
             "usp:m2650",
@@ -154,7 +153,7 @@ def amiloride():
             "N-amidino-3,5-diamino-6-chloropyrazinecarboxamide",
             "Amyloride"
         ],
-        "approval_rating": "rxnorm_prescribable",
+        "approval_ratings": ["rxnorm_prescribable"],
         "xrefs": [
             "drugbank:DB00594"
         ],
@@ -192,7 +191,7 @@ def timolol():
             "(S)-1-(tert-butylamino)-3-[(4-morpholin-4-yl-1,2,5-thiadiazol"
             "-3-yl)oxy]propan-2-ol"
         ],
-        "approval_rating": "rxnorm_prescribable",
+        "approval_ratings": ["rxnorm_prescribable"],
         "xrefs": [
             "drugbank:DB00373"
         ],
@@ -246,7 +245,7 @@ def lymphocyte():
             "Globulin, Anti-Thymocyte",
             "lymphocyte immune globulin, anti-thy (obs)"
         ],
-        "approval_rating": "rxnorm_prescribable",
+        "approval_ratings": ["rxnorm_prescribable"],
         "xrefs": [],
         "associated_with": [
             "mesh:D000961",
@@ -282,7 +281,7 @@ def aspirin():
             "o-carboxyphenyl acetate",
             "Acetylsalicylic Acid"
         ],
-        "approval_rating": "rxnorm_prescribable",
+        "approval_ratings": ["rxnorm_prescribable"],
         "xrefs": [
             "drugbank:DB00945"
         ],
@@ -317,7 +316,7 @@ def mesna():
             "2-Mercaptoethanesulphonate, Sodium",
             "Sodium 2-Mercaptoethanesulphonate"
         ],
-        "approval_rating": "rxnorm_prescribable",
+        "approval_ratings": ["rxnorm_prescribable"],
         "xrefs": [],
         "associated_with": [
             "usp:m49500",
@@ -350,7 +349,7 @@ def beta_alanine():
             "3 Aminopropionic Acid",
             "3-Aminopropionic Acid"
         ],
-        "approval_rating": "rxnorm_prescribable",
+        "approval_ratings": ["rxnorm_prescribable"],
         "xrefs": [],
         "associated_with": [
             "mesh:D015091",
@@ -374,7 +373,7 @@ def algestone():
             "Alphasone",
             "Dihydroxyprogesterone"
         ],
-        "approval_rating": None,
+        "approval_ratings": [],
         "xrefs": [],
         "associated_with": [
             "mesh:D000523"
@@ -408,7 +407,7 @@ def levothyroxine():
             "4-(4-Hydroxy-3,5-diiodophenoxy)-3,5-diiodo-L-phenylalanine",
             "Levothyroxin"
         ],
-        "approval_rating": "rxnorm_prescribable",
+        "approval_ratings": ["rxnorm_prescribable"],
         "xrefs": [
             "drugbank:DB00451"
         ],
@@ -439,7 +438,7 @@ def fluoxetine():
             "(+-)-N-Methyl-3-phenyl-3-((alpha,alpha,alpha-trifluoro-"
             "P-tolyl)oxy)propylamine"
         ],
-        "approval_rating": "rxnorm_prescribable",
+        "approval_ratings": ["rxnorm_prescribable"],
         "xrefs": [
             "drugbank:DB00472"
         ],
@@ -473,7 +472,7 @@ def fluoxetine_hydrochloride():
             "FLUoxetine hydrochloride",
             "Fluoxetine Hydrochloride"
         ],
-        "approval_rating": "rxnorm_prescribable",
+        "approval_ratings": ["rxnorm_prescribable"],
         "xrefs": [],
         "associated_with": [
             "usp:m33780",
@@ -499,80 +498,80 @@ def test_bifidobacterium_infantis(bifidobacterium_infantis, rxnorm):
     """
     # Concept ID Match
     response = rxnorm.search("RxCUI:100213")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], bifidobacterium_infantis)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], bifidobacterium_infantis)
 
     # Label Match
     response = rxnorm.search(" Bifidobacterium infantis")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], bifidobacterium_infantis)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], bifidobacterium_infantis)
 
     response = rxnorm.search("bifidobacterium infantis")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], bifidobacterium_infantis)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], bifidobacterium_infantis)
 
     # Trade Name Match
     response = rxnorm.search("ALIGN")
-    assert response["match_type"] == MatchType.TRADE_NAME
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], bifidobacterium_infantis)
+    assert response.match_type == MatchType.TRADE_NAME
+    assert len(response.records) == 1
+    compare_records(response.records[0], bifidobacterium_infantis)
 
     response = rxnorm.search("evivo")
-    assert response["match_type"] == MatchType.TRADE_NAME
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], bifidobacterium_infantis)
+    assert response.match_type == MatchType.TRADE_NAME
+    assert len(response.records) == 1
+    compare_records(response.records[0], bifidobacterium_infantis)
 
     # Xref Match
     response = rxnorm.search("drugbank:DB14222")
-    assert response["match_type"] == MatchType.XREF
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], bifidobacterium_infantis)
+    assert response.match_type == MatchType.XREF
+    assert len(response.records) == 1
+    compare_records(response.records[0], bifidobacterium_infantis)
 
 
 def test_cisplatin(cisplatin, rxnorm):
     """Test that cisplatin drug normalizes to correct drug concept."""
     # Concept ID Match
     response = rxnorm.search("RxCUI:2555")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     # Label Match
     response = rxnorm.search("CISPLATIN")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     # Alias Match
     response = rxnorm.search("Cis-DDP")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = rxnorm.search("Dichlorodiammineplatinum")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = rxnorm.search("cis Platinum")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     # Trade Name Match
     response = rxnorm.search("platinol")
-    assert response["match_type"] == MatchType.TRADE_NAME
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.TRADE_NAME
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     # Xref Match
     response = rxnorm.search("drugbank:DB12117")
-    assert response["match_type"] == MatchType.XREF
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.XREF
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
 
 def test_amiloride_hydrochloride(amiloride_hydrochloride, rxnorm):
@@ -581,20 +580,20 @@ def test_amiloride_hydrochloride(amiloride_hydrochloride, rxnorm):
     """
     # Concept ID Match
     response = rxnorm.search("RxcUI:142424")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], amiloride_hydrochloride)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], amiloride_hydrochloride)
 
     # Label Match
     response = rxnorm.search("amiloride hydrochloride")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], amiloride_hydrochloride)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], amiloride_hydrochloride)
 
     # Trade Name Match
     response = rxnorm.search("Midamor")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 2
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 2
 
 
 def test_amiloride(amiloride, rxnorm):
@@ -603,245 +602,245 @@ def test_amiloride(amiloride, rxnorm):
     """
     # Concept ID Match
     response = rxnorm.search("RxcUI:644")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], amiloride)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], amiloride)
 
     # Label Match
     response = rxnorm.search("amiloride")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], amiloride)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], amiloride)
 
     # Alias Match
     response = rxnorm.search("Amyloride")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], amiloride)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], amiloride)
 
     response = rxnorm.search("3,5-diamino-N-carbamimidoyl-6-"
                              "chloropyrazine-2-carboxamide")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], amiloride)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], amiloride)
 
     # Trade Name Match
     response = rxnorm.search("Midamor")
-    assert response["match_type"] == MatchType.TRADE_NAME
-    assert len(response["records"]) == 2
+    assert response.match_type == MatchType.TRADE_NAME
+    assert len(response.records) == 2
 
 
 def test_timolol(timolol, rxnorm):
     """Test that timolol drug normalizes to correct drug concept."""
     # Concept ID Match
     response = rxnorm.search("RxcUI:10600")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], timolol)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], timolol)
 
     # Label Match
     response = rxnorm.search("timolol")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], timolol)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], timolol)
 
     # Alias Match
     response = rxnorm.search("(S)-1-(tert-butylamino)-3-[(4-"
                              "morpholin-4-yl-1,2,5-thiadiazol"
                              "-3-yl)oxy]propan-2-ol")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], timolol)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], timolol)
 
     # Trade Name Match
     response = rxnorm.search("Betimol")
-    assert response["match_type"] == MatchType.TRADE_NAME
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], timolol)
+    assert response.match_type == MatchType.TRADE_NAME
+    assert len(response.records) == 1
+    compare_records(response.records[0], timolol)
 
 
 def test_lymphocyte(lymphocyte, rxnorm):
     """Test that lymphocyte drug normalizes to correct drug concept."""
     # Concept ID Match
     response = rxnorm.search("RxCUI:1011")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], lymphocyte)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], lymphocyte)
 
     # Label Match
     response = rxnorm.search("lymphocyte immune globulin, "
                              "anti-thymocyte globulin")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], lymphocyte)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], lymphocyte)
 
     # Alias Match
     response = rxnorm.search("Anti Thymocyte Globulin")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], lymphocyte)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], lymphocyte)
 
     response = rxnorm.search("Antithymoglobulin")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], lymphocyte)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], lymphocyte)
 
     # Trade Name Match
     response = rxnorm.search("Thymoglobulin")
-    assert response["match_type"] == MatchType.TRADE_NAME
-    assert len(response["records"]) == 2
-    response["records"].sort(key=lambda r: r["concept_id"])
-    compare_records(response["records"][0], lymphocyte)
+    assert response.match_type == MatchType.TRADE_NAME
+    assert len(response.records) == 2
+    response.records.sort(key=lambda r: r.concept_id)
+    compare_records(response.records[0], lymphocyte)
 
     response = rxnorm.search("ATGAM")
-    assert response["match_type"] == MatchType.TRADE_NAME
-    assert len(response["records"]) == 2
-    response["records"].sort(key=lambda r: r["concept_id"])
-    compare_records(response["records"][0], lymphocyte)
+    assert response.match_type == MatchType.TRADE_NAME
+    assert len(response.records) == 2
+    response.records.sort(key=lambda r: r.concept_id)
+    compare_records(response.records[0], lymphocyte)
 
 
 def test_aspirin(aspirin, rxnorm):
     """Test that aspirin drug normalizes to correct drug concept."""
     # Concept ID Match
     response = rxnorm.search("RxcUI:1191")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], aspirin)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], aspirin)
 
     # (Trade Name) No Match
     response = rxnorm.search("Anacin")
-    assert response["match_type"] == MatchType.NO_MATCH
-    assert len(response["records"]) == 0
+    assert response.match_type == MatchType.NO_MATCH
+    assert len(response.records) == 0
 
 
 def test_mesnan(mesna, rxnorm):
     """Test that mesna drug normalizes to correct drug concept."""
     # Concept ID Match
     response = rxnorm.search("RxCUI:44")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], mesna)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], mesna)
 
     # Label Match
     response = rxnorm.search("mesna")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], mesna)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], mesna)
 
     # Alias Match
     response = rxnorm.search("Mesnum")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], mesna)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], mesna)
 
     response = rxnorm.search("Ethanesulfonic acid, 2-mercapto-, "
                              "monosodium salt")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], mesna)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], mesna)
 
     # Trade Name Match
     response = rxnorm.search("Mesnex")
-    assert response["match_type"] == MatchType.TRADE_NAME
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], mesna)
+    assert response.match_type == MatchType.TRADE_NAME
+    assert len(response.records) == 1
+    compare_records(response.records[0], mesna)
 
 
 def test_beta_alanine(beta_alanine, rxnorm):
     """Test that beta_alanine drug normalizes to correct drug concept."""
     # Concept ID Match
     response = rxnorm.search("RxCUI:61")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], beta_alanine)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], beta_alanine)
 
     # Label Match
     response = rxnorm.search("beta-alanine")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], beta_alanine)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], beta_alanine)
 
     # Alias Match
     response = rxnorm.search("3 Aminopropionic Acid")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], beta_alanine)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], beta_alanine)
 
 
 def test_algestone(algestone, rxnorm):
     """Test that algestone drug normalizes to correct drug concept."""
     # Concept ID Match
     response = rxnorm.search("RxCUI:595")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], algestone)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], algestone)
 
     # Label Match
     response = rxnorm.search("algestone")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], algestone)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], algestone)
 
     # Alias Match
     response = rxnorm.search("Pregn-4-ene-3,20-dione, 16,"
                              "17-dihydroxy-, (16alpha)-")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], algestone)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], algestone)
 
 
 def test_levothyroxine(levothyroxine, rxnorm):
     """Test that levothyroxine drug normalizes to correct drug concept."""
     # Concept ID Match
     response = rxnorm.search("RxCUI:10582")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], levothyroxine)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], levothyroxine)
 
     # Label Match
     response = rxnorm.search("levothyroxine")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], levothyroxine)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], levothyroxine)
 
     # Alias Match
     response = rxnorm.search("Thyroxin")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], levothyroxine)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], levothyroxine)
 
     response = rxnorm.search("LT4")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], levothyroxine)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], levothyroxine)
 
     # trade name matches fail because they exceed the max # limit
     response = rxnorm.search("Unithroid")
-    assert response["match_type"] == MatchType.NO_MATCH
+    assert response.match_type == MatchType.NO_MATCH
 
     response = rxnorm.search("Euthyrox")
-    assert response["match_type"] == MatchType.NO_MATCH
+    assert response.match_type == MatchType.NO_MATCH
 
     # Xref Match
     response = rxnorm.search("DRUGBANK:DB00451")
-    assert response["match_type"] == MatchType.XREF
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], levothyroxine)
+    assert response.match_type == MatchType.XREF
+    assert len(response.records) == 1
+    compare_records(response.records[0], levothyroxine)
 
 
 def test_fluoxetine(fluoxetine, rxnorm):
     """Test that fluoxetine drug normalizes to correct drug concept."""
     # Concept ID Match
     response = rxnorm.search("RxCUI:4493")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], fluoxetine)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], fluoxetine)
 
     # Label Match
     response = rxnorm.search("fluoxetine")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], fluoxetine)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], fluoxetine)
 
 
 def test_fluoxetine_hydrochloride(fluoxetine_hydrochloride, rxnorm):
@@ -850,45 +849,45 @@ def test_fluoxetine_hydrochloride(fluoxetine_hydrochloride, rxnorm):
     """
     # Concept ID Match
     response = rxnorm.search("RxCUI:227224")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], fluoxetine_hydrochloride)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], fluoxetine_hydrochloride)
 
     # Label Match
     response = rxnorm.search("fluoxetine hydrochloride")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], fluoxetine_hydrochloride)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], fluoxetine_hydrochloride)
 
 
 def test_no_match(rxnorm):
     """Test that a term normalizes to correct drug concept as a NO match."""
     # Misspelled name
     response = rxnorm.search("17-hydroxycorticosteroi")
-    assert response["match_type"] == MatchType.NO_MATCH
-    assert len(response["records"]) == 0
+    assert response.match_type == MatchType.NO_MATCH
+    assert len(response.records) == 0
 
     # Not storing foreign synonyms
     response = rxnorm.search("cisplatino")
-    assert response["match_type"] == MatchType.NO_MATCH
-    assert len(response["records"]) == 0
+    assert response.match_type == MatchType.NO_MATCH
+    assert len(response.records) == 0
 
     # Wrong Namespace
     response = rxnorm.search("rxnorm:3")
-    assert response["match_type"] == MatchType.NO_MATCH
+    assert response.match_type == MatchType.NO_MATCH
 
     # Test white space in between id
     response = rxnorm.search("rxcui: 3")
-    assert response["match_type"] == MatchType.NO_MATCH
+    assert response.match_type == MatchType.NO_MATCH
 
     # Should not store brand name concepts as identity record
     response = rxnorm.search("rxcui:202433")
-    assert response["match_type"] == MatchType.NO_MATCH
+    assert response.match_type == MatchType.NO_MATCH
 
     # Test empty query
     response = rxnorm.search("")
-    assert response["match_type"] == MatchType.NO_MATCH
-    assert len(response["records"]) == 0
+    assert response.match_type == MatchType.NO_MATCH
+    assert len(response.records) == 0
 
 
 def test_brand_name_to_concept(rxnorm):
@@ -909,19 +908,19 @@ def test_brand_name_to_concept(rxnorm):
 def test_xref_lookup(rxnorm, bifidobacterium_infantis, cisplatin, amiloride):
     """Test that xref lookup resolves to correct concept."""
     response = rxnorm.search("mmsl:d07347")
-    assert response["match_type"] == MatchType.ASSOCIATED_WITH
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], bifidobacterium_infantis)
+    assert response.match_type == MatchType.ASSOCIATED_WITH
+    assert len(response.records) == 1
+    compare_records(response.records[0], bifidobacterium_infantis)
 
     response = rxnorm.search("mesh:D002945")
-    assert response["match_type"] == MatchType.ASSOCIATED_WITH
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.ASSOCIATED_WITH
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = rxnorm.search("atc:C03DB01")
-    assert response["match_type"] == MatchType.ASSOCIATED_WITH
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], amiloride)
+    assert response.match_type == MatchType.ASSOCIATED_WITH
+    assert len(response.records) == 1
+    compare_records(response.records[0], amiloride)
 
 
 def test_meta_info(rxnorm):
diff --git a/tests/unit/test_wikidata.py b/tests/unit/test_wikidata.py
index dc6e6e63..137ec56c 100644
--- a/tests/unit/test_wikidata.py
+++ b/tests/unit/test_wikidata.py
@@ -18,9 +18,8 @@ def __init__(self):
             self.query_handler = QueryHandler()
 
         def search(self, query_str):
-            resp = self.query_handler.search_sources(query_str, keyed=True,
-                                                     incl="wikidata")
-            return resp["source_matches"]["Wikidata"]
+            resp = self.query_handler.search(query_str, keyed=True, incl="wikidata")
+            return resp.source_matches["Wikidata"]
     return QueryGetter()
 
 
@@ -38,7 +37,7 @@ def cisplatin():
             "Platinol",
             "Platinol-AQ"
         ],
-        "approval_rating": None,
+        "approval_ratings": [],
         "xrefs": [
             "chembl:CHEMBL11359",
             "drugbank:DB00515",
@@ -70,7 +69,7 @@ def interferon_alfacon_1():
             "Recombinant Consensus Interferon",
             "Recombinant methionyl human consensus interferon"
         ],
-        "approval_rating": None,
+        "approval_ratings": [],
         "xrefs": [
             "chembl:CHEMBL1201557",
             "drugbank:DB00069",
@@ -91,7 +90,7 @@ def d_methamphetamine():
         "label": "D-methamphetamine",
         "concept_id": "wikidata:Q191924",
         "aliases": [],
-        "approval_rating": None,
+        "approval_ratings": [],
         "xrefs": [
             "chembl:CHEMBL1201201",
             "drugbank:DB01577",
@@ -130,7 +129,7 @@ def atropine():
             "3-hydroxy-2-phenylpropanoate",
             "8-Methyl-8-azabicyclo[3.2.1]oct-3-yl tropate"
         ],
-        "approval_rating": None,
+        "approval_ratings": [],
         "xrefs": [
             "drugbank:DB00572",
             "chemidplus:51-55-8",
@@ -147,201 +146,201 @@ def atropine():
 def test_cisplatin(cisplatin, wikidata):
     """Test that cisplatin drug normalizes to correct drug concept."""
     response = wikidata.search("wikidata:Q412415")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = wikidata.search("wiKIdata:Q412415")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = wikidata.search("wiKIdata:q412415")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = wikidata.search("cisplatin")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = wikidata.search("Cisplatin")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = wikidata.search("CDDP")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = wikidata.search("cddp")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = wikidata.search("chembl:CHEMBL11359")
-    assert response["match_type"] == MatchType.XREF
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.XREF
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = wikidata.search("drugbank:DB00515")
-    assert response["match_type"] == MatchType.XREF
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.XREF
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = wikidata.search("rxcui:2555")
-    assert response["match_type"] == MatchType.XREF
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.XREF
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = wikidata.search("chemidplus:15663-27-1")
-    assert response["match_type"] == MatchType.XREF
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.XREF
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
     response = wikidata.search("pubchem.compound:5702198")
-    assert response["match_type"] == MatchType.XREF
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], cisplatin)
+    assert response.match_type == MatchType.XREF
+    assert len(response.records) == 1
+    compare_records(response.records[0], cisplatin)
 
 
 def test_atropine(atropine, wikidata):
     """Test that atropine drug normalizes to correct drug concept."""
     response = wikidata.search("wikidata:Q26272")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], atropine)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], atropine)
 
     response = wikidata.search("wiKIdata:Q26272")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], atropine)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], atropine)
 
     response = wikidata.search("wiKIdata:q26272")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], atropine)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], atropine)
 
     response = wikidata.search("atropine")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], atropine)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], atropine)
 
     response = wikidata.search("Atropine")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], atropine)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], atropine)
 
     response = wikidata.search("Mydriasine")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], atropine)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], atropine)
 
     response = wikidata.search("(±)-Hyoscyamine")
-    assert response["match_type"] == MatchType.ALIAS
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], atropine)
+    assert response.match_type == MatchType.ALIAS
+    assert len(response.records) == 1
+    compare_records(response.records[0], atropine)
 
     response = wikidata.search("chemidplus:51-55-8")
-    assert response["match_type"] == MatchType.XREF
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], atropine)
+    assert response.match_type == MatchType.XREF
+    assert len(response.records) == 1
+    compare_records(response.records[0], atropine)
 
     response = wikidata.search("pubchem.compound:174174")
-    assert response["match_type"] == MatchType.ASSOCIATED_WITH
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], atropine)
+    assert response.match_type == MatchType.ASSOCIATED_WITH
+    assert len(response.records) == 1
+    compare_records(response.records[0], atropine)
 
 
 def test_interferon_alfacon_1(interferon_alfacon_1, wikidata):
     """Test that interferon alfacon-1 drug normalizes to correct concept"""
     response = wikidata.search("wikidata:Q15353101")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], interferon_alfacon_1)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], interferon_alfacon_1)
 
     response = wikidata.search("wiKIdata:Q15353101")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], interferon_alfacon_1)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], interferon_alfacon_1)
 
     response = wikidata.search("wiKIdata:q15353101")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], interferon_alfacon_1)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], interferon_alfacon_1)
 
     response = wikidata.search("Interferon alfacon-1")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], interferon_alfacon_1)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], interferon_alfacon_1)
 
     response = wikidata.search("Interferon Alfacon-1")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], interferon_alfacon_1)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], interferon_alfacon_1)
 
 
 def test_d_methamphetamine(d_methamphetamine, wikidata):
     """Test that d_methamphetamine drug normalizes to correct concept."""
     response = wikidata.search("wikidata:Q191924")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], d_methamphetamine)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], d_methamphetamine)
 
     response = wikidata.search("wiKIdata:Q191924")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], d_methamphetamine)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], d_methamphetamine)
 
     response = wikidata.search("wiKIdata:q191924")
-    assert response["match_type"] == MatchType.CONCEPT_ID
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], d_methamphetamine)
+    assert response.match_type == MatchType.CONCEPT_ID
+    assert len(response.records) == 1
+    compare_records(response.records[0], d_methamphetamine)
 
     response = wikidata.search("D-methamphetamine")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], d_methamphetamine)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], d_methamphetamine)
 
     response = wikidata.search("d-methamphetamine")
-    assert response["match_type"] == MatchType.LABEL
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], d_methamphetamine)
+    assert response.match_type == MatchType.LABEL
+    assert len(response.records) == 1
+    compare_records(response.records[0], d_methamphetamine)
 
     response = wikidata.search("rxcui:6816")
-    assert response["match_type"] == MatchType.XREF
-    assert len(response["records"]) == 1
-    compare_records(response["records"][0], d_methamphetamine)
+    assert response.match_type == MatchType.XREF
+    assert len(response.records) == 1
+    compare_records(response.records[0], d_methamphetamine)
 
 
 def test_case_no_match(wikidata):
     """Test that a term normalizes to NO match."""
     response = wikidata.search("cisplati")
-    assert response["match_type"] == MatchType.NO_MATCH
-    assert len(response["records"]) == 0
+    assert response.match_type == MatchType.NO_MATCH
+    assert len(response.records) == 0
 
     # Test white space in between label
     response = wikidata.search("Interferon alfacon - 1")
-    assert response["match_type"] == MatchType.NO_MATCH
+    assert response.match_type == MatchType.NO_MATCH
 
     # Test empty query
     response = wikidata.search("")
-    assert response["match_type"] == MatchType.NO_MATCH
-    assert len(response["records"]) == 0
+    assert response.match_type == MatchType.NO_MATCH
+    assert len(response.records) == 0
 
 
 def test_meta_info(wikidata):
     """Test that the meta field is correct."""
     response = wikidata.search("cisplatin")
-    assert response["source_meta_"]["data_license"] == "CC0 1.0"
-    assert response["source_meta_"]["data_license_url"] == \
+    assert response.source_meta_.data_license == "CC0 1.0"
+    assert response.source_meta_.data_license_url == \
            "https://creativecommons.org/publicdomain/zero/1.0/"
-    assert isodate.parse_date(response["source_meta_"]["version"])
-    assert response["source_meta_"]["data_url"] is None
-    assert not response["source_meta_"]["rdp_url"]
-    assert response["source_meta_"]["data_license_attributes"] == {
+    assert isodate.parse_date(response.source_meta_.version)
+    assert response.source_meta_.data_url is None
+    assert not response.source_meta_.rdp_url
+    assert response.source_meta_.data_license_attributes == {
         "non_commercial": False,
         "share_alike": False,
         "attribution": False