Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Custom Queries backend #133

113 changes: 113 additions & 0 deletions query-connector/src/app/database-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
QueryInput,
generateQueryInsertionSql,
generateQueryToValueSetInsertionSql,
CustomUserQuery,
} from "./query-building";
import { UUID } from "crypto";
import {
Expand Down Expand Up @@ -606,6 +607,118 @@ export async function getConditionsData() {
} as const;
}

/**
* Fetches and structures custom user queries from the database.
* Executes a SQL query to join query information with related valueset and concept data,
* and then structures the result into a nested JSON format. The JSON format groups
* valuesets and their nested concepts under each query.
* @returns customUserQueriesArray - An array of objects where each object represents a query.
* Each query object includes:
* - query_id: The unique identifier for the query.
* - query_name: The name of the query.
* - valuesets: An array of ValueSet objects
* - concepts: An array of Concept objects
*/
export async function getCustomQueries(): Promise<CustomUserQuery[]> {
const query = `
SELECT
q.id AS query_id,
q.query_name,
vc.valueset_id AS valueSetId,
vc.version AS valueSetVersion,
vc.valueset_name AS valueSetName,
vc.author,
vc.system,
vc.ersd_concept_type AS ersdConceptType,
vc.dibbs_concept_type AS dibbsConceptType,
vc.valueset_include AS includeValueSet,
vc.code,
vc.display,
qic."include" AS concept_include
FROM
query q
LEFT JOIN query_to_valueset qtv ON q.id = qtv.query_id
LEFT JOIN query_included_concepts qic ON qic.query_by_valueset_id = qtv.id
LEFT JOIN (
SELECT
v.id AS valueset_id,
v.version,
v.name AS valueset_name,
v.author,
c.code_system AS system,
v.type AS ersd_concept_type,
v.dibbs_concept_type,
true AS valueset_include,
c.code,
c.display
FROM
valuesets v
LEFT JOIN valueset_to_concept vtc ON vtc.valueset_id = v.id
LEFT JOIN concepts c ON c.id = vtc.concept_id
) vc ON vc.valueset_id = qtv.valueset_id
WHERE q.author = 'DIBBs';
`;
// TODO: this will eventually need to take into account user permissions and specific authors
// We might also be able to take advantage of the `query_name` var to avoid joining valuesets/conc

const results = await dbClient.query(query);
const formattedData: { [key: string]: CustomUserQuery } = {};

results.rows.forEach((row) => {
const {
query_id,
query_name,
valueSetId,
valueSetVersion,
valueSetName,
author,
system,
ersdConceptType,
dibbsConceptType,
includeValueSet,
code,
display,
concept_include,
} = row;

// Initialize query structure if it doesn't exist
if (!formattedData[query_id]) {
formattedData[query_id] = {
query_id,
query_name,
valuesets: [],
};
}

// Check if the valueSetId already exists in the valuesets array
let valueset = formattedData[query_id].valuesets.find(
(v) => v.valueSetId === valueSetId,
);

// If valueSetId doesn't exist, add it
if (!valueset) {
valueset = {
valueSetId,
valueSetVersion,
valueSetName,
author,
system,
ersdConceptType,
dibbsConceptType,
includeValueSet,
concepts: [],
};
formattedData[query_id].valuesets.push(valueset);
}

// Add concept data to the concepts array
const concept: Concept = { code, display, include: concept_include };
valueset.concepts.push(concept);
});

return Object.values(formattedData);
}

/**
* Checks the database to see if data has been loaded into the valuesets table by
* estmating the number of rows in the table. If the estimated count is greater than
Expand Down
7 changes: 7 additions & 0 deletions query-connector/src/app/query-building.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,10 @@ export function generateQueryToValueSetInsertionSql(
});
return joinInsertionSqlArray;
}

// Type definition for CustomUserQueries
export interface CustomUserQuery {
query_id: string;
query_name: string;
valuesets: ValueSet[];
}
Loading