Saltar al contenido

Compilación y Expression

Las funciones de compilación analizan una expresión FHIRPath una sola vez y retornan un objeto Expression que puede ser evaluado múltiples veces contra diferentes recursos. Este es el patrón “compilar una vez, evaluar muchas” y ofrece el mejor rendimiento para rutas críticas.

Compile

Analiza una cadena de expresión FHIRPath y retorna una Expression compilada. Retorna un error si la expresión es sintácticamente inválida.

func Compile(expr string) (*Expression, error)

Parámetros:

NombreTipoDescripción
exprstringUna expresión FHIRPath a compilar

Retorna:

TipoDescripción
*ExpressionUn objeto de expresión compilado y reutilizable
errorNo nulo si la expresión tiene errores de sintaxis

Ejemplo:

expr, err := fhirpath.Compile("Patient.name.where(use = 'official').family")
if err != nil {
    log.Fatalf("invalid expression: %v", err)
}

// Use expr.Evaluate() against many resources
for _, patient := range patients {
    result, err := expr.Evaluate(patient)
    if err != nil {
        log.Printf("evaluation error: %v", err)
        continue
    }
    fmt.Println(result)
}

MustCompile

Similar a Compile, pero genera un panic en caso de error. Ideal para variables a nivel de paquete o inicialización donde una expresión incorrecta es un error de programación.

func MustCompile(expr string) *Expression

Parámetros:

NombreTipoDescripción
exprstringUna expresión FHIRPath a compilar

Retorna:

TipoDescripción
*ExpressionUn objeto de expresión compilado y reutilizable

Genera panic si la expresión es sintácticamente inválida.

Ejemplo:

// Package-level compiled expressions -- compiled once at startup.
var (
    exprFamilyName = fhirpath.MustCompile("Patient.name.family")
    exprBirthDate  = fhirpath.MustCompile("Patient.birthDate")
    exprActive     = fhirpath.MustCompile("Patient.active")
)

func getPatientInfo(resource []byte) (string, error) {
    result, err := exprFamilyName.Evaluate(resource)
    if err != nil {
        return "", err
    }
    if first, ok := result.First(); ok {
        return first.String(), nil
    }
    return "", nil
}

Tipo Expression

Expression representa una expresión FHIRPath compilada. Contiene el AST (árbol de sintaxis abstracta) analizado y puede ser evaluada contra cualquier recurso FHIR®.

type Expression struct {
    // unexported fields
}

Expression.Evaluate

Ejecuta la expresión compilada contra un recurso FHIR® en formato JSON.

func (e *Expression) Evaluate(resource []byte) (Collection, error)

Parámetros:

NombreTipoDescripción
resource[]byteBytes JSON crudos de un recurso FHIR®

Retorna:

TipoDescripción
CollectionEl resultado de la evaluación
errorNo nulo si la evaluación falla

Ejemplo:

expr := fhirpath.MustCompile("Patient.telecom.where(system = 'phone').value")

patient := []byte(`{
    "resourceType": "Patient",
    "telecom": [
        {"system": "phone", "value": "555-0100"},
        {"system": "email", "value": "john@example.com"}
    ]
}`)

result, err := expr.Evaluate(patient)
if err != nil {
    log.Fatal(err)
}
fmt.Println(result) // [555-0100]

Expression.EvaluateWithContext

Ejecuta la expresión con un contexto de evaluación personalizado. Este es un método de nivel inferior que otorga control total sobre el entorno de evaluación.

func (e *Expression) EvaluateWithContext(ctx *eval.Context) (Collection, error)

Parámetros:

NombreTipoDescripción
ctx*eval.ContextUn contexto de evaluación creado por eval.NewContext

Retorna:

TipoDescripción
CollectionEl resultado de la evaluación
errorNo nulo si la evaluación falla

Este método está destinado para casos de uso avanzados donde se necesita acceso directo al contexto de evaluación interno (por ejemplo, establecer variables o límites a un nivel inferior). Para la mayoría de los casos, es preferible utilizar EvaluateWithOptions.


Expression.EvaluateWithOptions

Ejecuta la expresión contra un recurso JSON con opciones configurables. Las opciones se aplican utilizando el patrón de opciones funcionales.

func (e *Expression) EvaluateWithOptions(resource []byte, opts ...EvalOption) (Collection, error)

Parámetros:

NombreTipoDescripción
resource[]byteBytes JSON crudos de un recurso FHIR®
opts...EvalOptionCero o más opciones funcionales

Retorna:

TipoDescripción
CollectionEl resultado de la evaluación
errorNo nulo si la evaluación falla

Cuando no se proporcionan opciones, se utilizan los valores de DefaultOptions() (timeout de 5 segundos, profundidad máxima 100, tamaño máximo de colección 10000).

Ejemplo:

expr := fhirpath.MustCompile("Patient.name.family")

result, err := expr.EvaluateWithOptions(patient,
    fhirpath.WithTimeout(2*time.Second),
    fhirpath.WithMaxDepth(50),
)
if err != nil {
    log.Fatal(err)
}
fmt.Println(result)

Consulte Opciones de Evaluación para la lista completa de opciones disponibles.


Expression.String

Retorna la cadena de expresión FHIRPath original que fue compilada.

func (e *Expression) String() string

Retorna:

TipoDescripción
stringEl texto fuente de la expresión original

Ejemplo:

expr := fhirpath.MustCompile("Patient.name.family")
fmt.Println(expr.String()) // Patient.name.family

Compilar Una Vez, Evaluar Muchas

El patrón recomendado para código de producción es compilar las expresiones en el momento de inicialización del paquete y reutilizarlas durante toda la vida de la aplicación:

package patient

import "github.com/gofhir/fhirpath"

// Compiled once when the package loads.
var (
    nameExpr   = fhirpath.MustCompile("Patient.name.where(use = 'official').family")
    phoneExpr  = fhirpath.MustCompile("Patient.telecom.where(system = 'phone').value")
    activeExpr = fhirpath.MustCompile("Patient.active")
)

// GetOfficialName evaluates the pre-compiled expression against any Patient resource.
func GetOfficialName(patient []byte) (string, error) {
    result, err := nameExpr.Evaluate(patient)
    if err != nil {
        return "", err
    }
    if first, ok := result.First(); ok {
        return first.String(), nil
    }
    return "", nil
}

// GetPhoneNumbers returns all phone numbers for a Patient.
func GetPhoneNumbers(patient []byte) ([]string, error) {
    result, err := phoneExpr.Evaluate(patient)
    if err != nil {
        return nil, err
    }
    phones := make([]string, 0, result.Count())
    for _, v := range result {
        phones = append(phones, v.String())
    }
    return phones, nil
}

Esto evita la sobrecarga de analizar y compilar la expresión en cada llamada, lo cual es especialmente importante en handlers de solicitudes, pipelines de datos y en cualquier lugar donde las expresiones se evalúen con alta frecuencia.

Última actualización