查找

文章
· 一月 6 阅读大约需 1 分钟

Incluindo ou removendo esses hífens (-) na sua operação FHIR personalizada

Muitas vezes, ao trabalhar com dados FHIR, por exemplo com o IRIS For Health, você vai achar útil criar uma operação FHIR personalizada. O padrão FHIR já vem com um conjunto de operações definidas (como $everything), mas uma operação personalizada é útil quando você precisa criar funcionalidades extras que vão além do conjunto de operações padrão do FHIR. A documentação guia você passo a passo (embora este comentário possa ser útil para quem está começando). Uma coisa que eu destacaria, puramente por propósitos estéticos, é como nomear sintaticamente sua função de forma que você possa chamá-la usando hífens. A documentação realmente explica isso:

Se a sua operação contiver um hífen (-), basta remover o hífen do nome do método. Por exemplo, se a operação em todo o sistema for $my-operation, nomeie o método como FHIRSystemOpMyOperation.

Embora eu apenas queira deixar isso mais explícito aqui:

Para uma operação sem hífen, por exemplo $thisismyoperation, nomeie seu método como FHIRSystemOpThisismyoperation (sim, a letra "T" de "This" deve estar maiúscula).

 

Se você quiser, em vez disso, que sua operação seja $this-is-my-operation, seu método deve ser FHIRSystemOpThisIsMyOperation. (A letra maiúscula indica que deve haver um hífen antes dela).

讨论 (0)1
登录或注册以继续
文章
· 一月 6 阅读大约需 2 分钟

Encontre e Exiba Valores a partir de textos

A utilidade retorna os valores desejados do texto e exibe múltiplos valores, se existirem, com base na string de início e na string de término.

Class Test.Utility.FunctionSet Extends %RegisteredObject
{

/// W !,##class(Test.Utility.FunctionSet).ExtractValues("Some random text VALUE=12345; some other VALUE=2345; more text VALUE=345678;","VALUE=",";")
 

ClassMethod ExtractValues(text As %String, startStr As %String, endStr As %String) As %String
{    //Initialize Valriables
   Set values = ""
   Set start = 1
   
   While start '= 0 {
 Set start = $FIND(text, startStr, start)
 IF start = 0 QUIT }
     Set end = $FIND(text, endStr, start)
     IF end = 0 QUIT }
    //S value = $E(text, start, end-2)
     value = $E(text, start, end-$L(endStr)-1)
     IF values '= "" {
  Set values = values _" "_value   
     }Else {
  values = value   
     }
     start = end
   }
    values
} }

Output:

W !,##class(Test.Utility.FunctionSet).ExtractValues("Some random text VALUE=12345; some other VALUE=2345; more text VALUE=345678;","VALUE=",";")

12345 2345 345678

讨论 (0)1
登录或注册以继续
文章
· 一月 6 阅读大约需 1 分钟

Usando IRIS como una base de datos vectorial

Las capacidades integradas de búsqueda vectorial de InterSystems IRIS nos permiten buscar datos no estructurados y semiestructurados. Los datos se convierten en vectores (también llamados “embeddings”) y luego se almacenan e indexan en InterSystems IRIS para búsqueda semántica, generación aumentada por recuperación (RAG), análisis de texto, motores de recomendación y otros casos de uso.

Esta es una demostración sencilla de IRIS siendo utilizado como una base de datos vectorial y para búsquedas por similitud en IRIS.

Requisitos previos:

  1. Python
  2. InterSystems IRIS for Health - ya que se usará como la base de datos vectorial

Repositorio: https://github.com/piyushisc/vectorsearchusingiris

Pasos a seguir:

  1. Clonar el repositorio.
  2. Abrir VS Code, conectarse a la instancia y espacio de nombres deseados de IRIS y compilar las clases.
  3. Abrir la terminal de IRIS e invocar el comando: do ##class(vectors.vectorstore).InsertEmbeddings(), Esto lee el texto del archivo text.txt genera los embeddings y los almacena en IRIS.
  4. Invocar el comando: do ##class(vectors.vectorstore).VectorSearch("search_terms") con las palabras deseadas para realizar la búsqueda por similitud. IRIS devolverá los tres resultados más cercanos:alt text
讨论 (0)1
登录或注册以继续
文章
· 一月 6 阅读大约需 2 分钟

Causa e solução do erro <SLMSPAN> ao eliminar uma global

Rubrica de FAQ da InterSystems

Se você tentar eliminar uma global que está mapeada no nível de subscrito a partir do nó raiz, você receberá um erro e ela não será excluída. Isso ocorre porque o comando kill para globais mapeadas no nível de subscrito não pode ser usado atravessando mapeamentos.

// Suppose subscript-mapped globals exist in different databases, as shown below:
^TEST(A*~K*) -> database A
^TEST(L*~Z*) -> database B

// Trying to kill from the top level will result in a <SLMSPAN> error.
NAMESPACE>Kill ^TEST
<SLMSPAN> <- This error is output.

Para excluir apenas a global no namespace (banco de dados) atual, use o seguinte:

NAMESPACE>Kill ^["^^."]TEST

Globais mapeadas no nível de subscrito devem ser movidas para o banco de dados e eliminadas diretamente.

Para alternar para o banco de dados, use o seguinte:

zn "^^c:\intersystems\iris\mgr\user"
or
set $namespace="^^c:\intersystems\iris\mgr\user"

Ao importar globais com $System.OBJ.Load, o comportamento padrão é eliminar as globais antes de importá-las.
Como resultado, se as globais de destino estiverem mapeadas no nível de subscrito, ocorre um erro <SLMSPAN>. Nesse caso, especifique o parâmetro /mergeglobal como segundo argumento de $System.OBJ.Load, conforme abaixo, para evitar a eliminação prévia:

Set sc = $System.OBJ.Load(path," /mergeglobal",.errors)

enlightened [Referências]
Mapped globals cannot be exported.
How do I compile mapped classes and routines?

讨论 (0)1
登录或注册以继续
文章
· 一月 6 阅读大约需 3 分钟

Gerando JWT sem acesso aos certificados/chaves x509 do sistema

Se você quiser gerar um JWT a partir de um certificado/chave x509, qualquer operação (inclusive leitura) em %SYS.X509Credentials exige permissão U no recurso %Admin_Secure. O %Admin_Secure é necessário porque %SYS.X509Credentials é persistente e foi implementado dessa forma para impedir que todos os usuários tenham acesso às chaves privadas.

Se o recurso %Admin_Secure não estiver disponível em tempo de execução, você pode usar a seguinte alternativa.

Ao revisar o código de geração de JWT, descobri que o código de JWT utiliza %SYS.X509Credentials apenas como fonte de dados em tempo de execução para PrivateKey, PrivateKeyPassword, e Certificate. Como alternativa, você pode usar uma implementação não persistente da interface X.509 em tempo de execução, expondo apenas essas propriedades.Se você estiver usando interoperabilidade, o certificado/chave privada (Cert/PK) pode ser armazenado em credenciais para acesso seguro.

Class User.X509 Extends %RegisteredObject
{

Property PrivateKey As %VarString;
Property PrivateKeyPassword As %String;
Property Certificate As %VarString;
Property HasPrivateKey As %Boolean [ InitialExpression = {$$$YES} ];
ClassMethod GetX509() As User.X509
{
    set x509 = ..%New()
    set x509.PrivateKey = ..Key()
    set x509.Certificate = ..Cert()
    quit x509
}

/// Get X509 object from credential.
/// Username is a Cert, Password is a Private Key
ClassMethod GetX509FromCredential(credential) As User.X509
{
    set credentialObj = ##class(Ens.Config.Credentials).%OpenId(credential,,.sc)
    throw:$$$ISERR(sc) ##class(%Exception.StatusException).ThrowIfInterrupt(sc)
    
    set x509 = ..%New()
    set x509.PrivateKey = credentialObj.Password
    set x509.Certificate = credentialObj.Username
    quit x509
}

ClassMethod Key()
{
    q "-----BEGIN RSA PRIVATE KEY-----"_$C(13,10)
    _"YOUR_TEST_KEY"_$C(13,10)
    _"-----END RSA PRIVATE KEY-----"
}

ClassMethod Cert() As %VarString
{
    q "-----BEGIN CERTIFICATE-----"_$C(13,10)
    _"YOUR_TEST_CERT"_$C(13,10)
    _"-----END CERTIFICATE-----"
}

}

E você pode gerar o JWT da seguinte forma:

ClassMethod JWT() As %Status
{
    Set sc = $$$OK
    //Set x509 = ##class(%SYS.X509Credentials).GetByAlias("TempKeyPair")
    Set x509 = ##class(User.X509).GetX509()
    
    Set algorithm ="RS256"
    Set header = {"alg": (algorithm), "typ": "JWT"}
    Set claims= {"Key": "Value" }
    
    #; create JWK
    Set sc = ##class(%Net.JSON.JWK).CreateX509(algorithm,x509,.privateJWK)
    
    If $$$ISERR(sc) {
        Write $SYSTEM.OBJ.DisplayError(sc)
    }

    #; Create JWKS
    Set sc = ##class(%Net.JSON.JWKS).PutJWK(privateJWK,.privateJWKS)
    
    If $$$ISERR(sc) {
        Write $SYSTEM.OBJ.DisplayError(sc)
    }

    Set sc = ##Class(%Net.JSON.JWT).Create(header,,claims,privateJWKS,,.pJWT)
    
    If $$$ISERR(sc) {
        Write $SYSTEM.OBJ.DisplayError(sc)
    }
    
    Write pJWT
	Return sc
}

Como alternativa, você pode usar um objeto dinâmico para evitar a criação de uma classe; nesse caso, ficaria assim:

ClassMethod JWT(credential) As %Status
{
    Set sc = $$$OK
    //Set x509 = ##class(%SYS.X509Credentials).GetByAlias("TempKeyPair")
    Set credentialObj = ##class(Ens.Config.Credentials).%OpenId(credential,,.sc)
    throw:$$$ISERR(sc) ##class(%Exception.StatusException).ThrowIfInterrupt(sc)
    
    Set x509 = {
        "HasPrivateKey": true,
        "PrivateKey": (credentialObj.Password),
        "PrivateKeyPassword":"",
        "Certificate":(credentialObj.Username)
    }

    Set algorithm ="RS256"
    Set header = {"alg": (algorithm), "typ": "JWT"}
    Set claims= {"Key": "Value" }
    
    #; create JWK
    Set sc = ##class(%Net.JSON.JWK).CreateX509(algorithm,x509,.privateJWK)
    
    If $$$ISERR(sc) {
        Write $SYSTEM.OBJ.DisplayError(sc)
    }

    #; Create JWKS
    Set sc = ##class(%Net.JSON.JWKS).PutJWK(privateJWK,.privateJWKS)
    
    If $$$ISERR(sc) {
        Write $SYSTEM.OBJ.DisplayError(sc)
    }

    Set sc = ##Class(%Net.JSON.JWT).Create(header,,claims,privateJWKS,,.pJWT)
    
    If $$$ISERR(sc) {
        Write $SYSTEM.OBJ.DisplayError(sc)
    }
    
    Write pJWT
    Return sc
}
讨论 (0)1
登录或注册以继续