From 798a0b41f54cc6d7b1b36e848f5fffd7a37a80b5 Mon Sep 17 00:00:00 2001 From: "k.siwek@kainos.com" Date: Tue, 7 Jun 2016 15:43:08 +0200 Subject: [PATCH] extension to sort on nested parameters --- src/fhir/meta_pg.coffee | 5 +++ src/fhir/search.litcoffee | 50 ++++++++++++++++++++++++++--- src/fhir/search_common.coffee | 2 +- src/fhir/search_nested.litcoffee | 26 +++++++++++++++ src/fhir/search_reference.litcoffee | 6 +++- src/fhir/search_token.litcoffee | 9 ++++-- 6 files changed, 89 insertions(+), 9 deletions(-) create mode 100644 src/fhir/search_nested.litcoffee diff --git a/src/fhir/meta_pg.coffee b/src/fhir/meta_pg.coffee index 972ea61..a636378 100644 --- a/src/fhir/meta_pg.coffee +++ b/src/fhir/meta_pg.coffee @@ -10,6 +10,11 @@ exports.getter = (plv8, rt, query)-> select: sql.raw('*') from: sql.q(tbl_name) where: {"resource->>'name'": query.name } + else if rt = "SearchParameter" + utils.exec plv8, + select: sql.raw('*') + from: sql.q(tbl_name) + where: {"resource->>'name'": query.name.split(".")[0], "resource->>'base'": query.base} else utils.exec plv8, select: sql.raw('*') diff --git a/src/fhir/search.litcoffee b/src/fhir/search.litcoffee index 2ada774..31e3e60 100644 --- a/src/fhir/search.litcoffee +++ b/src/fhir/search.litcoffee @@ -217,11 +217,20 @@ To build search query we need to if expr.sort ordering = order_hsql(alias, expr.sort) - hsql = - select: ':*' - from: ['$alias', ['$q', "#{namings.table_name(plv8, expr.query)}"], alias] - where: expr.where - order: ordering + if expr.sort && is_nested_order(expr.sort) + nested_order_query = get_nested_order_query(expr, alias) + hsql = + select: nested_order_query.select, + from: nested_order_query.from, + join: nested_order_query.join, + where: nested_order_query.where, + order: ordering + else + hsql = + select: ':*' + from: ['$alias', ['$q', "#{namings.table_name(plv8, expr.query)}"], alias] + where: expr.where + order: ordering if expr.count != null || expr.page != null hsql.limit = expr.count || DEFAULT_RESOURCES_PER_PAGE @@ -271,6 +280,37 @@ implementation based on searchType throw new Error("Search type does not exports order_expression fn: [#{meta.searchType}] #{JSON.stringify(meta)}") h.order_expression(tbl, meta) + is_nested_order = (params)-> + for meta in params.map((x)-> x[1]) + name = meta.name + if name.split(".").length > 1 + return true + return false + + nested_table = (params)-> + for meta in params.map((x)-> x[1]) + name = meta.name + if name.split(".").length > 1 + return name.split(".")[0] + + get_nested_order_query = (expr, alias)-> + nested_table_name = nested_table(expr.sort) + table_name = namings.table_name(plv8, expr.query) + if table_name == "appointment" + { + select: ":#{table_name}.*", + from: ['$raw', "(SELECT split_part((json_array_elements((\"#{table_name}\".resource->'participant')::json)->'actor'->>'reference')::text, '/', 2)::text as subelem_id, \"#{table_name}\".* FROM \"#{table_name}\") AS #{table_name}"], + join: [[["$raw", "#{nested_table_name} AS #{alias}"],["$raw", "#{alias}.id = subelem_id"]]], + where: expr.where + } + else if table_name == "encounter" + { + select: ":#{table_name}.*", + from: ['$alias', ['$q', "#{nested_table_name}"], alias], + join: [["#{table_name}", "#{alias}.id=split_part((\"#{table_name}\".resource->'#{nested_table_name}'->>'reference'), '/', 2)"]], + where: expr.where + } + ### Handling chained parameters diff --git a/src/fhir/search_common.coffee b/src/fhir/search_common.coffee index b7c14a2..c45351c 100644 --- a/src/fhir/search_common.coffee +++ b/src/fhir/search_common.coffee @@ -49,4 +49,4 @@ get_search_functions = (obj) -> } -exports.get_search_functions = get_search_functions \ No newline at end of file +exports.get_search_functions = get_search_functions diff --git a/src/fhir/search_nested.litcoffee b/src/fhir/search_nested.litcoffee new file mode 100644 index 0000000..2bdb6b6 --- /dev/null +++ b/src/fhir/search_nested.litcoffee @@ -0,0 +1,26 @@ +# Search and indexing nested elements + + sql = require('../honey') + lang = require('../lang') + xpath = require('./xpath') + search_common = require('./search_common') + + paths = { + "patient.given" : "\"tbl1\".resource->'name'->0->'given'->0", + "patient.family" : "\"tbl1\".resource->'name'->0->'family'->0", + "patient.birthDate" : "\"tbl1\".resource->'birthDate'", + "practitioner.given" : "\"tbl1\".resource->'name'->0->'given'->0", + "practitioner.family" : "\"tbl1\".resource->'name'->0->'family'->0", + } + + exports.order_expression = (tbl, meta)-> + elem = meta.name + expression = paths[elem] + if meta.operator == "desc" + expression += " DESC" + expression + + exports.order_expression.plv8_signature = + arguments: ['text', 'json'] + returns: 'json' + immutable: true diff --git a/src/fhir/search_reference.litcoffee b/src/fhir/search_reference.litcoffee index 77742dc..120566d 100644 --- a/src/fhir/search_reference.litcoffee +++ b/src/fhir/search_reference.litcoffee @@ -17,6 +17,7 @@ Only equality operator is implemented. xpath = require('./xpath') lang = require('../lang') search_token = require('./search_token') + search_nested = require('./search_nested') TODO = -> throw new Error("TODO") @@ -109,7 +110,10 @@ Only equality operator is implemented. op(tbl, meta, value) exports.order_expression = (tbl, meta)-> - search_token.order_expression(tbl, meta) + if meta.name.split(".").length>1 + search_nested.order_expression(tbl, meta) + else + search_token.order_expression(tbl, meta) exports.index = (plv8, metas)-> meta = metas[0] diff --git a/src/fhir/search_token.litcoffee b/src/fhir/search_token.litcoffee index dab5124..a3675fc 100644 --- a/src/fhir/search_token.litcoffee +++ b/src/fhir/search_token.litcoffee @@ -30,7 +30,7 @@ PostgreSQL implementation is based on arrays support - http://www.postgresql.org 'date' ] - sf = search_common.get_search_functions({extract:'fhir_extract_as_token', sort:'fhir_sort_as_token',SUPPORTED_TYPES:SUPPORTED_TYPES}) + sf = search_common.get_search_functions({extract:'fhir_extract_as_token', sort:'fhir_sort_as_token', SUPPORTED_TYPES:SUPPORTED_TYPES}) extract_expr = sf.extract_expr exports.order_expression = sf.order_expression @@ -74,12 +74,17 @@ PostgreSQL implementation is based on arrays support - http://www.postgresql.org else if element_type == 'Reference' for ref in data res.push(ref.reference) + else if element_type == 'ReferenceUid' + for ref in data + res.push(ref.reference.split("/")[1]) + else if element_type == 'ReferenceUidTxt' + for ref in data + res = ref.reference.split("/")[1] else throw new Error("fhir_extract_as_token: Not implemented for #{element_type}") # console.log("!!!! #{resource.id} #{JSON.stringify(data)} #{JSON.stringify(path)} => #{JSON.stringify(res)} (#{element_type})") - if res.length == 0 ['$NULL'] else