Skip to content

Commit

Permalink
make sure we can send limit and offset when querying.
Browse files Browse the repository at this point in the history
list the diagnostic reports in the dropdown for filtering.
  • Loading branch information
AnalogJ committed Oct 2, 2023
1 parent c258ab4 commit 6d831f6
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 23 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
.idea/**/tasks.xml
.idea/**/dictionaries
.idea/**/shelf
.idea/dataSources.xml

# Sensitive or high-churn files
.idea/**/dataSources/
Expand Down
52 changes: 33 additions & 19 deletions backend/pkg/database/sqlite_repository_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,20 @@ const (

const TABLE_ALIAS = "fhir"

//Allows users to use SearchParameters to query resources
// Allows users to use SearchParameters to query resources
// Can generate simple or complex queries, depending on the SearchParameter type:
//
// eg. Simple
//
//
// eg. Complex
// SELECT fhir.*
// FROM fhir_observation as fhir, json_each(fhir.code) as codeJson
// WHERE (
//
// (codeJson.value ->> '$.code' = "29463-7" AND codeJson.value ->> '$.system' = "http://loinc.org")
// OR (codeJson.value ->> '$.code' = "3141-9" AND codeJson.value ->> '$.system' = "http://loinc.org")
// OR (codeJson.value ->> '$.code' = "27113001" AND codeJson.value ->> '$.system' = "http://snomed.info/sct")
//
// )
// AND (user_id = "6efcd7c5-3f29-4f0d-926d-a66ff68bbfc2")
// GROUP BY `fhir`.`id`
Expand Down Expand Up @@ -142,7 +143,7 @@ func (sr *SqliteRepository) sqlQueryResources(ctx context.Context, query models.
//defaults
selectClauses := []string{fmt.Sprintf("%s.*", TABLE_ALIAS)}
groupClause := fmt.Sprintf("%s.id", TABLE_ALIAS)
orderClause := fmt.Sprintf("%s.sort_date ASC", TABLE_ALIAS)
orderClause := fmt.Sprintf("%s.sort_date DESC", TABLE_ALIAS)
if query.Aggregations != nil {

//Handle Aggregations
Expand Down Expand Up @@ -210,12 +211,21 @@ func (sr *SqliteRepository) sqlQueryResources(ctx context.Context, query models.
fromClauses = lo.Uniq(fromClauses)
fromClauses = lo.Compact(fromClauses)

return sr.GormClient.WithContext(ctx).
fluentQuery := sr.GormClient.WithContext(ctx).
Select(strings.Join(selectClauses, ", ")).
Where(strings.Join(whereClauses, " AND "), whereNamedParameters).
Group(groupClause).
Order(orderClause).
Table(strings.Join(fromClauses, ", ")), nil
Order(orderClause)

//add limit and offset clauses if present
if query.Limit != nil {
fluentQuery = fluentQuery.Limit(*query.Limit)
}
if query.Offset != nil {
fluentQuery = fluentQuery.Offset(*query.Offset)
}

return fluentQuery.Table(strings.Join(fromClauses, ", ")), nil
}

/// INTERNAL functionality. These functions are exported for testing, but are not available in the Interface
Expand All @@ -227,14 +237,17 @@ type SearchParameter struct {
Modifier string
}

//Lists in the SearchParameterValueOperatorTree are AND'd together, and items within each SearchParameterValueOperatorTree list are OR'd together
//For example, the following would be AND'd together, and then OR'd with the next SearchParameterValueOperatorTree
// {
// {SearchParameterValue{Value: "foo"}, SearchParameterValue{Value: "bar"}}
// {SearchParameterValue{Value: "baz"}},
// }
//This would result in the following SQL:
// (value = "foo" OR value = "bar") AND (value = "baz")
// Lists in the SearchParameterValueOperatorTree are AND'd together, and items within each SearchParameterValueOperatorTree list are OR'd together
// For example, the following would be AND'd together, and then OR'd with the next SearchParameterValueOperatorTree
//
// {
// {SearchParameterValue{Value: "foo"}, SearchParameterValue{Value: "bar"}}
// {SearchParameterValue{Value: "baz"}},
// }
//
// This would result in the following SQL:
//
// (value = "foo" OR value = "bar") AND (value = "baz")
type SearchParameterValueOperatorTree [][]SearchParameterValue

type SearchParameterValue struct {
Expand All @@ -243,7 +256,7 @@ type SearchParameterValue struct {
SecondaryValues map[string]interface{}
}

//SearchParameters are made up of parameter names and modifiers. For example, "name" and "name:exact" are both valid search parameters
// SearchParameters are made up of parameter names and modifiers. For example, "name" and "name:exact" are both valid search parameters
// This function will parse the searchCodeWithModifier and return the SearchParameter
func ProcessSearchParameter(searchCodeWithModifier string, searchParamTypeLookup map[string]string) (SearchParameter, error) {
searchParameter := SearchParameter{}
Expand Down Expand Up @@ -284,8 +297,9 @@ func ProcessSearchParameter(searchCodeWithModifier string, searchParamTypeLookup
// top level is AND'd together, and each item within the lists are OR'd together
//
// For example, searchParamCodeValueOrValuesWithPrefix may be:
// "code": "29463-7,3141-9,27113001"
// "code": ["le29463-7", "gt3141-9", "27113001"]
//
// "code": "29463-7,3141-9,27113001"
// "code": ["le29463-7", "gt3141-9", "27113001"]
func ProcessSearchParameterValueIntoOperatorTree(searchParameter SearchParameter, searchParamCodeValueOrValuesWithPrefix interface{}) (SearchParameterValueOperatorTree, error) {

searchParamCodeValuesWithPrefix := []string{}
Expand Down Expand Up @@ -416,7 +430,7 @@ func NamedParameterWithSuffix(parameterName string, suffix string) string {
return fmt.Sprintf("%s_%s", parameterName, suffix)
}

//SearchCodeToWhereClause converts a searchCode and searchCodeValue to a where clause and a map of named parameters
// SearchCodeToWhereClause converts a searchCode and searchCodeValue to a where clause and a map of named parameters
func SearchCodeToWhereClause(searchParam SearchParameter, searchParamValue SearchParameterValue, namedParameterSuffix string) (string, map[string]interface{}, error) {

//add named parameters to the lookup map. Basically, this is a map of all the named parameters that will be used in the where clause we're generating
Expand Down Expand Up @@ -575,7 +589,7 @@ func AggregationParameterToClause(aggParameter SearchParameter) string {
}
}

//ProcessAggregationParameter processes the aggregation parameters which are fields with optional properties:
// ProcessAggregationParameter processes the aggregation parameters which are fields with optional properties:
// Fields that are primitive types (number, uri) must not have any property specified:
// eg. `probability`
//
Expand Down
8 changes: 8 additions & 0 deletions backend/pkg/models/query_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ type QueryResource struct {
Select []string `json:"select"`
From string `json:"from"`
Where map[string]interface{} `json:"where"`
Limit *int `json:"limit,omitempty"`
Offset *int `json:"offset,omitempty"`

//aggregation fields
Aggregations *QueryResourceAggregations `json:"aggregations"`
Expand Down Expand Up @@ -56,7 +58,13 @@ func (q *QueryResource) Validate() error {
if strings.Contains(q.Aggregations.OrderBy, " ") {
return fmt.Errorf("order_by cannot have spaces (or aliases)")
}
}

if q.Limit != nil && *q.Limit < 0 {
return fmt.Errorf("'limit' must be greater than or equal to zero")
}
if q.Offset != nil && *q.Offset < 0 {
return fmt.Errorf("'offset' must be greater than or equal to zero")
}

return nil
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/app/models/widget/dashboard-widget-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ export class DashboardWidgetQuery {
select: string[]
from: string
where: {[key: string]: string | string[]}
// limit: number
// offset: number
limit?: number
offset?: number

//https://lodash.com/docs/4.17.15#unionBy
aggregations?: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ <h1 class="az-dashboard-title">Observations</h1>
<div ngbDropdownMenu aria-labelledby="dropdownReports">
<button ngbDropdownItem>All</button>
<button ngbDropdownItem [disabled]="true">-----</button>
<button ngbDropdownItem>Report 1</button>
<button ngbDropdownItem>Report 2</button>
<button *ngFor="let diagnosticReport of diagnosticReports" ngbDropdownItem>{{diagnosticReport?.sort_title}} [{{diagnosticReport?.sort_date | amDateFormat: 'LL'}}]</button>
</div>
</div>
<div ngbDropdown class="d-inline-block float-right">
Expand Down
27 changes: 27 additions & 0 deletions frontend/src/app/pages/report-labs/report-labs.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,39 @@ export class ReportLabsComponent implements OnInit {

isEmptyReport = false

diagnosticReports: ResourceFhir[] = []

constructor(
private fastenApi: FastenApiService,
) { }

ngOnInit(): void {
this.loading = true

this.fastenApi.queryResources({
select: ["*"],
from: "DiagnosticReport",
where: {
"category": "http://terminology.hl7.org/CodeSystem/v2-0074|LAB",
},
limit: 5,
}).subscribe(results => {
this.diagnosticReports = results.data
console.log("ALL DIAGNOSTIC REPORTS", results)
})

this.fastenApi.queryResources({
select: ["*"],
from: "Observation",
where: {},
aggregations: {
order_by: "code:code"
}
}).subscribe(results => {
console.log("OBSERVATIONS GROUPED", results)
})


this.fastenApi.getResources("Observation").subscribe(results => {
this.loading = false
results = results || []
Expand Down

0 comments on commit 6d831f6

Please sign in to comment.