Skip to main content

GraphQL service for exposing OMOP CDM records.

Exported scripts

  • load-omop-cdm-db-records

  • run-omop-cdm-graphql-app

Step 1 - Create Python virtual environment

python3 -m venv venv

Step 2 - Activate Python virtual environment

source venv/bin/activate

Step 3 - Install

pip install omop-cdm-graphql

Step 4 - Update the configuration file

---
port: 8081
url: http://localhost
database_file: /tmp/omop-cdm-graphql/omop-cdm-v1.db

Step 5 - Copy configuration file to launch directory

cp venv/lib/python3.10/site-packages/omop_cdm_graphql/conf/config.yaml .

Step 6 - Load the database

Run the loader to load mock records.

load-omop-cdm-db-records

Step 7 - Run the app

run-omop-cdm-graphql-app

Step 8 - Open browser

http://localhost:8080/graphql

Step 9 - Execute queries

Query 1 - Retrieve person 1

query {
  person(personId: 1) {
    personId
    genderConceptId
    birthDatetime
    observations {
      observationId
      observationConceptId
      observationDate
    }
    conditions {
      conditionOccurrenceId
      conditionConceptId
      conditionStartDate
    }
  }
}

Result:

{
  "data": {
    "person": {
      "personId": 1,
      "genderConceptId": 8507,
      "birthDatetime": "1990-01-01T00:00:00",
      "observations": [
        {
          "observationId": 1,
          "observationConceptId": 123,
          "observationDate": "2023-01-01T00:00:00"
        },
        {
          "observationId": 7,
          "observationConceptId": 129,
          "observationDate": "2023-07-10T00:00:00"
        }
      ],
      "conditions": [
        {
          "conditionOccurrenceId": 1,
          "conditionConceptId": 456,
          "conditionStartDate": "2023-02-01T00:00:00"
        },
        {
          "conditionOccurrenceId": 7,
          "conditionConceptId": 462,
          "conditionStartDate": "2023-08-20T00:00:00"
        }
      ]
    }
  }
}

Query 2 - Retrieve all persons

query {
  allPersons {
    personId
    genderConceptId
    birthDatetime
  }
}

Result:

{
  "data": {
    "allPersons": [
      {
        "personId": 1,
        "genderConceptId": 8507,
        "birthDatetime": "1990-01-01T00:00:00"
      },
      {
        "personId": 2,
        "genderConceptId": 8532,
        "birthDatetime": "1985-05-15T00:00:00"
      },
      {
        "personId": 3,
        "genderConceptId": 8507,
        "birthDatetime": "1978-03-22T00:00:00"
      },
      {
        "personId": 4,
        "genderConceptId": 8532,
        "birthDatetime": "1995-07-10T00:00:00"
      },
      {
        "personId": 5,
        "genderConceptId": 8507,
        "birthDatetime": "1982-11-30T00:00:00"
      },
      {
        "personId": 6,
        "genderConceptId": 8532,
        "birthDatetime": "2000-04-15T00:00:00"
      }
    ]
  }
}

Query 3 - Filter Persons by Gender

Purpose: Shows how GraphQL lets clients filter data without needing a separate endpoint.

query {
  personsByGender(genderConceptId: 8532) {
    personId
    birthDatetime
    observations {
      observationId
      observationDate
    }
  }
}

Returns only female persons (gender_concept_id = 8532) with their observations. Client specifies exactly what fields they want (e.g., skipping conditions or genderConceptId), avoiding over-fetching.

Result:

{
  "data": {
    "personsByGender": [
      {
        "personId": 2,
        "birthDatetime": "1985-05-15T00:00:00",
        "observations": [
          {
            "observationId": 2,
            "observationDate": "2023-03-15T00:00:00"
          }
        ]
      },
      {
        "personId": 4,
        "birthDatetime": "1995-07-10T00:00:00",
        "observations": [
          {
            "observationId": 4,
            "observationDate": "2023-05-20T00:00:00"
          }
        ]
      },
      {
        "personId": 6,
        "birthDatetime": "2000-04-15T00:00:00",
        "observations": [
          {
            "observationId": 6,
            "observationDate": "2023-06-01T00:00:00"
          }
        ]
      }
    ]
  }
}

Query 4 - Recent Observations

Purpose: Demonstrates time-based filtering and standalone access to related entities.

query {
  recentObservations(afterDate: "2023-03-01") {
    observationId
    observationConceptId
    observationDate
  }
}

Returns observations after March 1, 2023 (e.g., observation IDs 2, 4, 6, 7). No need to fetch persons first; GraphQL lets you query related data directly, reducing round trips.

Result:

{
  "data": {
    "recentObservations": [
      {
        "observationId": 2,
        "observationConceptId": 124,
        "observationDate": "2023-03-15T00:00:00"
      },
      {
        "observationId": 4,
        "observationConceptId": 126,
        "observationDate": "2023-05-20T00:00:00"
      },
      {
        "observationId": 6,
        "observationConceptId": 128,
        "observationDate": "2023-06-01T00:00:00"
      },
      {
        "observationId": 7,
        "observationConceptId": 129,
        "observationDate": "2023-07-10T00:00:00"
      }
    ]
  }
}

Query 5 - Persons with a Specific Condition

Purpose: Highlights nested relationship traversal and conditional filtering.

query {
  personsWithCondition(conditionConceptId: 456) {
    personId
    genderConceptId
    conditions {
      conditionOccurrenceId
      conditionStartDate
    }
    observations {
      observationId
    }
  }
}

Returns persons with condition_concept_id 456 (just person 1) and their conditions and observations. Combines filtering with flexible field selection across relationships in one request—impossible in REST without multiple calls or a custom endpoint.

Query - Nested Data with Selective Fields

Purpose: Shows how clients can pick and choose fields across relationships.

query {
  allPersons {
    personId
    birthDatetime
    observations {
      observationDate
    }
    conditions {
      conditionConceptId
    }
  }
}

Returns all 6 persons with only their birth dates, observation dates, and condition concept IDs. Avoids over-fetching unused fields (e.g., gender_concept_id, observation_id) and simplifies frontend logic—no need to parse bloated responses.

Results:

{
  "data": {
    "allPersons": [
      {
        "personId": 1,
        "birthDatetime": "1990-01-01T00:00:00",
        "observations": [
          {
            "observationDate": "2023-01-01T00:00:00"
          },
          {
            "observationDate": "2023-07-10T00:00:00"
          }
        ],
        "conditions": [
          {
            "conditionConceptId": 456
          },
          {
            "conditionConceptId": 462
          }
        ]
      },
      {
        "personId": 2,
        "birthDatetime": "1985-05-15T00:00:00",
        "observations": [
          {
            "observationDate": "2023-03-15T00:00:00"
          }
        ],
        "conditions": [
          {
            "conditionConceptId": 457
          }
        ]
      },
      {
        "personId": 3,
        "birthDatetime": "1978-03-22T00:00:00",
        "observations": [
          {
            "observationDate": "2022-12-10T00:00:00"
          }
        ],
        "conditions": [
          {
            "conditionConceptId": 458
          }
        ]
      },
      {
        "personId": 4,
        "birthDatetime": "1995-07-10T00:00:00",
        "observations": [
          {
            "observationDate": "2023-05-20T00:00:00"
          }
        ],
        "conditions": [
          {
            "conditionConceptId": 459
          }
        ]
      },
      {
        "personId": 5,
        "birthDatetime": "1982-11-30T00:00:00",
        "observations": [
          {
            "observationDate": "2023-01-25T00:00:00"
          }
        ],
        "conditions": [
          {
            "conditionConceptId": 460
          }
        ]
      },
      {
        "personId": 6,
        "birthDatetime": "2000-04-15T00:00:00",
        "observations": [
          {
            "observationDate": "2023-06-01T00:00:00"
          }
        ],
        "conditions": [
          {
            "conditionConceptId": 461
          }
        ]
      }
    ]
  }
}

Query - Single Person Deep Dive

Purpose: Demonstrates deep nesting and customization.

query {
  person(personId: 1) {
    personId
    birthDatetime
    observations {
      observationId
      observationConceptId
      observationDate
    }
    conditions {
      conditionOccurrenceId
      conditionConceptId
      conditionStartDate
    }
  }
}

Returns person 1 with all observation and condition details. Replaces multiple REST calls (e.g., /persons/1, /persons/1/observations, /persons/1/conditions) with one precise query.

Result:

{
  "data": {
    "person": {
      "personId": 1,
      "birthDatetime": "1990-01-01T00:00:00",
      "observations": [
        {
          "observationId": 1,
          "observationConceptId": 123,
          "observationDate": "2023-01-01T00:00:00"
        },
        {
          "observationId": 7,
          "observationConceptId": 129,
          "observationDate": "2023-07-10T00:00:00"
        }
      ],
      "conditions": [
        {
          "conditionOccurrenceId": 1,
          "conditionConceptId": 456,
          "conditionStartDate": "2023-02-01T00:00:00"
        },
        {
          "conditionOccurrenceId": 7,
          "conditionConceptId": 462,
          "conditionStartDate": "2023-08-20T00:00:00"
        }
      ]
    }
  }
}

Step 10 - Execute queries via CLI using httpie

Query 1 - Retrieve person 1

http POST http://localhost:8081/graphql query=@examples/query1.graphql

Result:

Query 2 - Retrieve all persons

http POST http://localhost:8081/graphql query=@examples/query2.graphql

Query 3 - Filter Persons by Gender

http POST http://localhost:8081/graphql query=@examples/query3.graphql

Query 4 - Recent Observations

http POST http://localhost:8081/graphql query=@examples/query4.graphql

Query 5 - Persons with a Specific Condition

http POST http://localhost:8081/graphql query=@examples/query5.graphql

Query 6 - Nested Data with Selective Fields

http POST http://localhost:8081/graphql query=@examples/query6.graphql

Query 7 - Single Person Deep Dive

http POST http://localhost:8081/graphql query=@examples/query7.graphql

References

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

omop_cdm_graphql-0.6.0.tar.gz (19.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

omop_cdm_graphql-0.6.0-py2.py3-none-any.whl (13.3 kB view details)

Uploaded Python 2Python 3

File details

Details for the file omop_cdm_graphql-0.6.0.tar.gz.

File metadata

  • Download URL: omop_cdm_graphql-0.6.0.tar.gz
  • Upload date:
  • Size: 19.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.10.12

File hashes

Hashes for omop_cdm_graphql-0.6.0.tar.gz
Algorithm Hash digest
SHA256 ecaf70444096721ab92f19e9284a2edb289678c4751ac874bc81a507033fb58f
MD5 5b38ae3747ed99d6cbd3a132681e7f79
BLAKE2b-256 5c775c35eab98437380e15e5f4f5de6e7c4f3362cc5aead8d31019518db98aec

See more details on using hashes here.

File details

Details for the file omop_cdm_graphql-0.6.0-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for omop_cdm_graphql-0.6.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 2bfdcaacc420c95bc55a4464a7297a8fc74cd87af4b28f5a536ff667b3d98047
MD5 56bc79ac1bf3e8cb4e5b442576485943
BLAKE2b-256 f983d3b23b9a46d82a7db393424801c2859a115ce16e5ce7aba9a3914ffb0079

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.6.0 This release

2 files

0.5.0

2 files

0.4.0

2 files

0.3.0

2 files

0.2.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page