Artículo
· 14 mar, 2024 Lectura de 5 min

Consulta de datos dinámicos usando ASQ

IRIS 2023.3.0 ASQ

Abstract Set Query, ASQ, es un superconjunto del lenguaje JSONPath, JPL, que fue introducido por primera vez por el Standard SQL ISO 2016. JPL sólo está definido dentro del contexto de SQL. En 2023.3, introdujimos clases que implementan ASQ. Funciona en cualquier implementación de %Library.AbstractSet. La sintaxis completa para ASQ será documentada más adelante. Esto es solo una introducción rápida a algunas de sus funcionalidades. Esta implementación también viene con una utilidad muy chula. ¡Lo sabrás cuando la veas!

En primer lugar, vamos a coger algunos datos de la base de datos de la NHL (National Hockey League). Este paso requiere una configuración válida de SSL/TLS. Yo he llamado a la mía Default.

USER>set data = ##class(%Net.Http).GetJson("https://api.nhle.com/stats/rest/en/team",{"SSLConfiguration":"Default"})

Esto puede tardar unos segundos en completarse. Este es un objeto de respuesta. Tiene campos de nivel superior - bueno, veamos. Podría simplemente imprimir los datos de forma bonita, pero es bastante grande. Solo quiero los nombres de los campos.

USER>set iterator = data.iterator() while iterator.hasNext() { write !,iterator.next().key }  
httpStatus
message
content

Es el contenido lo que nos interesa, así que vamos a hacerlo de nuevo, esta vez iterando sobre el valor del campo de contenido. Supongo que debería añadir una funcionalidad para imprimir un árbol de los datos. Quizá la semana que viene.

USER>set iterator = data.content.iterator() while iterator.hasNext() { write !,iterator.next().key }
data
total

Finalmente - los datos. Vamos a echar un vistazo.

Quiero señalar algo aquí. El código que ejecuté no ha modificado otra cosa que el objeto del que obtuve el iterador. El resto del comando es igual. En unas pocas líneas de código, pude implementar la visualización del árbol. Hay una función similar que está en la versión 2023.3.0 que podría ser de interés. Así que vamos a obtener una instancia del array de datos (sé que es un array porque lo he mirado antes :). Lo siento.)

USER>:pp data.content.data.get(0)
do ##class(%ASQ.SetUtils).pp(data.content.data.get(0))
{
  "id": 11,
  "franchiseId": 35,
  "fullName": "Atlanta Thrashers",
  "leagueId": 133,
  "rawTricode": "ATL",
  "triCode": "ATL"
}

Estoy usando un alias aquí. Podéis ver la llamada que hace - %ASQ.SetUtils.pp. Simplemente pasa la referencia.

Los datos que recuperamos contienen los equipos que están actualmente en la NHL. Vamos a aplicar algunas expresiones ASQ, solo para practicar un poco. La primera parte de una expresión ASQ es el valor base. Se referencia como '$'.

USER>:pp data.apply("$.content.data[0 to 3]") 
do ##class(%ASQ.SetUtils).pp(data.apply("$.content.data[0 to 3]"))
[
  {
    "id": 11,
    "franchiseId": 35,
    "fullName": "Atlanta Thrashers",
    "leagueId": 133,
    "rawTricode": "ATL",
    "triCode": "ATL"
  },
  {
    "id": 34,
    "franchiseId": 26,
    "fullName": "Hartford Whalers",
    "leagueId": 133,
    "rawTricode": "HFD",
    "triCode": "HFD"
  },
  {
    "id": 31,
    "franchiseId": 15,
    "fullName": "Minnesota North Stars",
    "leagueId": 133,
    "rawTricode": "MNS",
    "triCode": "MNS"
  },
  {
    "id": 32,
    "franchiseId": 27,
    "fullName": "Quebec Nordiques",
    "leagueId": 133,
    "rawTricode": "QUE",
    "triCode": "QUE"
  }
]

Esa expresión solo recupera los miembros de la matriz de datos de 0 al 3 - cuatro de ellos. La expresión [0 TO 3] se llama array accessor expression. Permite un comodín como [*], un índice como [5] por ejemplo, un índice relativo como [last], un rango como [1 TO 3], una lista separada por comas con el índice, rango y posición relativa [0, 2, 4, 5 TO 7, last]. El orden de las expresiones de índice no importa, pero serán devueltas en el orden que se especificó:

USER>:pp data.content.data.apply("$[0 TO 1,last]")
do ##class(%ASQ.SetUtils).pp(data.content.data.apply("$[0 TO 1,last]"))
[
  {
    "id": 11,
    "franchiseId": 35,
    "fullName": "Atlanta Thrashers",
    "leagueId": 133,
    "rawTricode": "ATL",
    "triCode": "ATL"
  },
  {
    "id": 34,
    "franchiseId": 26,
    "fullName": "Hartford Whalers",
    "leagueId": 133,
    "rawTricode": "HFD",
    "triCode": "HFD"
  },
  {
    "id": 9,
    "franchiseId": 30,
    "fullName": "Ottawa Senators",
    "leagueId": 133,
    "rawTricode": "OTT",
    "triCode": "OTT"
  }
]
USER>:pp data.content.data.apply("$[last, 0 TO 1]")
do ##class(%ASQ.SetUtils).pp(data.content.data.apply("$[last, 0 TO 1]"))
[
  {
    "id": 9,
    "franchiseId": 30,
    "fullName": "Ottawa Senators",
    "leagueId": 133,
    "rawTricode": "OTT",
    "triCode": "OTT"
  },
  {
    "id": 11,
    "franchiseId": 35,
    "fullName": "Atlanta Thrashers",
    "leagueId": 133,
    "rawTricode": "ATL",
    "triCode": "ATL"
  },
  {
    "id": 34,
    "franchiseId": 26,
    "fullName": "Hartford Whalers",
    "leagueId": 133,
    "rawTricode": "HFD",
    "triCode": "HFD"
  }
]

Después viene el member accessor. La forma de acceder a los miembros es simplemente a través de un punto seguido por el nombre del miembro, también conocido como nombre del campo. También hay un miembro comodín, indicado con un asterisco. Los member accessors son necesarios y útiles, pero no muy interesantes.

Lo que es más interesante es el comportamiento cuando el valor de un miembro es una matriz. Podemos filtrar cualquier valor - ya sea una matriz o un objeto. Probablemente incluso un literal. Así que vamos a sacar una lista de todos los Equipos en nuestros datos cuyo nombre empieza por la letra 'M'. En esta expresión, el @ en la expresión de filtro se refiere al valor actual.

USER>:pp data.content.data.apply("$[*]?(@.fullName STARTS WITH 'M').fullName")
do ##class(%ASQ.SetUtils).pp(data.content.data.apply("$[*]?(@.fullName STARTS WITH 'M').fullName"))
[
  "Minnesota North Stars",
  "Montreal Wanderers",
  "Montreal Maroons",
  "Montréal Canadiens",
  "Minnesota Wild"
]
Comentarios (0)1
Inicie sesión o regístrese para continuar