IBM Cloud Docs
Referencia de Annotation Query Language

Referencia de Annotation Query Language

Annotation Query Language (AQL) es el lenguaje principal que se utiliza para crear extractores de reglas avanzadas de IBM Watson® Knowledge Studio.

  • Modelo de datos: El modelo de datos para AQL es similar al modelo relacional estándar que utiliza una base de datos SQL como, por ejemplo, DB2®. Todos los datos de AQL se almacenan en tuplas, registros de datos de una o más columnas o campos. Un conjunto de tuplas forma una vista. Todas las tuplas de una vista deben tener el mismo esquema, es decir, los nombres y los tipos de los campos de todas las tuplas.
  • Modelo de ejecución: el componente de tiempo de ejecución tiene un modelo de ejecución de tipo un documento a la vez. El componente de tiempo de ejecución recibe una colección de documentos y ejecuta el extractor sobre cada documento para extraer información de dicho documento.
  • Sentencias SQL: mediante sentencias AQL, puede crear y luego utilizar módulos, vistas, tablas, diccionarios y funciones.
  • Funciones integradas: AQL tiene una colección de funciones incorporadas que puede utilizar en las reglas de extracción.
  • La sentencia create function: para realizar operaciones sobre valores extraídos que no reciben soporte de AQL, puede definir funciones personalizadas que se utilizarán en las reglas de extracción denominadas funciones definidas por el usuario (UDF).

Sintaxis de Annotation Query Language (AQL)

Al igual que muchos lenguajes de programación, AQL se basa en sintaxis y gramática comunes.

La estructura léxica de un lenguaje de programación es el conjunto de reglas elementales que definen las señales o los componentes básicos de ese lenguaje, como por ejemplo sus palabras reservadas, identificadores, constantes y más.

La sintaxis de AQL se parece a la de SQL, pero hay varias diferencias importantes:

  • AQL distingue entre mayúsculas y minúsculas.

  • Actualmente AQL no da soporte a las características avanzadas de SQL, como por ejemplo subconsultas correlacionadas y consultas recursivas.

  • AQL tiene un nuevo tipo de sentencia, extract, que no existe en SQL.

  • AQL no permite palabras claves (palabras reservadas) como nombres de vista, de columna o de función.

  • AQL permite, aunque no requiere, que las expresiones regulares se expresan en la sintaxis de Perl. Las expresiones regulares comienzan por una barra inclinada (/) y terminan con una barra inclinada (/), como en la sintaxis de Perl. AQL también permite expresiones regulares que empiezan con una comilla simple (') y terminan con una comilla simple ('). Por ejemplo, puede utilizar /regex/ en lugar de 'regex' como expresión regular en AQL.

  • Identificadores: los identificadores sirven para definir los nombres de los objetos de AQL, incluidos nombres de módulos, vistas, tablas, diccionarios, funciones, atributos y parámetros de función.

  • Palabras reservadas: las palabras reservadas son palabras que tienen un significado fijo dentro del contexto de la estructura de AQL y que no se pueden volver a definir. Las palabras clave son palabras reservadas que tienen significados especiales dentro de la sintaxis del lenguaje.

  • Constantes: las constantes son valores fijos que pueden ser de uno de estos tipos de datos: serie (string), entero (integer), flotante (float) o booleano (boolean).

  • Comentarios: utilice comentarios para clarificar el código AQL con descripciones básicas que ayuden a comprender el código y a generar módulos compilados de autodescripción.

  • Expresiones: una expresión de AQL es una combinación de uno o varios valores escalares y funciones que se evalúa como un solo valor escalar.

Identificadores

Los identificadores sirven para definir los nombres de los objetos de AQL, incluidos nombres de módulos, vistas, tablas, diccionarios, funciones, atributos y parámetros de función.

Hay dos tipos de identificadores AQL que distinguen entre mayúsculas y minúsculas:

  • Identificador simple

    Un identificador simple debe empezar con una letra minúscula (a-z) o mayúscula (A-Z) o el carácter de subrayado (_). Los caracteres siguientes pueden ser letras en minúsculas o mayúsculas, el carácter de subrayado o dígitos (0-9). Un identificador simple debe ser distinto de cualquier palabra clave AQL.

  • Identificador de comillas dobles

    Un identificador entre comillas dobles comienza y termina por un carácter de comillas dobles ("). Puede utilizar cualquier carácter entre los caracteres de comillas dobles inicial y final. Los identificadores con comillas dobles no pueden contener un carácter de punto (.). Si hay un carácter de comillas dobles en el nombre, debe especificar como prefijo el carácter de barra inclinada invertida (\), por ejemplo \”.

Palabras reservadas

Las palabras reservadas son palabras que tienen un significado fijo dentro del contexto de la estructura de AQL y que no se pueden volver a definir. Las palabras clave son palabras reservadas que tienen significados especiales dentro de la sintaxis del lenguaje.

Las siguientes palabras clave reservadas de AQL no se pueden utilizar como identificadores porque cada una tiene una finalidad bien definida dentro del lenguaje:

  • all
  • allow
  • allow_empty
  • always
  • and
  • annotate
  • as
  • ascending
  • ascii
  • attribute
  • between
  • blocks
  • both
  • by
  • called
  • case
  • cast
  • ccsid
  • character
  • characters
  • columns
  • consolidate
  • content\_type
  • count
  • create
  • default
  • descending
  • detag
  • detect
  • deterministic
  • dictionary
  • dictionaries
  • document
  • element
  • else
  • empty\_fileset
  • entries
  • exact
  • export
  • external
  • external_name
  • extract
  • fetch
  • file
  • first
  • flags
  • folding
  • from
  • function
  • group
  • having
  • import
  • in
  • include
  • infinity
  • inline_match
  • input
  • into
  • insensitive
  • java
  • language
  • left
  • lemma_match
  • like
  • limit
  • mapping
  • matching_regex
  • minus
  • module
  • name
  • never
  • not
  • null
  • on
  • only
  • order
  • output
  • part_of_speech
  • parts_of_speech
  • parameter
  • pattern
  • point
  • points
  • priority
  • regex
  • regexes
  • retain
  • required
  • return
  • right
  • rows
  • select
  • separation
  • set
  • specific
  • split
  • table
  • tagger
  • then
  • token
  • Token
  • tokens
  • unicode
  • union
  • up
  • using
  • values
  • view
  • views
  • when
  • where
  • with

Las siguientes palabras reservadas son los nombres de los tipos escalares incorporados:

  • Text
  • Span
  • Integer
  • Float
  • String
  • Boolean
  • ScalarList

Los siguientes nombres reservados no se pueden utilizar como identificadores:

  • Dictionary
  • Regex
  • Consolidate
  • Block
  • BlockTok
  • Sentence
  • Tokenize
  • RegexTok
  • PosTag

Constantes

Las constantes son valores fijos que pueden ser de uno de estos tipos de datos: serie (String), entero (Integer), flotante (Float) o booleano (Boolean).

Las constantes se utilizan en la lista select de una cláusula select o extract o como argumentos en las funciones integradas o UDF y en los predicados. AQL da soporte a los siguientes tipos de constantes:

  • Constante de tipo serie

    Una serie de caracteres especificada entre comillas simples ('), por ejemplo 'una serie'.

  • Constante de entero

    Un valor entero con signo de 32 bits que no está especificado entre comillas, por ejemplo 10 o -1.

  • Constante flotante

    Un valor de coma flotante de 32 bits de precisión única que no está especificado entre comillas, por ejemplo 3.14 o -1.2.

  • Constante booleana

    El valor true o false que no está especificado entre comillas.

  • Constante nula

    El valor nulo que no está especificado entre comillas.

Comentarios

Utilice comentarios para clarificar el código AQL con descripciones básicas que ayuden a comprender el código y a generar módulos compilados de autodescripción.

Los comentarios permiten a los desarrolladores de AQL clarificar el código AQL con descripciones básicas para facilitar la comprensión del código fuente de AQL y para generan módulos AQL compilados de autodescripción. En AQL se da soporte a tres tipos de comentarios:

  • Comentarios de una sola línea

    Los comentarios de una sola línea empiezan por dos guiones (--).

  • Comentarios de varias líneas

    Los comentarios de varias líneas empiezan con una barra inclinada y un asterisco (/*) y terminan con un asterisco y una barra inclinada (*). Los comentarios de varias líneas no se pueden anidar. Por ejemplo, el siguiente comentario de varias líneas anidada no está permitido:

    /*
    A comment with a /*nested comment*/
    */
    
  • Comentarios de AQL Doc

    Los comentarios de AQL Doc proporcionan una forma de describir un módulo o un objeto de AQL en lenguaje sencillo y de forma detallada para facilitar la comprensión contextual por parte de otros usuarios. A diferencia de los comentarios de una sola línea y de los comentarios de varias líneas, que AQL Compiler pasa por alto, los comentarios de AQL Doc se serializan en los metadatos de los módulos compilados (archivos .tam) y están disponibles para el consumo externo.

    Todos los comentarios en AQL Doc para las sentencias y los módulos tienen el formato siguiente:

    • El comentario está en texto sin formato (no se da soporte a etiquetas HTML).

    • El comentario empieza con una barra inclinada seguida de dos asteriscos (/**) y termina con una barra inclinada (*/). Opcionalmente, cada línea puede empezar con un asterisco (*).

    • Se puede utilizar el número que se desee de espacios en blanco antes del asterisco.

    • Las etiquetas especiales que están precedidas del símbolo (@) se pueden utilizar al principio de cada línea o después del asterisco opcional.

    • Los comentarios de AQL Doc no se pueden anidar. Se da soporte a dos niveles de granularidad dentro del sistema AQL Doc. El formato para documentar cada artefacto se explica detalladamente en el tema en que se describe su sentencia y su sintaxis.

    • Comentarios de nivel de módulo

      Los comentarios de nivel de módulo están contenidos dentro de un archivo especial denominado module.info que se encuentra directamente bajo la carpeta del módulo. Se espera que los comentarios describan la semántica del módulo y el esquema de la vista Document del módulo.

    • Comentarios de nivel de sentencia

      Los comentarios de nivel de sentencia están contenidos en el archivo AQL de origen, inmediatamente antes de la sentencia que crea un objeto AQL. Se permiten comentarios de una sola línea y comentarios de varias líneas entre el comentario de AQL Doc de una sentencia y la propia sentencia.

      Las siguientes sentencias AQL de nivel general se pueden documentar mediante comentarios de AQL Doc:

      • La sentencia create external view
      • La sentencia create external table
      • La sentencia create external dictionary
      • La función create
      • La sentencia detag
      • La sentencia select... into Los comentarios de AQL Doc se serializan dentro de la representación compilada de un módulo.

Expresiones

Una expresión de AQL es una combinación de uno o varios valores escalares y funciones que se evalúa como un solo valor escalar.

Las expresiones pueden ser de uno de los cuatro tipos siguientes:

  • una constante
  • una referencia de columna
  • una llamada de función escalar
  • una llamada de función de agregación

Constante

Una expresión puede ser una constante de tipo Integer, Float o String, como en el ejemplo siguiente:

select 'positive' as polarity

La expresión es la constante de serie positive.

Referencia de columna

Una expresión puede ser una referencia de columna, como en el ejemplo siguiente:

create view Person as
select F.name as firstname, L.name as lastname
from FirstName F, LastName L
where FollowsTok(F.name, L.name, 0, 0);

Esta vista identifica el texto que se puede interpretar como el nombre completo de una persona (por ejemplo, "Samuel Davis", "Vicky Rosenberg"). Las expresiones F.name y L.name son expresiones de referencia de columna que devuelven la columna de nombre de las vistas F y L, respectivamente. La sentencia from define las vistas F y L como los nombres locales de las vistas FirstName y LastName (que definen el nombre y apellidos válidos y que no se muestran en este ejemplo).

Llamada de función escalar

Una expresión se puede componer de una o más llamadas de funciones escalares, cada una de las cuales puede contener argumentos que también son expresiones de tipo constante, referencia de columna o llamada de función escalar. Una llamada de función escalar puede ser una de las funciones escalares incorporadas o bien una función escalar definida por el usuario. Consulte el ejemplo siguiente:

create view FamilyMembers as
    select ToLowerCase(GetText(P.lastname)) as lastname, List( (GetText(P.firstname))) as firstnames
    from Person P
    group by GetText(P.lastname);

Esta vista identifica a los miembros potenciales de la familia agrupando personas con los mismos apellidos, imprimiendo todos los nombres, con los apellidos en minúsculas (por ejemplo, lastname keaton, firstnames (Elyse, Alex, Diane)). Los resultados de las llamadas de la función GetText se utilizan como argumentos de la llamada de la función ToLowerCase para mostrar los nombres en minúsculas. Las expresiones de la llamada de función scalar de este ejemplo son: ToLowerCase, (GetText(P.lastname), ToLowerCase(GetText(P.firstname)) y GetText(P.lastname).

Llamada de función de agregación

Una expresión puede ser una llamada de función de agregación. Este tipo de expresión puede tener como argumentos otra expresión de tipo referencia de columna de tipo llamada de función escalar. En el siguiente ejemplo se muestra una llamada de función de agregación con una expresión de tipo referencia de columna:

create view CountLastNames as
select Count(Person.lastname)
from Person;

La expresión es simplemente Count(Person.lastname) y cuenta el número de anotaciones Person.lastname del documento. El ejemplo anterior contiene una llamada de función de agregación con una expresión de tipo llamada de función escalar como List(GetText(P.firstname)), donde la función de agregación List toma una función escalar GetText como argumento para generar una lista de nombres propios. Las expresiones de llamada de función de agregación solo se permiten como expresiones en la lista select de una sentencia select. Las expresiones de llamada de función de agregación no se permiten en la lista select de una sentencia extract ni como argumentos a una llamada de función escalar o de agregación.

Modelo de datos

El modelo de datos para AQL es similar al modelo relacional estándar que utiliza una base de datos SQL como, por ejemplo, DB2®. Todos los datos de AQL se almacenan en tuplas, registros de datos de una o más columnas o campos. Un conjunto de tuplas forma una vista. Todas las tuplas de una vista deben tener el mismo esquema, es decir, los nombres y los tipos de los campos de todas las tuplas.

El contenido del documento de entrada se representa como una vista especial denominada Document.

Los campos de una tupla deben pertenecer a uno de los tipos de datos incorporados de AQL:

  • Boolean

    Un tipo de datos que tiene un valor true o false.

  • Float

    Un número de coma flotante de precisión única.

  • Integer

    Un entero con signo de 32 dígitos.

  • ScalarList

    Una colección de valores del mismo tipo escalar (Integer, Float, Text o Span). Se puede obtener un valor de tipo de datos ScalarList como resultado de la función de agregación incorporada de AQL List() o como resultado de una UDF.

  • Span

    Un tramo o Span es una región contigua de un objeto Text, que se identifica por sus desplazamientos de principio y fin en el objeto Text. Supongamos que el texto de entrada es el siguiente:

    Amelia Earhart is a pilot.
    

    El texto contenido en Span [0-6] es Amelia.

    Este valor de Span se puede visualizar como:

    0A1m2e3l4i5a6
    

    Paralelamente, el texto contenido en Span [20-25] es pilot.

    El valor de Span [x-x] representa el tramo comprendido entre el final de un carácter y el principio del siguiente carácter. En el ejemplo anterior, [0-0] es una serie vacía antes del carácter A. Asimismo, un Span de [3-3] es una serie vacía entre los caracteres e y l.

    Se puede obtener un valor de tipo Span como resultado de una sentencia extract o de una función escalar incorporada o una UDF.

  • Text

    El tipo de datos de AQL para representar una secuencia de caracteres. Un objeto de texto contiene una serie Unicode, llamada su valor de serie. Cuando una serie de caracteres está formada como la concatenación de subseries disyuntivas de otro objeto de tipo Text, también contiene una referencia al objeto Text original e información relevante de correlación de desplazamiento. Dos objetos de texto se consideran iguales entre sí si todos sus componentes son iguales entre sí.

  • Comparación entre los valores de tipo Span y Text Los factores de priorización afectan a las comparaciones entre los valores de tipo Span y de tipo Text.

Comparación entre los valores de tipo Span y Text

Los factores de priorización afectan a las comparaciones entre los valores de tipo Span y de tipo Text.

Los valores de tipo Span y de tipo Text se comparan entre sí de estas formas:

  • Un valor de Span nulo siempre se clasifica por debajo de otros valores.
  • Un valor de Text siempre se clasifica por encima de un valor de Span.
  • Los valores del tipo Text se clasifican en primer lugar por el orden léxico de sus valores de serie y luego por su orden en el texto original y por la información de correlación de desplazamiento, si procede.
  • Los valores de tipo Span se clasifican en primer lugar por sus objetos de texto subyacentes, luego por su desplazamiento de inicio y luego por su desplazamiento final. Un valor de tipo Span con un desplazamiento de inicio menor se clasifica por debajo. Entre dos valores de tipo Span que empiezan por el mismo desplazamiento, el que tiene el desplazamiento final menor se clasifica por debajo.

Modelo de ejecución

El componente de tiempo de ejecución tiene un modelo de ejecución de tipo un documento a la vez. El componente de tiempo de ejecución recibe una colección de documentos y ejecuta el extractor sobre cada documento para extraer información de dicho documento.

Un extractor consta de uno o varios módulos AQL para crear una colección de vistas, cada una de las cuales define una relación. Algunas de estas vistas se designan como vistas de salida, mientras que otras son vistas que no son de salida. Las vistas que no son de salida pueden incluir algunas vistas importadas en un módulo o exportadas desde un módulo. Es importante resaltar que las vistas de salida y las vistas exportadas son ortogonales. Por ejemplo, una vista que se exporta no se cualifica como una vista que es de salida. Además de estas vistas, la vista Document exclusiva representa el documento de entrada que anota este extractor.

Vista de Document

En el nivel de módulo de AQL, la vista Document es una vista especial que representa el documento actual que está anotando ese módulo. Cuando se combinan dos o más módulos para formar un extractor, la unión libre de duplicados de esquemas de documento de todos los módulos es la vista Document necesaria. Utilice la sentencia require document with columns para especificar el esquema de la vista Document. Si un módulo no contiene esta sentencia, el esquema predeterminado que se presupone para la vista Document es (texto Texto, etiqueta Texto):

  • text

    El contenido textual del documento actual.

  • label

    La etiqueta del documento actual que se está anotando.

La palabra clave Document se reserva como identificador para la vista Document, que se llena automáticamente durante la ejecución. Por lo tanto, no puede definir otra vista o tabla con el mismo nombre. Sin embargo, puede utilizar la palabra Document como identificador para nombres de atributo y alias.

Sentencias AQL

Mediante sentencias AQL, puede crear y luego utilizar módulos, vistas, tablas, diccionarios y funciones.

Las siguientes sentencias reciben soporte en AQL:

  • Sentencias para crear módulos y declarar la interacción entre los mismos

    La sentencia module

    La sentencia export

    La sentencia import

  • Sentencias para crear objetos de AQL: vistas, diccionarios, tablas o funciones

    Las sentencias create dictionary y create external dictionary

    La sentencia create table

    La sentencia create view

    La sentencia create external view

    La sentencia detag

    La sentencia extract

    La sentencia select

    La sentencia require document with columns

    La sentencia set default dictionary language

    La sentencia create function

Las especificaciones de sintaxis de las sentencias AQL contienen corchetes ([ ]). Estas especificaciones indican que los corchetes y las construcciones que mantienen son opcionales cuando se utiliza la sintaxis correspondiente en la escritura de una sentencia. Además, sirven como marcadores de posición para definir cómo especificar instancias adicionales de una construcción o un argumento.

La sentencia module

Utilice la sentencia module para crear un módulo que tenga los recursos necesarios autocontenidos. Puede exportar e importar estos recursos como objetos de AQL a y desde otros módulos.

Sintaxis

module <module-name\>;

Descripción

  • <module-name\>

    Declara que el archivo actual forma parte del módulo denominado <module-name\>. El nombre de módulo debe ser un identificador simple. No se permite identificadores con comillas dobles como nombres de módulo.

    Cada archivo AQL contenido dentro del módulo debe tener exactamente una declaración module y dicha declaración debe ser la primera en cada archivo. Esta declaración establece un espacio de nombres idéntico al nombre de módulo. Todas las vistas (y otros objetos, como diccionarios, tablas y funciones) declaradas en archivos AQL dentro de este módulo se encuentran dentro de este espacio de nombres. Todos los archivos AQL de este espacio de nombres pueden acceder a dichas vistas.

    Todos los archivos que se declaran como parte del módulo <module-name\> deben estar dentro de una carpeta denominada <module-name\> para imponer este espacio de nombres. No hay ningún orden de los archivos de AQL dentro de esta carpeta de módulo. El compilador de AQL examina todos los archivos AQL del módulo y determina el orden correcto para compilar todas las vistas, diccionarios, tablas y funciones declarados en el módulo.

Notas de uso

  • Cuando el archivo AQL subyacente no se encuentra como parte de un módulo (AQL modular) y se compila en modalidad de compatibilidad, esta sentencia no recibe soporte.
  • No se permiten dependencias circulares entre vistas.
  • Los módulos de AQL no dan soporte a submódulos.
  • Los archivos de AQL dentro de subcarpetas de la carpeta de módulo de nivel superior se pasan por alto.

Ejemplos

Ejemplo 1: Módulo de ejemplo

En el ejemplo siguiente, la vista TheMentions pertenece al módulo llamado sample.

module sample;

create dictionary GetTheDict as ('The', 'the');

create view TheMentions as
  extract dictionary 'GetTheDict' on D.text as theMention
  from Document D;

La sentencia export

La sentencia export en AQL se utiliza para exportar un objeto de AQL desde el módulo actual de modo que se pueda importar y utilizar en otros módulos.

Sintaxis

export view|dictionary|table|function <object-name\>;

Descripción

  • view|dictionary|table|function

    Define el tipo de objeto que se va a exportar. El tipo de objeto puede ser una vista (view), un diccionario (dictionary), una tabla (table) o una función (function).

  • <object-name\>

    Define el nombre del objeto que se va a exportar. El <object-name\> puede ser un identificador simple o un identificador de comillas dobles.

Notas de uso

  • No puede exportar ninguno de los objetos de AQL importados. Puede crear el efecto de volver a exportar la vista o la tabla en el módulo actual creando una nueva vista:

    select * from <imported_view_name_or_table_name>;
    
  • Las sentencias export view y output view que se muestran en los ejemplos son ortogonales entre sí. Es decir, una vista de salida no es automáticamente una vista exportada, sino que se debe exportar de forma explícita mediante una sentencia export. Una vista exportada no es automáticamente una vista de salida, sino que se debe convertir en vista de salida explícitamente mediante la sentencia output view. En los ejemplos, la sentencia export intenta exportar la vistaPersonName.FirstName, que es una vista importada. Este intento genera un error, lo que significa que el desarrollador debe copiar la vista importada en una nueva vista y luego exportar esta.

Ejemplos

Ejemplo 1: Creación de vistas y diccionarios y luego exportación de los mismos para utilizarlos en otros módulos

En este ejemplo se crean las vistas FirstName y NotFirstName. La vista FirstName recopila información sobre los nombres propios que están representados en el diccionario FirstNamesDictionary. La otra vista recopila los nombres que permanecen cuando se excluyen los nombres propios. Se necesitan dos diccionarios para facilitar la extracción de texto. Un diccionario contiene todos los nombres propios que desea buscar. El segundo diccionario, LastNamesDictionary, contiene los apellidos que se deben buscar. El diccionario FirstNamesDictionary se exporta para que se pueda utilizar en otros módulos. Las vistas FirstName y NotFirstName también se exportan para que se puedan importar y utilizar en otros módulos, como por ejemplo el módulo person del Ejemplo 2.

module personName;

create dictionary FirstNamesDictionary as
('Smith', 'John', 'Mary', 'Sam', 'George');

-- export dictionary statement

export dictionary FirstNamesDictionary;


create view FirstName as
  extract dictionary 'FirstNamesDictionary'
  on D.text as firstName
from Document D;

-- export view statement

export view FirstName;

create dictionary LastNamesDictionary as
('Stewart', 'Johnson', 'Smith', 'Hopkins', 'George');

create view NotFirstName as
  select F.firstName as notFirstName from FirstName F
  where ContainsDict('LastNamesDictionary', F.firstName);

-- export view statement

export view NotFirstName;

Ejemplo 2: Importación de vistas a utilizarlas, pero la exportación incorrecta provoca un error

En este ejemplo se muestra la importación de dos vistas. Estas vistas se han exportado desde el módulo personName en el Ejemplo 1. La persona del módulo ahora puede importar y hacer referencia a esas vistas. Sin embargo, este módulo intenta exportar la misma vista que ha importado, FirstName, lo que ocasiona un error.

module person;

-- Form 1

import view FirstName from module personName as PersonFirstName;

-- Form 2

import view NotFirstName from module personName;


-- ERROR
-- Reason: A view that is imported from one module
-- cannot be exported in the current module.
export view personName.FirstName;


output view PersonFirstName;

La razón del error de este código es que una vista que se ha importado de un módulo no se puede exportar en el módulo actual. Además, las vistas exportadas no son vistas de salida automáticamente a menos que haya definido una vista de salida con la sentencia output view.

La sentencia import

Puede utilizar la sentencia import para hacer referencia a los objetos que se exportan desde otros módulos en el contexto del módulo actual.

Sintaxis

import view|dictionary|table|function <object-name\>
     from module <module-name\> [as <alias\>];

Descripción

  • view\|dictionary\|table\|function

    Identifica el tipo de objeto de AQL que se va a importar. El tipo de objeto es obligatorio.

  • <object-name\>

    El <object-name\> puede ser un identificador simple o un identificador de comillas dobles.

  • <module-name\>

    El <module-name\> debe ser un identificador simple.

  • <alias\>

    Este formato de la sentencia de importación, también conocida como alias import, importa el objeto AQL especificado bajo el nombre <alias\> (no el nombre original) en el espacio de nombres del módulo actual. Puede hacer referencia al elemento importado utilizando un alias no cualificado o un alias que esté cualificado con el nombre del módulo actual (el módulo en el que se ha importado el objeto de AQL). No puede utilizar originalModule.elementName porque la sentencia alias import solo importa el elemento bajo el nombre de alias y no bajo el nombre original calificado.

Notas de uso

  • Una sentencia import sin una especificación de alias importa el objeto de AQL especificado en el módulo actual. Hace que el objeto AQL sea accesible a las sentencias AQL definidas en el módulo actual bajo su nombre calificado <original\_module\_name\>.<object-name\>.

  • La sentencia import solo se utiliza para importar objetos de AQL desde módulos que no sean el módulo actual. Un objeto declarado en un archivo de AQL del módulo resulta visible para cualquier otro archivo de AQL del mismo módulo. Una sentencia import coloca los objetos en el contexto del módulo actual, no en el contexto del archivo actual. Por lo tanto, una vista importada por 1.aql dentro del módulo A resulta visible a 2.aql dentro del mismo módulo sin necesidad de ninguna sentencia import adicional.

  • Todas las sentencias import deben ir inmediatamente después de la declaración del módulo y deben estar antes que los demás tipos de sentencias. Solo los objetos de AQL que se exportan explícitamente desde cualquier módulo se pueden importar en otro módulo. Si no se tiene en cuenta este requisito, se produce un error de compilación.

  • Se produce un error de compilación cuando una sentencia import view incorpora un conflicto de denominación con cualquier sentencia create view o con otras sentencias import dentro del mismo módulo (no solo dentro del archivo actual). Esta restricción se aplica a la sentencia import de otros objetos, además de a las vistas.

  • El compilador de AQL cumple con los convenios de denominación que se utilizan en las versiones anteriores de AQL:

    • Un módulo no puede contener una vista y una tabla con el mismo nombre.
    • Se permite un diccionario con el mismo nombre que una tabla o una vista.
    • Se permite una función con el mismo nombre que una tabla, una vista o un diccionario.
  • Se produce un error de compilación cuando distintas sentencias import dentro de uno o varios archivos de AQL del módulo asignan el mismo nombre a distintos objetos de AQL.

  • Se produce un error de compilación cuando un archivo de AQL dentro de un módulo intenta hacer referencia a otra vista exportada de un módulo sin utilizar la sentencia import view. Lo mismo se aplica a los diccionarios, las tablas o las funciones.

  • Cuando dos archivos de AQL dentro de un módulo importan la misma vista X de otro módulo bajo dos alias diferentes, por ejemplo A y B, los dos alias se tratan como sinónimos. Esta regla se aplica también a las tablas, los diccionarios y las funciones.

Ejemplos

Ejemplo 1: Crear vistas que exporta para que se importen en otros módulos.

En este ejemplo se crean dos vistas, FirstName y NotFirstName. La vista FirstName recopila información sobre los nombres propios que están representados en el diccionario FirstNamesDictionary. La segunda vista recopila los nombres que quedan cuando se excluyen los nombres propios. Se necesitan dos diccionarios para facilitar la extracción de texto. Un diccionario contiene todos los nombres propios que desea buscar. El segundo diccionario, LastNamesDictionary, contiene los apellidos que se deben buscar. Las vistas FirstName y NotFirstName se exportan para que se puedan importar y utilizar en otros módulos, como por ejemplo el módulo person de los Ejemplos 2 y 3.

module personName;

create dictionary FirstNamesDictionary as
('Smith', 'John', 'Mary', 'Sam', 'George');

create view FirstName as
extract dictionary 'FirstNamesDictionary'
on D.text as firstName
from Document D;

export view FirstName;

create dictionary LastNamesDictionary as
('Stewart', 'Johnson', 'Smith', 'Hopkins', 'George');

create view NotFirstName as
select F.firstName as notFirstName from FirstName F
where ContainsDict('LastNamesDictionary', F.firstName);

export view NotFirstName;

Ejemplo 2: Importación de la vista FirstName mediante la importación de un alias

Este ejemplo importa una de las vistas que se han creado y exportado en el Ejemplo 1. A continuación, la vista PersonFirstName es la salida para que se puedan visualizar sus resultados.

La sentencia import de ejemplo se conoce como importación de alias. Importo la vista FirstName, sin calificador de módulo, en el espacio de nombres del módulo actual, person. Solo se puede acceder a la vista importada a través del nombre de alias PersonFirstName (no de ninguna otra forma). Por ejemplo, no puede hacer referencia a la vista importada como personName.FirstName porque solo se importa a través del nombre de alias.

module person;

`import view FirstName from module personName as PersonFirstName;`

output view PersonFirstName;

Ejemplo 3: Importación de la vista NotFirstname sin utilizar la importación de alias

Esta sentencia import de ejemplo importa el nombre calificado personName.NotFirstName (no el nombre no calificado de la vista) en el espacio de nombres del módulo actual, person. Siempre haga referencia a la vista importada utilizando únicamente el nombre calificado. Cualquier otra modalidad de referencia se marca como error del compilador.

module person;

`import view NotFirstName from module personName;`


output view personName.NotFirstName;

La sentencia import module

Puede utilizar la sentencia import module para importar y reutilizar módulos de AQL existentes.

Sintaxis

 import module <module-name\>;

Descripción

  • <module-name\>

    Especifica el módulo que se va a importar. El <module-name\> debe ser un identificador simple.

Notas de uso

  • La sentencia import solo se utiliza para importar objetos de AQL desde otros módulos, no desde el módulo actual.

  • Todas las sentencias import deben ir inmediatamente después de la declaración del módulo y deben estar antes que los demás tipos de sentencias. Solo los objetos de AQL que se exportan explícitamente desde cualquier módulo se pueden importar en otro módulo. Si no se tiene en cuenta este requisito, se produce un error de compilación.

  • Se produce un error de compilación cuando una sentencia import view incorpora un conflicto de denominación con cualquier sentencia create view o con otras sentencias import dentro del mismo módulo (no solo dentro del archivo actual). Esta restricción se aplica a la sentencia import de otros objetos de AQL, además de a las vistas.

  • Se produce un error de compilación cuando un archivo de AQL dentro de un módulo intenta hacer referencia a otra vista exportada de un módulo sin utilizar la sentencia import view. Lo mismo se aplica a los diccionarios, las tablas o las funciones.

  • Si dos archivos de AQL dentro de un módulo importan la misma vista X de otro módulo bajo dos alias diferentes, por ejemplo A y B, los dos alias se tratan como sinónimos. Esta regla se aplica también a las tablas, los diccionarios y las funciones.

Ejemplos

En este ejemplo, la sentencia import importa el nombre cualificado de ambas vistas exportadas, personName.FirstName y personName.NotFirstName. Cualquier vista que no haya exportado el módulo personName no se importa como parte de la sentencia import.

  • Ejemplo 1: Importar las vistas FirstName y NotFirstName

    En este ejemplo se muestran todas las vistas exportadas del módulo personName. Las vistas FirstName y NotFirstName se han creado en la sección de ejemplo de la sentencia export.

    module personOther;
    
    -- The following statement would import both views FirstName and NotFirstName.
    import module personName;
    

La sentencia set default dictionary language

La sentencia set default dictionary language permite que un desarrollador del extractor personalice el conjunto predeterminado de idiomas de comparación de diccionario para el módulo que lo contiene.

Sintaxis

 set default dictionary language as '<language codes\>';

Descripción

  • <language codes\>

    Especifica el idioma para la compilación y la comparación de diccionarios del módulo que se declaran sin una especificación with language as explícita. El conjunto de <language codes\> debe ser una lista separada por comas, sin espacios en blanco alrededor de cada código de idioma. Si no se tiene en cuenta este requisito, se puede producir un error de compilación.

    Esta sentencia afecta a los siguientes diccionarios:

    • Diccionarios que se declaran explícitamente en el módulo actual mediante la sentencia create dictionary o create external dictionary, y dicha sentencia no tiene una cláusula with language as.
    • Diccionarios procedentes de archivos externos.
    • En una especificación de patrón de una sentencia extract pattern, los átomos de tipo 'string' y los átomos de tipo <'string' [match parameters]> sin una especificación with language as explícita. Cuando esta sentencia no aparece dentro de un módulo, el componente de tiempo de ejecución toma de forma predeterminada un conjunto de idiomas alemán, español, inglés, francés, italiano y el idioma x no especificado. Se define como un conjunto: [de,es,en,fr,it,x_unspecified]. Dentro de un módulo, solo puede haber una instancia de esta sentencia.

Notas de uso

  • La sentencia set default dictionary language se puede actualizar para mejorar el alcance de los idiomas cubiertos por el extractor. Esta capacidad de añadir idiomas promueve la facilidad de personalización y la reutilización de los extractores existentes.

Ejemplos

Ejemplo 1: Especificación de idiomas que se van a utilizar para comparar entradas de diccionario

module Dictionaries;

-- Set the default dictionary matching language
--  for this module to English and French

set default dictionary language as 'en,fr';


/**
* Dictionary of English and French names. Because no language clause
* exists in dictionary definition, module level dictionary matching
* setting will be applied.
*/

create dictionary EnglishFrenchNames
from file 'en_fr_names.dict';

/**
* Dictionary of Italian names. Language clause in the dictionary
* definition will override the module level dictionary matching setting.
*/

create dictionary ItalianNames
with language as 'it'
as
(
'firstEntry','secondEntry'
);


/**
* View to extract pattern: Phone, followed by one to three tokens,
* followed by Email. Language clause at the atom level will override
* the module level dictionary setting.
*/

create view PhoneEmailPattern as
extract pattern <'Phone'[ with language as 'en']>
  <Token> {1,3} 'Email'
as match
from Document D;

output view PhoneEmailPattern;

La sentencia require document with columns

Mediante la sentencia require document with columns, puede definir el esquema de la vista especial Document en el momento de la compilación. Esta definición de esquema especifica la lista de campos obligatorios y sus tipos que se van a buscar en cada tupla de la vista Document.

Sintaxis

require document with columns  <columnName\> <columnType\>
     [and <columnName\> <columnType\>]*;

Descripción

  • <columnName\>

    Especifica el nombre de la columna que se va a utilizar en el esquema. El <columnName\> es un identificador de atributo, que es un identificador simple o un identificador de comillas dobles.

  • <columnType\>

    Especifica el tipo de columna que se va a utilizar en el esquema de la vista Document. El <columnType\> puede ser uno de los siguientes tipos de datos: Integer, Float, Boolean o Text.

  • [ and <columnName\> <columnType\> ]*

    Especifica nombres y tipos adicionales de columna del esquema de la vista Document. Siguen las mismas reglas que <columnName\> y <columnType\>.

En versiones anteriores de AQL, el esquema de la vista especial Document estaba predefinido y consistía en un solo campo (texto Texto) o en dos campos (texto texto, etiqueta Texto). La opción a elegir entre estos dos esquemas se decidía en el momento de la ejecución. Mediante la sentencia require document with columns, puede modificar el esquema de documento de entrada predeterminado en el momento de la compilación.

Notas de uso

  • Para código de AQL modular, el ámbito de cualquier sentencia require document with columns es el módulo en el que está definida.
  • Solo se permite una sentencia require document with columns por archivo de AQL. Dentro de un solo módulo, puede haber cero, uno o varios archivos de AQL que tengan una sentencia require document with columns. Todos los archivos de AQL dentro de un módulo fusionan sus sentencias require document with columns en el nivel de todo el módulo para formar una sentencia require document with columns de todo el módulo. Esta sentencia define el esquema de la vista Document para dicho módulo. Si ninguno de los archivos de AQL de un módulo o de un módulo genérico contienen una sentencia require, el módulo tiene un esquema predeterminado para la vista Document. Este esquema contiene dos columnas: (texto Texto, etiqueta Texto). No se establece ninguna columna predeterminada para la vista especial Document si al menos un archivo de AQL del módulo tiene una sentencia require document with columns.
  • Cuando se combinan varios módulos para formar un extractor, el esquema de la vista Document de todo el extractor se define mediante la unión libre de duplicados de esquemas Document para cada módulo. Se produce una excepción cuando se detecta que cualquier columna encontrada en varias sentencias require document with columns está en conflicto en sus requisitos de tipo en los módulos. Por ejemplo, un módulo requiere una columna X con el tipo Y cuando otro módulo que se carga con el mismo requiere una columna X con el tipo Z.
  • Se produce una excepción cuando se ejecuta un extractor si la tupla de documento de entrada proporcionada no contiene todas las columnas necesarias. También se produce una excepción si una columna no se ajusta a su tipo necesario correspondiente.
  • Cuando la sentencia require document with columns está dentro de un módulo, cada columna de la vista especial Document a la que se hace referencia se debe declarar en al menos una de las sentencias require document with columns. La sentencia se puede encontrar en distintos archivos de AQL dentro del mismo módulo. Sin embargo, todas estas sentencias require document with columns se fusionarán en el nivel del módulo para formar una sentencia require document with columns de todo el módulo.

Ejemplos

Ejemplo 1: Sentencia require document con tipos de columna similares

En el ejemplo siguiente se define un esquema de documento que contiene cuatro campos del mismo tipo. Este ejemplo de AQL espera que cada tupla de documento de la colección de datos contenga cuatro columnas, tal como se ha definido en el esquema de documento.

Consulte los formatos de documento de JSON para ver detalles sobre cómo crear un documento que se ajuste a un esquema.

module person;

-- Require document statement with similar field types

require document with columns
  inputDocumentText Text
  and inputDocumentLabel Text
  and documentAuthor Text
  and documentCreationDate Text;

Ejemplo 2: Sentencia require document con distintos tipos de columna

En el ejemplo siguiente se define un esquema de documento que contiene columnas con distintos tipos de campo.

module sample;

-- Require document statement with varying field types

require document with columns
  bookText Text
  and purchaseCount Integer
  and bookPrice Float
  and isBookPopular Boolean;

Ejemplo 3: Fusión de esquemas de documentos

En el ejemplo se describe cómo fusionar esquemas de documento que utilizan los archivos first.aql, last.aql y socialsecurity.aql.

first.aql:
    module person;
    require document with columns firstName Text;


last.aql:
    module person;
    require document with columns lastName Text;


socialsecurity.aql
    module person;
    require document with columns lastName Text
        and socialSecurityNo Integer;

El esquema fusionado es (firstName Text, lastName Text, socialSecurityNo Integer).

La sentencia create view

Los componentes de nivel superior de un extractor de AQL son sus vistas. Las vistas son sentencias lógicas que definen, pero no necesariamente calculan, un conjunto de tuplas.

Sintaxis

La sentencia create view puede tomar una de estas tres formas. La forma más sencilla define una vista lógica que se compone de las tuplas de una sola sentencia select o extract. La segunda es una forma de varias uniones que define una vista que comprende las tuplas que surgen de la unión de varios conjuntos de sentencias select o extract. La tercera forma define una nueva vista que contiene la diferencia entre las tuplas de dos sentencias select o extract.

create view <viewname\> as  <select or extract statement\>;
create view <viewname\> as  (<select or extract statement\>) union all (<select or extract statement\>)...;
create view <viewname\> as  (<select or extract statement\>) minus (<select or extract statement\>);

Descripción

  • <viewname\>

    El <viewname\> puede ser un identificador simple o un identificador de comillas dobles. No puede contener el carácter de punto.

  • <select or extract statement\>

    La sentencia select o extract crea una salida que se utiliza para calcular las tuplas de la vista que la contiene.

Notas de uso

  • Los nombres de las vistas distinguen entre mayúsculas y minúsculas. Por ejemplo, Person, PERSON y person son nombres de vistas diferentes
  • Dos vistas dentro del mismo módulo de AQL no pueden compartir un nombre, lo que les convertiría en duplicados. Sin embargo, pueden existir dos vistas con el mismo nombre en dos módulos diferentes, ya que sus nombres completos son exclusivos.
  • De forma predeterminada, una vista definida por la sentencia create view es una vista que no es de salida hasta que se especifica como una vista de salida.
  • Las sentencias select o extract de las formas union all y minus deben tener un esquema de salida compatible. Se considera que dos esquemas son compatibles para una operación union o minus si tienen el mismo número de columnas, los nombres de columna están en el mismo orden y tienen tipos de datos compatibles:
    • Los campos del mismo tipo de datos son compatibles con union o minus.
    • Los tipos de datos Span y Text son compatibles con union o minus. En el caso de una unión entre un tipo Span y un tipo Text, el tipo de salida es Span. Sin embargo, los objetos de tipo Text no se convierten automáticamente en un tipo de Span: la conversión automática solo se produce cuando lo requieren las llamadas de función.
    • Dos ScalarLists son compatibles con union o minus independientemente del tipo de escalar subyacente.

Ejemplos

Ejemplo 1: Creación de una vista con una sentencia select o extract

En el ejemplo siguiente, la vista Phone utiliza una sentencia extract para preparar sus tuplas. La vista PhoneNumber utiliza una sentencia select para elegir campos específicos de la vista Phone.

create view Phone as extract
  regexes /\+?([1-9]\d{2}\)\d{3}-\d{4}/
  and /\+?[Xx]\.?\d{4,5}/
  on D.text as num
from Document D;

create view PhoneNumber as
select P.num as num, LeftContextTok(P.num, 3) as lc
from Phone P;

Ejemplo 2: Creación de una vista con la sentencia Union All

La vista AllPhoneNums prepara un conjunto unionizado de las tuplas de las vistas Phone y Extension. Las dos vistas que se unionizan tienen el mismo esquema.

create view Phone as
extract
    regex /\+?([1-9]\d{2}\)\d{3}-\d{4}/
    on D.text as match
from Document D;

create view Extension as
  extract
    regex /\+?[Xx]\.?\d{4,5}/
    on D.text as match
from Document D;

create view AllPhoneNums as
  (select P.match from Phone P)
union all
  (select E.match from Extension E);

Ejemplo 3: Creación de una vista con la sentencia Minus

En el ejemplo siguiente se muestra cómo se puede utilizar minus para filtrar las tuplas no deseadas de un conjunto de tuplas.

create view Organization as
  (select * from OrganizationCandidates)
minus
  (select * from InvalidOrganizations);

Ejemplo 4: Compatibilidad de esquemas para minus

Es importante tener en cuenta que los valores span sobre distintos textos de destino no son del mismo tipo. Examine el siguiente ejemplo de AQL, donde se explica esta diferencia utilizando un literal String.

create view OneString as
  select 'a string' as match
  from Document D;

create view TheSameString as
  select 'a string' as match
  from Document D;

create view Subtraction as
  (select R.match from OneString R)
minus
  (select R.match from TheSameString R);

En lugar de la salida esperada de una lista de tuplas vacías, la salida es un conjunto de registros que tienen 'una serie (string)' como valor de campo.

Aunque el contenido de las vistas OneString y TheSameString parece idéntico, los valores de texto reales tienen distintos objetos de AQL subyacentes. El tipo OneString.match es 'Span over OneString.match'. El tipo TheSameString.match es 'Span over TheSameString.match'. Puesto que los tipos de campo son diferentes, no son compatibles a efectos de comparación.

Para obtener la salida deseada de la lista de tuplas vacías, debe comparar valores del mismo tipo. En el siguiente ejemplo, la función GetString() convierte objetos span en objetos string para pasar tipos compatibles a la operación minus.

create view Subtraction as
(select GetString(R.match) from OneString R)
minus
(select GetString(R.match) from TheSameString R);

Documentación de la sentencia create view con AQL Doc

El comentario AQL Doc correspondiente a una sentencia create view contiene la siguiente información:

  • Descripción general de la vista.
  • @field correspondiente a cada nombre de columna de la vista.

Ejemplo

/**
* Extracts all spans that match a phone number pattern from
* the input documents. It uses a regular expression to match
* phone number patterns.
* @field num phone number
* @field lc 3 tokens to the left of phone number*/

create view PhoneNumber as
select P.num as num, LeftContextTok(P.num, 3) as lc
from
(
extract
    regexes /\+?([1-9]\d{2}\)\d{3}-\d{4}/ and /\+?[Xx]\.?\d{4,5}/
    on D.text as num
from Document D
) P;

La sentencia output view

La sentencia output view define una vista para que sea una vista de salida. El componente de tiempo de ejecución solo genera las tuplas de las vistas que están marcadas como vistas de salida. El compilador de AQL solo compila las vistas marcadas como salida o exportación, o a las que se puede acceder desde vistas marcadas como salida o exportación.

Sintaxis

output view <view-name\> [as '<alias\>'];

Descripción

  • <view-name\>

    El nombre de la vista que se debe mostrar, tal como se conoce en el espacio de nombres del módulo actual. El <view-name\> es un identificador simple o un identificador de comillas dobles. La vista incorporada Document no se puede utilizar como salida.

  • [as '<alias\>']*

    Define un nombre de <alias\> para la vista de salida. Si no se especifica el alias opcional, la vista se utiliza como salida bajo los nombres siguientes:

    • En AQL modular, la vista se genera bajo el nombre <module-name\>.<view-name\> donde <module-name\> es el nombre del módulo donde se ha definido originalmente la vista (que puede ser diferente del módulo donde la vista es de salida).
    • En AQL 1.4 o anterior, la vista se genera bajo el nombre <view-name\> La sentencia output ... as <alias\> es útil cuando personaliza un extractor para distintos dominios. El uso del nombre de <alias\> al definir una vista de salida garantiza que los nombres de salida sean idénticos entre distintas implementaciones de la personalización.

    El nombre <alias\> no se puede utilizar en otra sentencia select o export. Debe especificar el <alias\> entre comillas simples y el nombre de <alias\> puede contener puntos.

Notas de uso

  • Cuando se ejecuta un extractor de AQL, calcula las tuplas resultantes para cada vista definida como vista de salida. Las tuplas de las vistas que no son de salida también se calculan, pero solo si se necesitan para calcular las tuplas resultantes de una vista de salida.
  • En AQL modular, la sentencia output view genera las tuplas de la vista bajo el nombre completo de vista que está cualificado por su nombre de módulo. Tenga en cuenta el ejemplo siguiente en el que la sentencia output view Person; da como resultado la salida de la vista personModule.Person:
module personModule;

create view Person as
  extract dictionary 'FamousPeopleDict' on D.text as match
  from Document D;

output view Person;

Este comportamiento se aplica a cualquier salida de vista sin un alias, independientemente de si la vista es la salida del módulo en el que se ha definido o de un módulo en el que se ha importado o incluso de si se ha importado mediante una importación de alias. Por ejemplo, en la vista de salida MyPerson, este ejemplo da como resultado la salida de la vista bajo su nombre completo original personModule.Person y no bajo su alias local MyPerson

module employeeModule;

import view Person from module personModule as MyPerson;

output view MyPerson;
  • La sentencia output alias es útil cuando se crean bibliotecas de extractores donde el mismo tipo de entidad puede tener muchas implementaciones diferentes, en función del dominio de la aplicación o del idioma de los documentos de entrada. La principal ventaja de utilizar un alias cuando se define una vista de salida es que garantiza una nomenclatura coherente en las vistas de salida. La lógica de programa de un usuario espera una nomenclatura coherente cuando se procesan varios módulos, cada uno de ellos tienen una vista de salida semánticamente similar. En AQL modular, cuando se utiliza un nombre de alias en una sentencia output view, las tuplas de una vista se muestran como salida bajo el nombre de alias especificado. Por ejemplo, el código siguiente mostraría como salida los resultados bajo el nombre de alias PersonAlias, y el nombre de alias no está cualificado con el prefijo de módulo.
module personModule;

create view Person as
  extract dictionary 'FamousPeopleDict' on D.text as match
  from Document D;

output view Person as 'PersonAlias';

Ejemplos

Los ejemplos siguientes contienen dos módulos, personModuleFrench y personModuleEnglish. Cada módulo genera una vista, denominada PersonNameFrench y PersonNameEnglish. Suponga que hay módulos similares, cada uno de los cuales genera vistas que son variantes semánticas de un extractor para los nombres de personas. Estos módulos se personalizan para distintos idiomas con la diferencia en la personalización de esta vista para un idioma de entrada especificado. Es posible que un usuario desee que un programa utilice módulos cuya vista de salida buscada se denomine PersonName, independientemente de los módulos que se procesen. Esta expectativa es normal, ya que se espera que cada módulo que se personaliza para un idioma, dominio u otro propósito produzca distintos resultados. El consumidor de estos módulos no tiene que modificar el algoritmo de su programa para ajustarse a los distintos nombres de vistas de salida cuando la semántica subyacente es similar.

En el ejemplo, debido a que se utiliza el alias PersonName, el consumidor no tiene que modificar el nombre de vista que se busca. Sin embargo, los resultados pueden variar en función de los módulos que se procesen. En el ejemplo, por ejemplo, las coincidencias resultantes están en francés (Ejemplo 1) y en inglés (Ejemplo 2).

Ejemplo 1: Las coincidencias resultantes están en francés

En el ejemplo siguiente se define una vista PersonNameFrench y se muestra bajo un nombre de alias de que no depende de la implementación, 'PersonName'.

module personModuleFrench;

create dictionary FrenchNames as
  ('Jean', 'Pierre', 'Voltaire', 'Francois', 'Marie', 'Juliette');

create view PersonNameFrench as
  extract dictionary 'FrenchNames'
  on D.text as name
  from Document D;

output view PersonNameFrench as 'PersonName';

Ejemplo 2: Las coincidencias resultantes están en inglés

En el ejemplo siguiente se define una vista PersonNameEnglish y se muestra bajo un nombre de alias de que no depende de la implementación, 'PersonName'.

module personModuleEnglish;

create dictionary EnglishNames as
  ('John', 'Peter', 'Andrew', 'Francis', 'Mary', 'Juliet');

create view PersonNameEnglish as
  extract dictionary 'EnglishNames'
  on D.text as name
  from Document D;

output view PersonNameEnglish as 'PersonName';

El consumidor de los módulos de ejemplo puede acceder a las tuplas de salida a través del nombre de alias 'PersonName'. No es necesario que el consumidor conozca el módulo real del que se recuperan los resultados.

La sentencia extract

La sentencia extract se utiliza para extraer las características básicas directamente del texto.

Sintaxis

extract <select list>,
  <extraction specification>
from <from list>
[having <having clause>]
[consolidate on <column> [using '<policy>']]
[limit <maximum number of output tuples for each document>];

Descripción

  • <select list\>

    Una lista delimitada por comas de expresiones de salida. Los resultados de estas expresiones de salida se devuelven como la salida de la sentencia extract, junto con las tuplas generadas por la evaluación de la especificación de extracción. El formato para <select list\> es el mismo que el <select list\> de una sentencia select.

  • <extraction specification\>

    Aplica la especificación de extracción a todas las tuplas de las vistas definidas en <from list\>. Cambia el nombre de las columnas de tuplas de acuerdo con sus alias correspondientes especificados en la sentencia extract. Puede utilizar una de las siguientes especificaciones de extracción:

    • Expresiones regulares
    • Diccionarios
    • Divisiones
    • Bloques
    • Categoría léxica
    • Patrones de secuencias
  • <from list\>

    Una lista delimitada por comas que es el origen de las tuplas de las que se van a seleccionar las características. El formato de <from list\> es similar al formato del <from list\> de la sentencia select. Sin embargo, si la sentencia extract no tiene una especificación de patrón, el <from list\> puede contener un único elemento.

  • [having <having clause\>]

    Especifica un predicado de filtrado (en el <having clause\>) que se aplica a cada tupla de salida extraída. Los nombres de campo que se especifican en <having clause\> hacen referencia a los alias que se especifican en <select list\>. Esta cláusula es opcional.

  • [consolidate on <column\>[using '<policy\>' ]]

    Define cómo manejar los intervalos de solapamiento tal como se definen en la consolidación <policy\>. En esta especificación, <column\> debe ser el nombre de un campo de salida, que forma parte de la sentencia extract. Esta cláusula es opcional.

  • [limit<maximum number of output tuples for each document\>]

    Limita el número de tuplas de salida de cada documento al máximo especificado. Esta cláusula es opcional.

Notas de uso

La semántica de la sentencia extract es la siguiente:

  • Evalúe la especificación de extracción sobre cada tupla de la relación de entrada. Para cada resultado que produce la extracción, se produce una tupla de salida que contiene los valores extraídos, junto con las columnas de la tupla original que se han especificado en <select list\>.
  • Cambie el nombre de las columnas de la tupla de salida de acuerdo con los alias especificados como parte de <select list\> y <extraction specification\>.
  • Aplique los predicados en la cláusula having opcional a la tupla de salida resultante.
  • Consolide las tuplas que pasan los predicados de acuerdo con la cláusula consolidation opcional y añada las tuplas resultantes a la salida.
  • Si está presente la cláusula limit opcional, limite la salida al número especificado de tuplas para cada documento.

La semántica de la cláusula from de una sentencia extract pattern es distinta de las otras formas de sentencias extract que no tienen una especificación de patrón. Si al menos una de las vistas de <from list\> no contiene tuplas en un documento determinado, la salida de la sentencia extract está vacía. Esta salida está vacía porque el conjunto de todas las combinaciones de tuplas de las vistas de entrada está vacío.

En el caso especial de las sentencias extract pattern, la cláusula from es un marcador que declara los nombres de relaciones que intervienen en la especificación de patrón. La semántica de la sentencia solo está controlada por la especificación de patrón. En particular, la salida de la sentencia puede no estar vacía incluso cuando algunas de las vistas de entrada están vacías.

Ejemplos

Ejemplo 1: Extracción de números de teléfono de una vista predefinida

Esta sentencia extract de ejemplo evalúa una expresión regular correspondiente a números de teléfono de Estados Unidos de un texto de entrada representado por la vista predefinida Document. Luego la salida se restringe a los tres primeros números de teléfono que se identifican por cada documento. Los nombres de campo de la cláusula having hacen referencia a los alias que hay al principio de la sentencia extract.

create view PhoneNumbers as
  extract
    D.text as documentText,
    regex /\d{3}-\d{3}-\d{4}/ on D.text as phoneNumber
from Document D
having MatchesRegex(/\d{3}.*/, phoneNumber)
limit 3;

Ejemplo 2: Extracción de bloques de palabras en mayúsculas

En este ejemplo, la sentencia extract identifica bloques de entre dos y tres palabras mayúsculas. En AQL, un bloque es un tramo contiguo de señales, en este caso entre dos y tres señales. En este ejemplo también se utiliza una política de consolidación para excluir bloques que están contenidos en bloques grandes del conjunto de tuplas salida.

create view CapitalizedWord as
  extract
    regex /[A-Z][a-z]*/
            with flags 'CANON_EQ'
        on 1 token in D.text
        as word
from Document D;

create view TwoToThreeCapitalizedWords as
  extract blocks
  with count between 2 and 3
  and separation 0 tokens
  on CW.word as capswords
from CapitalizedWord CW
consolidate on capswords using 'ContainedWithin';

La cláusula consolidate se aplica al campo capswords mediante la especificación de bloques de extracción. La diferencia es que el campo de destino al que se hace referencia en la cláusula consolidation es un campo de salida de la sentencia extract. El campo de destino de la sentencia select es un campo de entrada. Este comportamiento es similar al de la cláusula having.

Ejemplo 3: Una sentencia extract o select anidada como un nombre de vista

La vista de entrada para una sentencia extract puede ser un nombre de vista, como en el Ejemplo 2, o una sentencia extract o select anidada, como en este ejemplo:

create view SampleExtract as
  extract
  regex /foo/ on E.foobar as foo
  from
    (extract regex /foobar/ on D.text as foobar
  from Document D) E;

Ejemplo 4: Extracción de una sentencia con una lista select

En este ejemplo, extraemos coincidencias de un patrón y, al mismo tiempo, seleccionamos varios atributos de las vistas de entrada.

create view Person as
  extract.F.first as first, M.initial as middle, L.last as last
          pattern ('Mr.'|'Ms.'|'Miss')? (<F.first> <M.initial>? <L.last>)
                    return group 0 as reference
                    and group 1 as salutation
                    and group 2 as name
  from FirstName F, MiddleInitial M, LastName L;
  • Expresiones regulares Utilice una especificación de extracción de expresión regular para identificar los patrones coincidentes contenidos en la expresión regular en el texto de entrada.
  • Diccionarios Utilice la especificación de extracción de diccionario para extraer series del texto de entrada que están contenidas en un diccionario de series de caracteres.
  • Diccionarios Utilice la especificación de extracción de división (split) para dividir un tramo grande en varios tramos de menor tamaño.
  • Bloques Utilice la especificación de extracción de bloques para identificar los bloques de tramos contiguos en el texto de entrada.
  • Categoría léxica Utilice la especificación de extracción de categoría léxica (part-of-speech) para identificar las ubicaciones de distintas categorías léxicas en el texto de entrada.
  • Patrones de secuencias Utilice la especificación de extracción de patrón para realizar comparaciones de patrones entre un documento de entrada y otros tramos extraídos del documento de entrada.

Expresiones regulares

Utilice una especificación de extracción de expresión regular para identificar los patrones coincidentes contenidos en la expresión regular en el texto de entrada.

Sintaxis

regex[es] /<regex1>/
         [and /<regex2>/ and ... and /<regex n>/]
       [with flags '<flags string>']
on <token spec>] <name>.<column>
<grouping spec>

Descripción

  • regex[es] /<regex1\>/

    Especifica las expresiones regulares que se van a utilizar en la extracción. De forma predeterminada, AQL utiliza la sintaxis de Perl para expresiones regulares, lo que significa que los literales de expresión regular están especificados entre dos caracteres de barra inclinada invertida (//). Las secuencias de caracteres de escape de las expresiones regulares prevalecen sobre otros caracteres de escape. AQL permite expresiones regulares en sintaxis de serie de SQL, de modo que una expresión regular correspondiente a números de teléfono de Estados Unidos se puede expresar como en cualquiera de los siguientes ejemplos:

    /\d{3}-\d{5}/
    
    '\\d{3}-\\d{5}'
    
  • [and /<regex2\>/ and ... and /<regex n\>/ ]

    Muestra más expresiones regulares que se pueden utilizar en la extracción.

  • [with flags '<flags string\>']

    Especifica una combinación de distintivos para controlar la comparación de expresiones regulares. Este parámetro es opcional. Estos distintivos corresponden a un subconjunto de los distintivos definidos en la implementación de Java™. Si no se especifica la serie de distintivos, AQL solo utiliza el distintivo DOTALL de forma predeterminada.

    Para especificar varios distintivos, debe separarlos con el carácter |. Por ejemplo, para especificar una comparación de varias líneas, comparación que no distingue entre mayúsculas y minúsculas, y conversión a mayúsculas de Unicode, utilice la serie de distintivos 'MULTILINE|CASE_INSENSITIVE|UNICODE'.

  • [<token spec\>]

    Indica si se debe comparar la expresión regular solo en los límites de la señal.

    ... [[between <number> and] <number> token[s] in] ...
    

    Las restricciones de señal son una parte opcional de la especificación. Si se omiten las restricciones de señal, AQL devuelve la coincidencia más larga que no se solape de cada posición de carácter del texto de entrada. Si hay restricciones de señal, la sentencia extract devuelve la coincidencia más larga de cada límite de señal que esté dentro del rango especificado de señales en cuanto a longitud. Cada coincidencia devuelta debe empezar al principio de una señal y finalizar al final de una señal. Si hay varias coincidencias solapadas, la sentencia extract las devuelve todas.

    Las ubicaciones de los límites de señal dependen del señalizador que utilice el componente de tiempo de ejecución para señalizar el documento. Si el motor utiliza el señalizador estándar, una señal se define como una secuencia de caracteres de palabra o como un solo carácter de puntuación.

    Por ejemplo, tenga en cuenta la siguiente serie:

    "The fish are pretty," said the boy.
    

    Los límites de la señal están identificados en estas ubicaciones:

    ["][The] [fish] [are] [pretty][,]["] [said] [the] [boy][.]
    
  • <name\>.<column\>

    El nombre de vista y el nombre de columna donde se aplica la expresión regular.

  • <grouping spec\>

    Determina cómo se debe manejar la captura de grupos en la expresión regular. Los grupos de captura son regiones de la coincidencia de la expresión regular que se identifican entre paréntesis en la expresión original. Por ejemplo, la expresión (fish)(cakes) tiene tres grupos de captura:

    • El grupo 0 es la coincidencia entera fishcakes.
    • El grupo 1 es fish.
    • El grupo 2 es cakes. Cuando especifica los ID de grupo en la cláusula return de la sintaxis, cada ID de grupo debe corresponder a un grupo válido dentro de cada expresión regular especificada como parte de la cláusula regex de extracción en la sintaxis.

    Este es el formato de la especificación de agrupación:

    return
        group <number> as <name>
        [and group <number> as <name>]*
    

    Para devolver solo el Grupo 0 (la coincidencia completa), puede utilizar un formato alternativo más corto como en el Ejemplo 1. Este formato es equivalente a return group 0 as <name>. <name> puede ser un identificador simple o un identificador de comillas dobles.

Notas de uso

  • En general, AQL da soporte a las mismas características que la implementación de expresión regular de Java 5, tal como se describe en [Patrones de clase: java.util.regex. El componente de tiempo de ejecución contiene varias implementaciones de motor de expresión regular, incluida la implementación incorporada de Java. Durante la compilación, el optimizador examina cada expresión regular y elige el motor más rápido que puede ejecutar la expresión.

  • Los motores de ejecución alternativos pueden tener una semántica ligeramente diferente para determinados casos. En particular, AQL no garantiza el orden en el que se evalúan las alternativas.

    Por ejemplo, suponga que una sentencia extract coincide con la expresión regular /fish|fisherman/, sobre el texto 'fisherman'. La sentencia puede coincidir con 'fish' o con 'fisherman', en función de, motor de expresión regular que se utilice internamente.

Serie de distintivo de AQL Distintivo de Java Descripción
CANON_EQ CANON_EQ Equivalencia canónica: distintas codificaciones Unicode del mismo carácter se consideran equivalentes.
CASE_INSENSITIVE CASE_INSENSITIVE Realizar una comparación que no distingue entre mayúsculas y minúsculas. De forma predeterminada, la comparación que no distingue entre mayúsculas y minúsculas presupone que solo se comparan los caracteres del juego de caracteres US-ASCII. La comparación que no distingue entre mayúsculas y minúsculas con reconocimiento de Unicode se puede habilitar especificando el distintivo UNICODE con este distintivo.
UNICODE UNICODE_CASE Si se especifica una comparación que no distingue entre mayúsculas y minúsculas, utilice la conversión a mayúsculas de Unicode para determinar si dos caracteres son equivalentes en la comparación que no distingue entre mayúsculas y minúsculas de modo coherente con el estándar de Unicode. De forma predeterminada, en la comparación que no distingue entre mayúsculas y minúsculas se presupone que solo se comparan los caracteres del juego de caracteres US-ASCII. Nota: el comportamiento de este distintivo no está definido si se utiliza sin el distintivo CASE_INSENSITIVE.
DOTALL DOTALL Hacer que el carácter de punto . coincida con todos los caracteres, incluidos los de nueva línea.
LITERAL LITERAL Tratar la expresión como una secuencia de caracteres literales, pasando por alto las secuencias de escape de una expresión regular normal.
MULTILINE MULTILINE Hacer que los caracteres ^ y $ coincidan con el principio y el final de cualquier línea, en contraposición con el principio y el final de todo el texto de entrada.
UNIX_LINES UNIX_LINES Tratar solo el carácter de nueva línea de UNIX™ como un salto de línea, pasando por alto el carácter de retorno de carro \r.
  • Siga estas directrices para hacer que los extractores se ejecuten más rápido y resulten más fáciles de mantener:
    • Evite expresiones regulares largas y complejas y utilice expresiones regulares más sencillas y cortas que se combinen con sentencias de AQL.
    • Evite el uso innecesario de lookahead y de lookbehind en expresiones regulares. Por lo general, puede lograr el mismo efecto añadiendo predicados a la cláusula having de la sentencia extract.
    • Utilice las restricciones de señal en las especificaciones de extracción de expresiones regulares cuando sea posible.

Ejemplos

Ejemplo 1: Utilización de equivalencia Unicode canónica para determinar coincidencias

En este ejemplo se muestra cómo buscar palabras en mayúscula que no son nombres propios. Se utiliza la equivalencia canónica de caracteres Unicode para determinar las coincidencias. Observe el uso del distintivo ‘CANON_EQ’ y que la expresión regular se ejecuta sobre las señales:

create dictionary FirstNamesDict as
  (
  'Aaron', 'Matthew', 'Peter'
  );
create view NotFirstName as
  extract
    regex /[A-Z][a-z]*/
    with flags 'CANON_EQ'
    on 1 token in D.text
    as word
from Document D
  having Not(ContainsDict('FirstNamesDict', word));

Ejemplo 2: Utilización de grupos de captura

En el ejemplo siguiente se muestra el uso de la captura de grupos en una sentencia extract regex. El código extrae los campos de un número de teléfono de Estados Unidos mediante el uso de grupos de captura:

create view Phone as
  extract regex /(\d{3})-(\d{3}-\d{4})/
    on between 4 and 5 tokens in D.text
    return
      group 1 as areaCode
      and group 2 as restOfNumber
      and group 0 as fullNumber
from Document D;

Ejemplo 3: Aplicación de varias expresiones regulares sobre el texto de entrada

Puede especificar varias expresiones regulares en la misma sentencia extract regex utilizando la sintaxis de regexes.

create view PhoneNum as
  extract regexes
    /(\d{3})-(\d{3}-\d{4})/ and /[Xx]\d{3,5}/
        on between 1 and 5 tokens in D.text as num
from Document D;

Ejemplo 4: Uso inadecuado de la especificación de agrupación

La expresión regular de este ejemplo de código no contiene ni group -1 ni group 3000. Esto da lugar a un error de compilación.

create view ErrorExample as
    extract regex /(\d+)/
    on D.text
    return group -1 as wrongGroup and
          group 3000 as nonExistentGroup
from Document D;

Diccionarios

Utilice la especificación de extracción de diccionario para extraer series del texto de entrada que están contenidas en un diccionario de series de caracteres.

Sintaxis

    dictionar[y|ies]
        '<dictionary>'
        [and '<dictionary>' and ... and '<dictionary>']
        [with flags '<flags string>']

Descripción

  • '<dictionary\>'

    Hace referencia a un diccionario que se crea mediante la sentencia create dictionary, la sentencia create external dictionary o un archivo de diccionario en el sistema de archivos.

  • [and '<dictionary\>' and ... and '<dictionary\>']

    Hace referencia a los diccionarios adicionales que se van a utilizar para la extracción.

  • [with flags'<flags string\>']

    Controla la comparación de diccionario. Actualmente, se da soporte a dos opciones:

    • Exacta

      Proporciona coincidencias exactas que distinguen entre mayúsculas y minúsculas.

    • IgnoreCase

      Proporciona coincidencias que no distinguen entre mayúsculas y minúsculas.

Si no se especifica ningún distintivo, el diccionario realiza la comparación en función de cualquier distintivo que se haya especificado al crearlo. Si no se ha especificado ningún distintivo durante la creación, realiza la comparación utilizando solo el distintivo IgnoreCase.

Notas de uso

  • Los diccionarios siempre se evalúan en los límites de la señal. En concreto, una entrada de diccionario compara una región de texto si la primera señal de la entrada coincide con la primera señal de la región de texto, la segunda señal de la entrada coincide con la segunda señal de la región de texto, y así sucesivamente. Los caracteres contenidos entre dos señales consecutivas se pasan por alto.

    Por ejemplo, suponga que está utilizando un modelo de señalización basado en un espacio en blanco simple que resulta apropiado para un idioma como el inglés. Suponga también que el texto de entrada es “Let’s go fishing!” Si un diccionario contiene el término go fish, no existe ninguna coincidencia en el texto para Let's go fishing!. Sin embargo, si el diccionario contiene la entrada go fishing (observe que hay dos espacios en blanco entre go y fishing), existe una coincidencia en el texto Let's go fishing!. El espacio en blanco especifica que go y fishing son dos señales distintas. Si hay uno o varios caracteres de espacio en blanco entre las dos señales go y fishing en el texto de entrada, hay una coincidencia.

    Para cada coincidencia de una entrada de diccionario con el texto de entrada, la sentencia extract dictionary genera una tupla de salida.

Ejemplos

Ejemplo 1: Extracción de términos de archivos de diccionario

Busque nombres de persona utilizando archivos de diccionario de nombres y apellidos comunes y una comparación que distingue entre mayúsculas y minúsculas.

create view Name as
  extract
    dictionaries
        'first.dict'
        and 'last.dict'
    with flags 'Exact'
        on D.text
        as name
from Document D;

A continuación se muestra el contenido de ejemplo de last.dict:

#Dictionary for surnames
Anthony
Aparicio
Cate
Lehmann
Radcliff

A continuación se muestra el contenido de ejemplo de first.dict:

#Dictionary for given names
Aaron
Candra
Freeman
Mathew
Matthew
Zoraida

Nota:

  • Un sistema de archivos de diccionario al que se hace referencia directamente en una sentencia extract dictionary no se puede configurar de forma explícita con un conjunto de idiomas para que los diccionarios se compilen y se apliquen en tiempo de ejecución. En su lugar, el conjunto de idiomas se especifica con la sentencia set default dictionary language si el módulo contiene esta sentencia.

    Por lo tanto, no se recomienda la referencia directa de los archivos de diccionario en una sentencia extract dictionary y es posible que se elimine esta opción en el futuro. La práctica recomendada consiste en definir de forma explícita un objeto de diccionario mediante la sentencia create dictionary from file y, a continuación, utilizar dicho diccionario en la sentencia extract.

  • El compilador y el componente de tiempo de ejecución intentan localizar los archivos de diccionario a los que se hace referencia en AQL bajo la vía de acceso de búsqueda configurada.

Ejemplo 2: Extracción de términos de un diccionario en línea

Encuentre conjunciones utilizando un diccionario en línea y la comparación predeterminada que no distingue entre mayúsculas y minúsculas.

create dictionary ConjunctionDict as
  (
    'and', 'or', 'but', 'yet'
  );

create view Conjunction as
  extract
    dictionary 'ConjunctionDict'
        on D.text
        as name
from Document D;

Divisiones

Utilice la especificación de extracción de división (split) para dividir un tramo grande en varios tramos de menor tamaño.

Sintaxis

split using <name>.<split point column>
    [retain [right|left|both] split point[s]]
    on <name>.<column to split>
    as <output name>

Descripción

La especificación de extracción split toma dos argumentos:

  • Una columna que contiene el tramo de destino largo del texto.
  • Una columna que contiene puntos de división.

El algoritmo de división funciona en dos pasadas sobre la vista de entrada. La primera pasada agrupa todas las tuplas de entrada por columna de destino. La segunda pasada recorre las tuplas de cada grupo, dividiendo la columna de destino con cada valor de la columna de división.

  • <name\>.<split point column\>

    Especifica los puntos de división para la extracción.

  • [retain [right|left|both] split point[s]]

    Especifica cómo se debe tratar los puntos finales de la izquierda y de la derecha de cada resultado. Este argumento es opcional.

    • Si se especifica retain left split point, cada tramo de la salida también contiene el punto de división de su izquierda, si existe.
    • Si se especifica retain right split point, el sistema hace que cada punto de salida contenga el punto de división a su derecha.
    • La extracción de división también acepta valores nulos como puntos de división. Para cada valor de este tipo, la extracción devuelve una tupla que contiene todo el tramo de entrada.
  • <name\>.<column to split\>

    Especifica la columna de destino de la extracción.

  • <output name\>

    Define el nombre de la salida de la extracción.

Ejemplos

Ejemplo 1: Puntos de división y la cláusula retain

Si los puntos de división son todas las instancias de la palabra fish de la frase fish are swimming in the fish pond, las distintas versiones de la cláusula retain tienen los siguientes efectos:

  • retain clause omitted

    " are swimming in the " and " pond"

  • retain right split point

    " are swimming in the fish" and " pond"

  • retain left split point

    "fish are swimming in the " and "fish pond"

  • retain both split points

    "fish are swimming in the fish" and "fish pond"

Ejemplo 2: Extracción de división

En este ejemplo se divide el documento en frases. En primer lugar, utiliza una expresión regular para identificar los límites de la frase y luego utiliza la especificación de extracción de división para dividir el texto del documento en los límites de la frase.

create dictionary AbbreviationsDict as
  (
  'Cmdr.',
  'Col.',
  'DR.',
  'Mr.',
  'Miss.');

create view Sentences as
  extract
    split using B.boundary
        retain right split point
        on B.text
        as sentence
  from (
    extract
        D.text as text,
        regex /(([\.\?!]+\s)|(\n\s*\n))/
        on D.text as boundary
        from Document D
    -- Filter the candidate boundaries.
      having Not(ContainsDict('AbbreviationsDict',
            CombineSpans(LeftContextTok(boundary, 1), boundary)))
      ) B;

Bloques

Utilice la especificación de extracción de bloques para identificar los bloques de tramos contiguos en el texto de entrada.

Sintaxis

blocks
    with count [between <min\> and] <max\>
    and separation [between 0 and] <max\> (tokens| characters)
    on <name\>.<column containing spans\>
    as <output name\>

Descripción

  • with count [between<min\> and] <max\>

    Especifica el número de tramos que pueden componer un bloque. Los valores <min\> y <max\> especifican el número mínimo y máximo de intervalos que pueden constituir un bloque.

  • [between 0 and] <max\>

    Especifica la distancia de separación que se permite entre tramos antes de que dejen de considerarse contiguos.

  • (tokens| characters)

    Especifica si la distancia de separación del tramo representa el número de señales o el número de caracteres.

  • <name\>.<column containing spans\>

    El nombre de vista y el nombre de columna a los que se debe aplicar el operador de bloque.

  • <output name\>

    Especifica el nombre de la salida del operador de bloque.

Notas de uso

  • Si las exploraciones de entrada contienen varios bloques solapados en los tramos de entrada, una sentencia de extracción de bloque devuelve todos los bloques posibles. Utilice la consolidación para filtrar los bloques redundantes.
  • Una sentencia extract con una especificación de extracción de bloque genera bloques que consisten en una agregación de valores de un determinado campo de varias tuplas de entrada. Por lo tanto, su lista select no puede incluir campos de su vista de entrada.

Ejemplos

Ejemplo 1: Extraer bloques de palabras dentro de un rango de caracteres

En el código siguiente, la vista TwoToThreeCapitalizedWords identifica bloques de entre dos y tres palabras en mayúsculas con una distancia máxima de 100 entre sí.

create view CapitalizedWords as
  extract
    regex /[A-Z][a-z]*/
        with flags 'CANON_EQ'
        on 1 token in D.text
        as word
from Document D;

create view TwoToThreeCapitalizedWords as
  extract blocks
    with count between 2 and 3
    and separation between 0 and 100 characters
    on CW.word as capswords
from CapitalizedWords CW;

Ejemplo 2: Extraer bloques de palabras dentro de un rango de señales

El código siguiente identifica bloques de exactamente dos palabras en mayúsculas con una distancia máxima de cinco señales entre sí.

create view TwoCapitalizedWords as
extract blocks
    with count 2
    and separation between 0 and 5 tokens
    on CW.word as capswords
from CapitalizedWords CW;

Categoría léxica

Utilice la especificación de extracción de categoría léxica (part-of-speech) para identificar las ubicaciones de distintas categorías léxicas en el texto de entrada.

Sintaxis

part_of_speech
 '<part of speech spec>'
 [and '<part of speech spec>']*
 [with language '<language code>']
 [and mapping from <mapping table name>]
 on <input column> as <output column\>
 from <input view>

Descripción

  • '<part of speech spec\>'

    Identifica las categorías léxicas de las que extraer texto de entrada. El '<part of speech spec\>' es una de las series siguientes:

    • Una serie de caracteres que contiene una lista delimitada por comas de las etiquetas de categoría léxica generadas por el señalizador multilingüe
    • Una combinación de un nombre interno de categoría léxica y distintivos, definida en una tabla de correlaciones
  • [and '<part of speech spec\>']*

    Identifica las etiquetas de categorías léxicas adicionales para la extracción.

  • [with language '<language code\>']

    Especifica el idioma que se va a utilizar en la extracción. El <language code\> es un código de dos letras, en minúsculas, como 'en' o 'ja'. Si se omite este argumento, se supone que el idioma para la extracción de categoría léxica es el inglés

  • [and mapping from <mapping table name\>]

    Especifica el nombre de una tabla de AQL que correlaciona etiquetas de categoría léxica sin formato, como por ejemplo "NOUN", con combinaciones de categorías léxicas y distintivos de nivel general. Mientras que la tabla de correlaciones opcional puede tener nombres de variables, la tabla de correlaciones de categorías léxicas deben tener estos nombres de columna:

    • tag

      La columna que contiene la etiqueta de categoría léxica del señalizador multilingüe.

    • basetag

      La columna que contiene la etiqueta interna correspondiente.

    • flagstr

      La columna que contiene una lista delimitada por comas de distintivos que están asociados con la categoría léxica indicada.

    La tabla de correlaciones se debe definir mediante la sentencia create table en el mismo módulo que la sentencia part_of_speech de extracción que la utiliza. No puede ser una tabla importada y no puede ser una tabla externa.

    create table POSMapping_EN(tag Text, basetag Text, flagstr Text)
    as values
     ('CCONJ','CONJ','coordinating'),
     ('SCONJ','CONJ','subordinating');
    
  • <input column\>

    Especifica la columna de la vista de entrada de la que se debe extraer la información de la categoría léxica.

  • <output column\>

    Especifica el nombre de la columna a la que se envían los tramos de las señales con las categorías léxicas indicadas.

  • <input view\>

    Especifica la vista de entrada de la que se debe extraer la información de la categoría léxica.

Notas de uso

  • La extracción de categorías léxicas solo funciona cuando se utiliza el señalizador multilingüe. Si el sistema utiliza el señalizador estándar, una extracción de tipo part_of_speech genera un error.

Etiquetas de categoría léxica correspondientes a idiomas

Para todos los idiomas admitidos, el señalizador multilingüe utiliza las etiquetas de categoría léxica que se muestran en la tabla siguiente.

Etiqueta Descripciones
ADJ adjetivo
ADP adposición
ADV adverbio
AUX auxiliar
CCONJ conjunción coordinada
DET determinante
INTJ interjección
NOUN sustantivo
NUM número
PART partícula
PRON pronombre
PROPN nombre propio
PUNCT puntuación
SCONJ conjunción de subordinación
SYM símbolo
VERB verb
X otros

Ejemplos

Ejemplo 1: Utilización de una etiqueta de categoría léxica directamente en una sentencia extract

La vista EnglishNoun extrae sustantivos en inglés (singular o incontable) o nombres propios (singular).

create view EnglishNoun
as extract parts_of_speech 'NOUN' and 'PROPN'
with language 'en' on D.text
as noun from Document D;

Patrones de secuencias

Utilice la especificación de extracción de patrón para realizar comparaciones de patrones entre un documento de entrada y otros tramos extraídos del documento de entrada.

Sintaxis

La sintaxis general de un patrón de secuencia consiste en especificar primero el patrón que se va a comparar en el texto y, a continuación, especificar lo que debe devolver el extractor. La parte final del patrón de secuencia especifica la entrada para el patrón; puede ser una columna de una vista definida anteriormente o puede ser todo el texto del documento.

pattern <pattern specification> [return clause] [with inline_match on <viewname.colname>]

Descripción

  • <pattern specification\>

    Un <pattern specification\> se compone de varios átomos. Un átomo individual puede ser una columna de una vista ya definida, una serie de caracteres fija o una expresión regular. Puede especificar los átomos de modo que sean opcionales y repetitivos, y puede especificar los espacios de señales entre átomos.

    La especificación de patrón forma parte de una sentencia AQL más larga, que incluye una cláusula extract.

    A continuación se muestra un ejemplo sencillo de cómo crear una vista que contenga tres coincidencias adyacentes de vistas definidas anteriormente. En este ejemplo, se devuelve toda la combinación, a la que hace referencia group 0:

    create view Money as
    extract pattern <C.match> <N.match> <Q.match>
    return group 0 as  match
    from Currency C, Number N, Quantifier Q;
    

    Si no es necesario que los átomos sean exactamente adyacentes entre sí, entonces puede utilizar los espacios de señales entre los átomos para permitir más coincidencias. En este ejemplo se encuentran las menciones a personas que se encuentran entre 0 y 2 señales por un número de teléfono. Observe la construcción de <Token>{0,2}, que indica que se permite un intervalo de 0 a 2 señales entre la persona y las anotaciones telefónicas.

    create view Phone as
    extract regex /(\d{3})-(\d{3}-\d{4})/
      on between 4 and 5 tokens in D.text
      return
       group 1 as areaCode
       and group 2 as restOfNumber
       and group 0 as fullNumber
    from Document D;
    create view PersonPhone as
    extract
      pattern (<P.name>) <Token>{0,2} (<Ph.fullNumber>)
      return group 0 as match
       and group 1 as person
       and group 2 as phone
    from Person P, Phone Ph;
    

    Las construcciones con espacio de señales solo se pueden producir en expresiones en secuencia. Además, cada espacio de señal de una secuencia debe ir precedida y seguida de una expresión "non-token gap". Como resultado, las sentencias extract pattern generan excepciones:

    -> pattern consisting only of a token gap is an error
    extract pattern <Token> as match from ...
    -> pattern beginning with a token gap is an error
    extract pattern <Token> {0,2} <Ph.phone> as match from ...
    -> pattern ending with a token gap is an error
    extract pattern <P.name> <Token> ?  as match from ...
    -> group consisting only of a token gap is an error
    extract pattern <P.name> (<Token>)  <Ph.phone> as match from ...
    

    Utilice la sintaxis (min,max) para indicar el número de veces que se repite cada átomo. También puede utilizar la sintaxis ? para indicar que un átomo o átomo repetitivo es opcional. Los átomos, junto con sus indicaciones sobre repetición y opcionalidad, se combinan para crear secuencias.

    A continuación se muestra un ejemplo más complejo en el que se repiten elementos. Encuentra nombres de hoteles candidatos identificando apariciones de entre una a tres palabras en mayúsculas, seguidas de una señal de 'Hotel 'o' hotel'.

    create view CapsWord as
    
    extract
        regex /[A-Z][a-z]*/
           on 1 token in D.text
           as word
    from Document D;
    
    create view HotelCandidate as
    extract
      pattern <CW.word>{1,3} /[Hh]otel/ as hotelname
    from CapsWord CW;
    

    También puede utilizar el operador | para indicar una opción entre átomos, como en extract pattern <A.match>| <B.match> <C.match> as match from Apple A, Bacon B, Chocolate C;. La explicación de este patrón podría ser “comparar un A.match O una secuencia de B.match seguida de C.match. En el Ejemplo 1 puede ver un ejemplo completo en el que se utiliza el operador |.

    Después de haber creado el patrón, cada coincidencia con el <pattern specification> construye un resultado de salida de acuerdo con la cláusula de retorno de la especificación de patrón, así como el <select list> opcional al principio de la sentencia extract. Los resultados se filtran y se consolidan de acuerdo con las cláusulas having, consolidate y limit de la sentencia extract. Por ejemplo, si hay varias coincidencias que se solapan para la especificación de patrón, se devuelven todas las coincidencias posibles y puede utilizar la cláusula consolidation para filtrar las salidas redundantes.

    Partiendo del ejemplo anterior, ahora suponga que el objetivo es eliminar las coincidencias que contienen la palabra 'Sheraton' y consolidar las coincidencias resultantes eliminando las contenidas en una coincidencia mayor. Por ejemplo, no queremos encontrar “Best Garden Hotel” y también “Garden Hotel” en el mismo tramo de texto.

    create view HotelCandidate as
    extract
      pattern <CW.word>{1,3} /[Hh]otel/ as hotelname
    from CapsWord CW
    having Not(ContainsRegex(/.*Sheraton.*/,hotelname))
    consolidate on hotelname using 'ContainedWithin';
    

Ahora que está familiarizado con la sintaxis y con algunos ejemplos, consulte este diagrama, en el que se describe la sintaxis completa de la especificación de patrón. Consulte esta sintaxis completa cuando empiece a crear patrones para ver cómo estructurar el patrón que desea construir.

Si está familiarizado con las expresiones regulares basadas en caracteres POSIX, observa que la sintaxis es similar. En este caso, la sintaxis permite elementos con espacios en blanco y también se define el orden de un elemento para que se ajuste a la finalidad de AQL. Observe que en este caso el término Alternation significa opción a elegir. El uso de una barra vertical entre elementos indica que existen opciones, que se pueden agrupar mediante ( ).

Pattern   -> Alternation
Alternation  -> Sequence | Sequence | ... | Sequence
Sequence   -> Optional Optional ... Optional
Optional   -> Repeat | Repeat ? Repeat     -> Atom | Atom { min, max }
Atom     -> <view_name.column_name>
     'string'
   <'string' [match parameters]>
     /regex/
     <Token>
     Group
Group -> ( Pattern )

En concreto, un átomo puede tener seis formatos:

  • <view_name.column_name\>

    Especifica una columna de una de las vistas, tablas o referencias de función de tabla que se mencionan la lista from de la sentencia extract pattern.

  • 'string'

    Especifica una coincidencia con la serie especificada utilizando la semántica de coincidencia de diccionario predeterminada de AQL.

  • <'string' [match parameters]\>

    Especifica una coincidencia con la serie especificada utilizando la semántica de coincidencia de diccionario que se especifica mediante los [match parameters]. El formato de los [match parameters] es case (exact | insensitive). Este formato especifica el tipo de conversión a mayúsculas que se utiliza para determinar las coincidencias de series. Para especificar una coincidencia exacta entre mayúsculas y minúsculas, seleccione exact. Para especificar una coincidencia que no tenga en cuenta mayúsculas y minúsculas, seleccione el valor predeterminado insensitive.

  • /regex/

    Especifica una coincidencia de expresión regular basada en caracteres con la coincidencia restringida a una sola señal en el texto del documento. Además, la sintaxis permite que se especifique una construcción de espacio de señal especial en una expresión de secuencia para indicar una coincidencia entre el número min y max de señales.

  • <token\>

    Una coincidencia para cualquier señal.

  • [return clause]

    Genera los valores extraídos para cada coincidencia de la expresión de patrón de acuerdo con la cláusula return. La cláusula return tiene la misma semántica que la cláusula return de una sentencia extract regex.

  • [with inline_match on <viewname.colname\>]

    Para los átomos como, por ejemplo serie y átomos de expresión regular, la cláusula with inline_match determina el objeto de texto que utiliza el sistema para la extracción de tipo serie o regex. Por ejemplo, si la cláusula es with inline_match on Email.subject, todos los diccionarios y las expresiones regulares definidos en línea en la especificación de patrón se aplican al campo de asunto de la vista Email. Si no se especifica with inline_match, la extracción de expresiones de serie y regulares se ejecuta de forma predeterminada en Document.text entero. En este caso, viewname debe ser el nombre de una vista o una tabla definida en el módulo actual o bien importada de otro módulo; las referencias a funciones de tabla no se permiten en la cláusula inline_match.

  • [with language as <language code(s)\>]

    Especifica una lista delimitada por comas de códigos de idioma de dos letras, como por ejemplo en (inglés) o zh (chino) para los idiomas en los que se evalúa la serie. No hay ninguna coincidencia en los documentos cuyo código de idioma no esté contenido en esta serie. Si se omite el parámetro language, el idioma de evaluación se establece de forma predeterminada en uno de los siguientes conjuntos de idiomas:

    • Si se declara, los conjuntos de idiomas que se especifican mediante la sentencia set default language en el módulo que lo contiene.
    • Los conjuntos de idiomas que contienen alemán (de), español (es), inglés (en), francés (fr), italiano (it) y el idioma no especificado (x_unspecified)

Notas de uso

  • La semántica de una sentencia extract pattern depende de la especificación de patrón. Cada coincidencia construye un resultado de salida de acuerdo con la cláusula de retorno de la especificación de patrón y la lista select de la parte superior de la sentencia extract. Los resultados se filtran y se consolidan de acuerdo con las cláusulas having, consolidate y limit de la sentencia extract. Si hay varias coincidencias solapadas para la especificación de patrón, una extracción de patrón genera todas las coincidencias posibles. Utilice la consolidación para filtrar los resultados redundantes.

  • La semántica de la cláusula from de una sentencia extract pattern es distinta de las otras formas de sentencias extract que no tienen una especificación de patrón. La semántica general de una sentencia extract requiere que la especificación de extracción se evalúe sobre cada combinación de las vistas definidas en <from list\>. Si al menos una de las vistas de <from list\> no contiene ningún resultado en un documento determinado, la salida de la sentencia de extracción está vacía porque el conjunto de todas las combinaciones de resultados en las vistas de entrada está vacío. En el caso especial de las sentencias extract pattern, la cláusula from es un marcador que declara los nombres de relaciones que intervienen en la especificación de patrón. La semántica de la sentencia solo está controlada por la especificación de patrón. En particular, la salida de la sentencia puede no estar vacía incluso cuando algunas de las vistas de entrada están vacías.

  • Una sentencia extract que utiliza la extracción de patrones de secuencia puede transferir las columnas de cualquier vista de la lista from, pero solo si el nombre de vista no aparece en un elemento de repetición de la especificación de patrón. Por ejemplo, la sentencia CapsWordOneToThree da como resultado un error de compilación. El error se produce porque la columna de reenvío CW.type en la parte superior de la sentencia extract pertenece al nombre de vista CW, que se encuentra en el elemento de repetición <CW.word>{1,3} de la especificación de patrón.

    create view CapsWord as
    extract 'UpperCase' as type,
        regex /[A-Z].*/ on 1 token in D.text as word
    from Document D;
    
    ---> This results in and error due to the repeating element CW.word
    create view CapsWordOneToThree as
    extract CW.type as type,
        pattern <CW.word>{1,3} as match
    from CapsWord CW;
    
    output view CapsWordOneToThree;
    

    En el caso de las columnas transferidas desde nombres de vista que aparecen en elementos alternativos u opcionales de la especificación de patrón, el valor de la columna de salida es null cuando la alternativa correspondiente o el elemento opcional no está presente en el texto. Encontrará un ejemplo que ilustra este punto en la vista Person del Ejemplo 1.

  • Los grupos que se encuentran bajo un elemento de repetición no se pueden generar en la cláusula return de la sentencia. Por ejemplo, la sentencia siguiente genera una excepción:

    create view CapsWordOneToThree as
      extract
             pattern (<CW.word>){1,3}
            return group 0 as fullmatch
                   and group 1 as word   -- not allowed due to repeat
      from CapsWord CW;
    

Ejemplos

Ejemplo 1: Patrón de secuencia con grupos de captura

El objetivo de este ejemplo es encontrar nombres de persona mediante la identificación de las apariciones de un nombre determinado, seguidos de forma opcional por la inicial del medio, seguido de un apellido, y toda la coincidencia precedida de forma opcional por un saludo común. Además, el extractor devuelve toda la coincidencia como referencia, el primer grupo como saludo, y el segundo grupo como nombre, y transferir los valores de nombre, inicial del medio y apellido de las respectivas vistas de entrada.

create view MiddleInitial as
extract regex /\b([\p{Lu}\p{M}*]\.\s*){1,5}\b/
            on between 1 and 10 tokens in D.text as initial
from Document D;

create view Person as
extract F.first as first,
        M.initial as middle,
        L.last as last,
        pattern ('Mr.'|'Ms.'|'Miss')? (<F.first> <M.initial>? <L.last>)
return group 0 as reference
  and group 1 as salutation
  and group 2 as name
from FirstName F, MiddleInitial M, LastName L;

Puesto que la expresión de subpatrón ('Mr.'|'Ms.'|'Miss')? es opcional, el valor de la columna de salida del saludo es null cuando no hay ningún saludo en el texto. De forma similar, dado que la subexpresión de patrón <M.initial>? es opcional, el valor de la columna de salida media es null cuando no existe una inicial intermedia.

Ejemplo 2: Patrón de secuencia con coincidencia de serie y parámetros de coincidencia

El objetivo de este ejemplo es encontrar las apariciones de notas de reuniones para proyectos conocidos examinando las anotaciones de título del documento. Observe la cláusula with inline_match, que especifica que la coincidencia de serie se realiza en el campo de coincidencia de la vista Title, en contraposición a todo el texto del documento.

create view Project as
extract
regex /[Pp]roject\s?\w*/ on D.text as name
from Document D;


create view Title as
extract regex /[A-z][a-z]+.*/
on between 1 and 20 tokens in D.text as match
from Document D;


create view MeetingNote as
extract
pattern <'Meeting Notes:'[with case exact]> (<P.name>)
return group 0 as match
  and group 1 as projectname
with inline_match on Title.match
from Project P;

Ejemplo 3: Patrón de secuencia que devuelve resultados que no están vacíos, incluso cuando una vista de entrada está vacía

La sentencia siguiente genera resultados incluso cuando la vista de entrada LastName está vacía. La segunda parte de la especificación de patrón, <L.name\>? contiene un elemento opcional. La semántica de la especificación de patrón está diseñada de modo que genera todos los tramos compuestos de un tramo FirstName.name o de un tramo FirstName.name inmediatamente seguido de un tramo LastName.name. Por lo tanto, en los documentos cuya vista LastName está vacía, el resultado de la sentencia consta de todos los tramos que contienen un solo tramo FirstName.name identificado en dicho documento.

create dictionary FirstNamesDict as
(
  'Aaron', 'Matthew', 'Peter'
);
create dictionary LastNamesDict as
(
  'Anthony', 'Lehman', 'Radcliff'
);

create view LastName as
  extract dictionary 'LastNamesDict'
  on D.text as last
from Document D
having MatchesRegex(/((\p{L}\p{M}*)+\s+)?\p{Lu}\p{M}*.{1,20}/, last);

create view FirstName as
  extract dictionary 'FirstNamesDict'
  on D.text as first
from Document D
having MatchesRegex(/\p{Lu}\p{M}*.{1,20}/, first);

create view PersonName as
extract pattern <F.first> <L.last>? as fullName
from FirstName F, LastName L;

La sentencia select

La sentencia select de AQL proporciona un potente mecanismo para utilizar diversas especificaciones para construir y combinar conjuntos de tuplas.

Sintaxis

La sentencia select tiene una estructura similar an una sentencia SELECT de SQL:

select `<select list>`
  from `<from list>`
  [where `<where clause>`]
  [consolidate on `<column>`
     [using '`<policy>`' [with priority
         from `<column> ` [priority order]]]]
  [group by `<group by list>`]
  [order by `<order by list>`]
  [limit `<maximum number of output tuples for each document>`];

Descripción

  • <select list\>

    Una lista delimitada por comas de expresiones de salida.

  • <from list\>

    Una lista delimitada por comas que es el origen de las tuplas que se van a seleccionar.

  • [where <where clause\>]

    Define un predicado que se aplicará en cada tupla que se genere a partir del producto cartesiano de todas las tuplas de las relaciones de la cláusula from. Esta cláusula es opcional.

  • [consolidate on<column\>[using '<policy\>' [with priority from <column\> priority order]]]

    Define una política de consolidación para gestionar los tramos que se solapen. Esta cláusula es opcional.

  • [group by<group by list\>]

    Agrupa las tuplas que se generan a partir del mismo documento por valores comunes de un campo especificado. Esta cláusula es opcional.

  • [order by<order by list\>]

    Ordena las tuplas de salida que se generan mediante la sentencia select de cada documento. El orden se basa en los valores de la lista order-by, una lista de expresiones delimitadas por comas. Esta cláusula es opcional.

  • [limit <maximum number of output tuples for each document\>]

    Limita el número de tuplas de salida de cada documento al máximo especificado. Esta cláusula es opcional.

Notas de uso

La semántica de la sentencia select es la siguiente:

  • Determinar los datos de entrada (en tuplas) tomando el producto cartesiano de las relaciones de la lista from.
  • Para cada tupla de entrada que se genere, filtrar aplicando los predicados de la cláusula where (opcional).
  • Si se ha especificado la cláusula opcional group by, agrupar las tuplas generadas a partir del mismo documento por los valores especificados en la lista group-by y calcular el resultado de las funciones aggregate dentro de la lista select.
  • Consolidar cualquier tupla que se solape, de acuerdo con la política definida en la cláusula consolidation (opcional). Si la cláusula opcional order by está presente, ordenar estas tuplas por los valores de la lista order-by.
  • Calcular todas las expresiones dentro de la lista select de cada tupla, y cambiar el nombre de las columnas tal como se especifica en las cláusulas as.
  • Si está presente la cláusula limit opcional, limitar el número de tuplas de salida al número de tuplas especificado para cada documento.

Ejemplos

Un ejemplo de cómo utilizar la sentencia select consiste en extraer números de teléfono que coincidan con un patrón. Supongamos que la vista PhoneNumbers que extrae los números de teléfono del patrón XXX-XXX-XXXX para los Estados Unidos ya está definida. Esta sentencia select evalúa la expresión regular correspondiente al patrón 444-888-XXXX en el texto de entrada. La vista tiene las columnas de salida documentText y phoneNumber. Además, la salida se limita a la primera aparición de este patrón de número de teléfono que se identifica por documento.

create view PhoneNumbersPattern1 as
select D.documentText, D.phoneNumber
from PhoneNumbers D
where MatchesRegex(/444-888-\d{4}/,D.phoneNumber)
limit 1;

Otro ejemplo de cómo se puede utilizar la sentencia select consiste en encontrar correlaciones aproximadas de personas y sus números de teléfono correspondientes. Supongamos que la vista Person ya está definida y que tiene las columnas person y la vista PhoneNumbers. La sentencia select evalúa la cláusula where para localizar tramos de texto que contengan una mención de persona seguida de un número de teléfono con una distancia de entre 1 y 3 palabras o señales. La entrada de esta sentencia se representa mediante una unión de las vistas Person y PhoneNumbers en la lista from.

create view PersonPhone as
select P1.documentText, P1.person, P2.phoneNumber, CombineSpans(P1.person,P2.phoneNumber) as personPhoneSpan
from Person P1, PhoneNumbers P2
where FollowsTok(P1.person,P2.phoneNumber,1,3);

La columna personPhoneSpan contendrá los tramos coincidentes que proporcionan la correlación aproximada entre persona y teléfono.

personPhoneSpan
John : 433-999-1000
Martha Mob 433-999-1001
  • La lista select La lista select de una sentencia select o extract de AQL consiste en una lista de expresiones de salida delimitadas por comas.
  • La lista from La segunda parte de una sentencia select o extract en AQL es la lista from. La lista from es una lista separada por comas que constituye el origen de las tuplas que se van a seleccionar o extraer.
  • La cláusula where La cláusula opcional where define un predicado que se aplicará en cada tupla generada a partir del producto cartesiano de todas las tuplas de las relaciones de la cláusula from.
  • La cláusula consolidate on La cláusula opcional consolidate on especifica cómo se resuelven los tramos que se solapan entre las tuplas que genera una sentencia select o extract. Las tuplas con tramos que no se solapan no se ven afectadas cuando se utiliza esta cláusula.
  • La cláusula group by La cláusula opcional group by de una sentencia select indica al componente de tiempo de ejecución que agrupe las tuplas que se generan desde el mismo documento con valores comunes de un campo especificado.
  • La cláusula order by La cláusula opcional order by indica al componente de tiempo de ejecución que ordene las tuplas de salida generadas por la sentencia select de cada documento en función de los valores de la lista order by, que es un conjunto de expresiones delimitadas por comas.
  • La cláusula limit La cláusula opcional limit especifica un límite en cuanto al número de tuplas de salida que genera la sentencia select para un documento.
  • La sentencia select... into La sentencia select ... into resulta útil para definir una vista y para especificar que se trata de una vista de salida en una sola sentencia.

La lista select

La lista select de una sentencia select o extract de AQL consiste en una lista de expresiones de salida delimitadas por comas.

Sintaxis

Cada expresión de salida debe estar en uno de los siguientes formatos:

select
   <viewname>.<colname> as <alias> |
   <viewname>.* |
   <expr> as <alias> |
     case
     when <predfunction1()> then <expr1>
      when <predfunction2()> then <expr2>...
     when <predfunctionn()>
      then <exprn>
     [else <expr\_default>]
      as <name>

Descripción

  • <viewname\>.<colname\> as <alias\>

    • <viewname\>

      Especifica la vista desde la que se seleccionan las columnas.

    • <colname\>

      Especifica la columna de dicha vista.

    • <alias\>

      Especifica el nombre por el que se conoce el campo seleccionado. Se trata de un campo opcional. Se selecciona para que forme parte de cada tupla de salida. Si no se especifica <alias\>, el nombre de la columna es de forma predeterminada el <colname\>. Puede ser un identificador simple o un identificador entre comillas dobles.

  • <viewname\>.*

    Especifica el nombre de una vista. Esta sintaxis indica que todas las columnas de la vista especificada se deben transportar a la sentencia select o extract contenida.

    Al igual que SQL, AQL permite la sentencia select * abreviada. El efecto de esta sentencia consiste en seleccionar todas las columnas de todas las entradas especificadas en la cláusula from de la sentencia select. Sin embargo, la sentencia extract * abreviada no recibe soporte.

  • <expr\> as <alias\>

    Representa la asignación de una expresión a un atributo de la vista completa.

    • <expr\>

      Especifica una expresión compuesta de llamadas a la función scalar, llamadas a la función aggregate o una constante.

    • <name\>

      Representa el nombre de la columna que contiene el resultado de la expresión especificada por <expr\> como <alias\>. Si no se especifica <alias\>, el nombre de la columna es de forma predeterminada el <name\>. Puede ser un identificador simple o un identificador entre comillas dobles.

  • when<function1()\> then <expr1\> when <function2()\> then <expr2\> ... when <functionN()\> then <exprn\> [else ] <expr_default\> as <name\>

    • <function1()\>, <function2()\>, <functionN()\>

      Especificar funciones escalares que devuelven el tipo booleano.

    • <expr1\>, <expr2\>, <exprn\>, <expr_default\>

      Especificar expresiones compuestas por llamadas a la función scalar y que deben devolver el mismo tipo.

    Si el resultado de <function1()\> es true, el resultado de la expresión case es el resultado de <expr1\> y no se evalúa ninguna de las siguientes cláusulas when. De lo contrario, las siguientes cláusulas when (si las hay) se evalúan del mismo modo.

    Cuando no se cumple ninguna de las condiciones de las cláusulas when, el resultado de esta expresión de caso es el resultado de la expresión predeterminada <expr\_default\>. Esta expresión se especifica en la cláusula else opcional. Si no se especifica la cláusula [else], el resultado de esta expresión case es null.

Notas de uso

  • La sentencia siguiente no recibe soporte:

    select * from Document;
    

    Es posible que el contenido de la vista Document no se conozca en su totalidad en el contexto o ámbito actual del archivo .aql en el que se emite esta sentencia select. La falta de información sobre el contenido se debe a que varias sentencias require document with columns proporcionadas fuera del archivo .aql actual pueden alterar la definición de esquema final de esta vista Document especial cuando se utiliza en el nivel de un módulo. La sentencia Document.* abreviada no es una construcción de AQL válida.

  • Puede seleccionar campos de forma explícita en la vista Document. En el ejemplo siguiente se muestra una selección explícita válida de campos de una vista Document:

    select D.label as label,
      D.text as text
    from Document D;
    

Ejemplos

En los ejemplos siguientes se ilustran diversas formas de la lista select.

Ejemplo 1: Asignación explícita de valores mediante una constante

En este ejemplo se muestra la asignación de un valor constante a un atributo de vista dentro de la lista select. El campo llamado polarity indica si la polaridad de PS.match es positiva o negativa (observe la asignación explícita de un valor constante a este atributo).

create view PositiveSentimentsWithPolarity as
select
  'positive' as polarity,
  PS.match as sentiment
from
  PositiveSentiments PS;
create view NegativeSentimentsWithPolarity as
select
  'negative' as polarity,
  NS.match as sentiment
from
  NegativeSentiments NS;

Ejemplo 2: Asignación explícita de valores mediante una llamada de función

En el ejemplo siguiente se muestra cómo se asigna de forma explícita el resultado de una llamada de función a un atributo de vista dentro de la lista select.

create view Citizenship as
select
  P.Name as name,
  MatchesDict('USCities.dict', P.birthPlace) as isUSCitizen
from
  Person P;

Ejemplo 3: Selección de una expresión de lista a partir de una extracción de diccionario

En el siguiente ejemplo se muestra cómo la expresión select list puede tomar valores de tipo Span de un resultado de extracción de diccionario.

create view PersonNames as
select N.match as name
from
  (extract
  dictionary 'firstNames.dict'
  on D.text
  as match
  from Document D
)N;

Ejemplo 4: Ejemplos de expresiones case

En este primer ejemplo se muestra cómo especificar el manejo de nulos en campos específicos:

create view School as
select
case
when Not(NotNull(P.education)) then 'Unknown'
else GetString(P.education)
as name
from Person P;

En este ejemplo se explica cómo clasificar los datos:

create view Company as
select
PM.name as productname,
case
when ContainsRegex (/IBM/,PM.name) then 'IBM'
when ContainsDict ('OpenSourceDict',PM.name) then 'OSS'
else 'Unknown'
as name
from ProductMatches PM;

La lista from

La segunda parte de una sentencia select o extract en AQL es la lista from. La lista from es una lista separada por comas que constituye el origen de las tuplas que se van a seleccionar o extraer.

Sintaxis

from <from list item> <name>  [, <from list item> <name>]

Descripción

  • <from list item\>

    Una vista, una tabla, una referencia de función de tabla o una sentencia AQL anidada. Todas las sentencias anidadas de AQL deben estar especificadas entre paréntesis.

  • <name\>

    Nombre local de <from list item\>, cuyo ámbito está dentro de la sentencia select o la sentencia extract. Un nombre local puede ser un identificador simple o un identificador entre comillas dobles. Los nombres locales que contienen espacios, caracteres de puntuación o palabras clave de AQL se deben especificar entre comillas dobles.

Ejemplos

Ejemplo 1: Una lista from con una vista y una sentencia anidada

En este ejemplo se muestra una lista from que hace referencia a una vista y a una sentencia extract anidada. En el ejemplo se asigna el resultado de la sentencia al nombre local FN. En el ejemplo también se asignan las salidas de la vista LastName al nombre local Last Name.

create dictionary LastNamesDict as
  (
    'Anthony', 'Lehman', 'Radcliff'
  );

create view LastName as
  extract dictionary 'LastNamesDict'
  on D.text as lastname
from Document D;

create view FromList as
  select *
    from
    (extract dictionary 'first.dict' on D.text
      as firstname from Document D) FN,
      LastName "Last Name"
    where Follows(FN.firstname,
      "Last Name".lastname, 0, 1);

Los siguientes nombres están contenidos en el diccionario externo first.dict:

#Dictionary for given names
Aaron
Candra
Freeman
Mathew
Matthew
Zoraida

La cláusula where

La cláusula opcional where define un predicado que se aplicará en cada tupla generada a partir del producto cartesiano de todas las tuplas de las relaciones de la cláusula from.

Sintaxis

select <select list>
  from <from list>
[where <where clause>]

Descripción

  • <where clause\>

    Especifica uno o varios predicados. Se produce una unión cuando cualquier predicado de una cláusula where implica campos de más de una vista perteneciente a la lista from. Este predicado debe ser una combinación de un conjunto de funciones de predicado incorporadas u otras funciones definidas por el usuario que devuelven el tipo de datos booleano:

    function1() and function2()
    and ... and functionn()
    

    La cláusula where es opcional y se puede omitir de una sentencia select si no hay predicados que aplicar.

Ejemplos

Ejemplo 1: Filtrado de las tuplas unidas mediante un predicado en la cláusula WHERE

En este ejemplo se muestra una cláusula where que solo busca frases que constan de nombres propios válidos que van seguidos por entre 0 y 1 caracteres por apellidos válidos.

-- a view containing words that are valid given names
create view FirstName as
  extract dictionary 'first.dict'
  on D.text as firstname
from Document D;

-- a view containing words that are valid surnames
create view LastName as
  extract dictionary 'last.dict'
  on D.text as lastname
from Document D;

-- a view containing phrases consisting of valid given names
-- followed within 0-1 characters by valid surnames.
create view FullName as
  select *
  from
  FirstName FN,
  LastName LN
  where
  Follows (FN.firstname, LN.lastname, 0, 1);

Los siguientes nombres están contenidos en el diccionario externo first.dict:

#Dictionary for given names
Aaron
Candra
Freeman
Mathew
Matthew
Zoraida

Los siguientes nombres están contenidos en el diccionario externo last.dict:

#Dictionary for surnames
Anthony
Lehman
Radcliff

La cláusula consolidate on

La cláusula opcional consolidate on especifica cómo se resuelven los tramos que se solapan entre las tuplas que genera una sentencia select o extract. Las tuplas con tramos que no se solapan no se ven afectadas cuando se utiliza esta cláusula.

Sintaxis

El código siguiente es un ejemplo de la estructura general de esta cláusula:

consolidate on <target>
  [using '<policy>'[ with priority from <priority_column>
    [ <priority_order> ]]]

Descripción

  • <target\>

    Especifica una columna en una vista en la cláusula from o una expresión compuesta de llamadas de función escalar que implican columnas de vistas especificadas en la cláusula from como argumentos.

  • '<policy\>'

    Especifica una de las siguientes políticas de consolidación admitida por Text Analytics:

    • ContainedWithin

      Esta es la política predeterminada. Si los tramos A y B se solapan, y A contiene B por completo, esta política elimina de la salida la tupla que contiene el tramo B. Si A y B son iguales, elimina uno de ellos. La elección de la tupla que elimina es arbitraria.

    • NotContainedWithin

      Si los tramos A y B se solapan, y A contiene B por completo, esta política elimina de la salida el tramo A. Si A y B son iguales, elimina uno de ellos. La elección de la tupla que elimina es arbitraria.

    • ContainsButNotEqual

      Esta política es igual que ContainedWithin, excepto en que los tramos que son exactamente iguales se conservan.

    • ExactMatch

      Si un conjunto de tramos cubre la misma región de texto, esta política devuelve exactamente uno de ellos. El resto de los tramos no se modifican.

    • De izquierda a derecha

      Esta política procesa los tramos en orden de izquierda a derecha. Cuando se produce un solapamiento, conserva el tramo más largo que hay más a la izquierda que no se solapa. Esta política emula la política de manejo de solapamiento de la mayoría de los motores de expresiones regulares.

  • <priority\_column\>

    Especifica una columna de tipo Text, String, Integer o Float. Solo se puede especificar con la política de consolidación LeftToRight.

  • <priority\_order\>

    Especifica si el orden debe ser ascendente o descendente. Solo se puede especificar con la política de consolidación LeftToRight. El orden ascendente garantiza que si una tupla T1 tiene la prioridad 1 y una tupla T2 tiene la prioridad 2, T1 tiene una prioridad más alta que T2. Por el contrario, si el orden de prioridad es descendente, T2 tiene una prioridad más alta. El valor predeterminado del orden de prioridad es el ascendente.

Notas de uso

  • Cuando la cláusula priority está presente, la semántica de la consolidación sigue este orden:
    • Procesa los tramos de izquierda a derecha y, cuando se solapan tramos, retiene el tramo que hay más a la izquierda.
    • Si tiene varios tramos que se solapan que empiezan en el mismo desplazamiento, conserva los que tienen la prioridad más alta de acuerdo con el orden de prioridad.
    • Interrumpe los enlaces restantes reteniendo los tramos más largos entre los tramos con la misma prioridad.
  • La consolidación trata los nulos como idénticos. Todas las entradas con un <consolidate target\> nulo dan como resultado una tupla de salida única, que se elige aleatoriamente entre esas entradas. Este comportamiento es similar a la forma en que se consolidan las tuplas con un tramo idéntico en la columna de destino. La excepción a que se genere una sola tupla se produce si la política es ContainsButNotEqual. En ese caso, el <consolidate target\> nulo da salida a todas las entradas con destino de consolidación nulo.

Ejemplos

Ejemplo 1: Consolidación en una sola columna

En este ejemplo se indica al sistema que examine el campo Person.name de todas las tuplas de salida y que utilice la política de consolidación ContainedWithin para resolver el solapamiento.

consolidate on Person.name
  using 'ContainedWithin'

Ejemplo 2: Consolidación de una expresión, que implica varias columnas

En este ejemplo se indica al sistema que examine el resultado de aplicar la función escalar CombineSpans a los campos Person.firstname y Person.lastname en cada tupla de salida. Resuelve el solapamiento utilizando la política de consolidación ContainedWithin.

consolidate on
  CombineSpans(Person.firstname, Person.lastname)
  using 'ContainedWithin'

Ejemplo 3: Consolidación mediante la política LeftToRight y el orden de prioridad

Supongamos que se extraen las siguientes tuplas de término del texto de entrada John Doe:

match: `John`,
priority: `1`

and

match: `John Doe`,
priority: `2`

Ambos tramos tienen el mismo desplazamiento. Si realiza la consolidación mediante la política LeftToRight para orden de prioridad ascendente, se retiene la tupla (match: John, priority: 1) porque tiene la prioridad más alta. Si realiza la consolidación con el orden de prioridad descendente, se retiene la tupla (match: John Doe, priority: 2), como en el siguiente ejemplo:

create view ConsolidatePeopleWithPrioritiesAscending as
  select P.match as match, P.weight as weight
  from People P
  consolidate on P.match
  using 'LeftToRight'
  with priority from P.weight
  ascending;

La cláusula group by

La cláusula opcional group by de una sentencia select indica al componente de tiempo de ejecución que agrupe las tuplas que se generan desde el mismo documento con valores comunes de un campo especificado.

Sintaxis

select <select list>
from <from list>
[where <where clause>]
...
[group by <group by list>]

Descripción

  • <group by list\>

    Especifica una lista de expresiones delimitadas por comas que implica columnas de las vistas de la cláusula from y las llamadas a funciones escalares. Cuando se aplica la cláusula group by, cada grupo de tuplas que comparte valores comunes para todas las expresiones group by genera una sola tupla de salida que es representativa de todo el grupo.

    Un campo o una expresión que no aparece en la cláusula group by no puede aparecer en la lista select, a menos que se utilice en una llamada de función de agregación. El orden de las expresiones en la lista no importa.

    La cláusula group by trata todos los nulos como idénticos. Group by en una columna con valores nulos da como resultado un único grupo.

Ejemplos

Ejemplo 1: Cálculo de valores agregados

Utilice la cláusula group by para calcular valores agregados. En este ejemplo se cuenta el número de apariciones de cada nombre propio en el documento. En este ejemplo, Count es una función de agregación.

create view SampleView as
  select
    GetText(P.firstname) as name,
    Count(GetText(P.firstname)) as occurrences
  from
    (extract
    dictionary 'first.dict'
    on D.text as firstname
    from Document D
    ) P
  group by GetText(P.firstname);

En este caso, first.dict es un diccionario externo que contiene las entradas siguientes:

#Dictionary for given names
Aaron
Candra
Freeman
Matthew
Zoraida

En los pasos siguientes se describe la semántica de esta sentencia:

  1. Agrupa las tuplas generadas por la subconsulta en la cláusula from por el contenido de texto de su campo firstname.
  2. Para cada grupo, cuenta el número de tuplas con un valor de firstname que no sea nulo. Genera una sola tupla de salida para cada uno de estos grupos con dos valores: el nombre y el número de tuplas del grupo.

Ejemplo 2: Problemas con la agrupación de campos diferentes

En este ejemplo se muestra una sentencia que no es válida.

select GetText(P.firstname) as first,
  GetText(P.lastname) as last,
  Count(P.firstname) as occurrences
from Person P
group by GetText(P.firstname);

La inclusión de GetText(P.lastname) en la lista select no se acepta, ya que tuplas con los mismos valores de firstname pueden tener distintos valores lastname, lo que da lugar a un resultado ambiguo.

La cláusula order by

La cláusula opcional order by indica al componente de tiempo de ejecución que ordene las tuplas de salida generadas por la sentencia select de cada documento en función de los valores de la lista order by, que es un conjunto de expresiones delimitadas por comas.

Sintaxis

select ...
  [order by <order by list>]

Descripción

  • <order by list\>

    Especifica una lista de expresiones delimitada por comas.

    El orden se basa en los valores de una lista de expresiones delimitadas por comas. La cláusula order by da soporte a expresiones que devuelven tipos de datos numéricos (Integer o Float), Text o Span. Si una expresión de la cláusula order by devuelve un valor de tipo Span, las tuplas resultantes se comparan comparando los valores de span relevantes. En el siguiente ejemplo, se comparan los valores de span del campo person.

    order by P.person
    
    

    La cláusula order by trata los nulos como sin orden (entre ellos). Los nulos se ordenan por debajo de otros objetos.

Ejemplos

Ejemplo 1: Varias expresiones order by

Supongamos que person es un campo de tipo Span. La siguiente cláusula order by especifica que la sentencia devuelve las tuplas dentro de cada documento. Se ordenan lexicográficamente por el texto del campo person y luego por el principio del campo person.

order by GetText(P.person), GetBegin(P.person)

La cláusula limit

La cláusula opcional limit especifica un límite en cuanto al número de tuplas de salida que genera la sentencia select para un documento.

Sintaxis

select <select list>
  from <from list>
  ...
  [limit <maximum number of output tuples for each document>];

Descripción

  • <maximum number of output tuples for each document\>

    Especifica el número máximo de tuplas de salida para cada documento. Si el valor de límite es mayor o igual que el número total de tuplas que se pueden devolver, se devuelven todas las tuplas.

Ejemplos

Ejemplo 1: Limitación del número de devoluciones

En este ejemplo se devuelven los primeros tres nombres de persona de cada documento:

create view SampleView as
  select *
  from Person P
  order by GetBegin(P.name)
  limit 3;

La sentencia select... into

La sentencia select ... into resulta útil para definir una vista y para especificar que se trata de una vista de salida en una sola sentencia.

Sintaxis

select <select list>
into <output view name>
from <from list>
[where <where clause>]
[consolidate on <column> [using '<policy>' [with priority from <column> [priority order]]]]
[group by <group by list>]
[order by <order by list>]
[limit <maximum number of output tuples for each document>];

Descripción

  • <output view name\>

    Especifica el nombre de la vista de salida que define la sentencia. La sentencia select ... into es idéntica a la sentencia select, excepto la cláusula into <output view name\> adicional.

Ejemplos

Ejemplo 1: Definición de una vista

En este ejemplo se define una vista llamada PersonPhone y también se especifica esta vista como una vista de salida.

select P.name as name,
  Ph.number as phoneNumber
into PersonPhone
from Person P, Phone Ph;

Este ejemplo es equivalente a las dos sentencias siguientes:

create view PersonPhone as
  select P.name as name,
    Ph.number as phoneNumber
  from Person P, Phone Ph;

output view PersonPhone;

La sentencia detag

La sentencia detag en AQL proporciona la función de desmarcar o eliminar toda la marcación de los documentos HTML o XML antes de ejecutar los extractores de AQL.

La sentencia detag también puede retener las ubicaciones originales de las etiquetas y de los valores guardados en estas etiquetas. Cuando una sentencia detag elimina etiquetas de un documento, el componente de tiempo de ejecución recuerda la correlación entre desplazamientos entre el texto sin etiquetas y el original con etiquetas. La función Remap es una función incorporada especial que correlaciona tramos del texto sin etiquetas con sus tramos equivalentes del original.

Sintaxis

detag <input view name>.<text column>
 as <output view name>
[detect content_type (always|never)]
[annotate
 element '<element name>' as <auxiliary view name>
 [with attribute '<attribute name>' as <column name>]
 [and attribute '<attribute name>' as <column name>]
 [, element ...]];

Descripción

  • <input view name\>.<text column\>

    • <input view name\>

      Especifica el nombre de la vista de entrada en la que se va a realizar el proceso detag. El <input view name\> puede ser un identificador simple o un identificador de comillas dobles.

    • <text column\>

      Especifica el campo de texto de la vista de entrada en la que se va a realizar el proceso detag. El <text column\> puede ser un identificador simple o un identificador de comillas dobles.

  • <output view name\>

    Especifica el nombre de la vista de salida que contiene el texto sin etiquetas. La vista de salida contiene una sola columna llamada text, que contiene el texto sin etiquetas. El <output view name\> puede ser un identificador simple o un identificador de comillas dobles.

  • always|never

    Especifica si se debe verificar que el contenido es HTML o XML antes de que se procese la sentencia detag. Cuando se ejecuta texto no HTML y no XML a través de un dispositivo de detección, se pueden producir problemas si el texto contiene caracteres especiales XML como <, > o &. Si falta la cláusula detect content_type, el valor predeterminado es always y el sistema siempre detecta el contenido.

    • always

      Especifica que siempre se verifica antes de que se intente la operación para evitar problemas con el análisis de documentos que no son HTML o XML. Si el valor de <text column\> no parece contener una marcación, el sistema se salta la señalización del documento actual.

    • never

      Especifica que nunca se verifica antes de que se intente la operación detag. El sistema intenta eliminar las etiquetas del texto de destino, aunque el texto no contenga ningún contenido HTML o XML.

  • <element name\>

    Especifica el nombre del elemento HTML o XML que se debe anotar. La cláusula opcional annotate puede indicar al componente de tiempo de ejecución que recuerde la información sobre las etiquetas eliminadas creando una o varias vistas.

  • <auxiliary view name\>

    Especifica el nombre de la vista que se crea para albergar las etiquetas originales y sus atributos. Puede ser un identificador simple o un identificador entre comillas dobles.

  • <attribute name\>

    Nombre de un atributo del elemento HTML o XML.

  • <column name\>

    El nombre de la columna en el <auxiliary view name\> que se utiliza para almacenar los valores de <attribute name\>. Puede ser un identificador simple o un identificador entre comillas dobles.

Ejemplos

Ejemplo 1: Especificación de la vista de salida de detag y de una vista auxiliar

En este ejemplo, se crea la vista DetaggedDoc para albergar la versión sin etiquetas del texto original en el atributo text de la vista Document. Además de crear una vista DetaggedDoc, la cláusula annotate crea una vista auxiliar llamada Anchor. Esta vista auxiliar tiene dos columnas. Una columna, llamada match, contiene el texto de anclaje. La otra columna, llamada linkTarget, contiene el destino real del enlace como texto. Los tramos de cada columna de comparación están sobre el valor del texto de la vista DetaggedDoc.

detag Document.text as DetaggedDoc
annotate
  'a' as Anchor
  with attribute 'href' as linkTarget;

Ejemplo 2: Utilización de la función Remap

En el ejemplo siguiente se muestra cómo se utiliza la función Remap para correlacionar tramos del texto sin etiquetas con sus equivalentes en el origen original.

-- Strip out tags from each document, provided that the document
-- is in HTML or XML format.
-- Remember the locations and content of all <A> and <META> tags
-- in the original source document.
detag Document.text as DetaggedDoc
detect content_type always
annotate
  element 'a' as Anchor
    with attribute 'href' as target,
  element 'meta' as Meta
    with attribute 'name' as name
    and attribute 'content' as content;

output view DetaggedDoc;

-- Create a view containing all lists of keywords in the
-- document's META tags.
create view MetaKeywordsLists as
select M.content as list
from Meta M
where MatchesRegex(/keywords/, 'CASE_INSENSITIVE', M.name)
  and NotNull(M.content);

-- Create a dictionary of "interesting" web sites
create dictionary InterestingSitesDict as
(
  'ibm.com', 'slashdot.org'
);

-- Create a view containing all anchor tags whose targets contain
-- a match of the "interesting sites" dictionary.
create view InterestingLinks as
select A.match as anchortext, A.target as href
from Anchor A
where ContainsDict('InterestingSitesDict', A.target);

-- Find all capitalized words in the anchor text of links to
-- "interesting" web sites.
create view InterestingWords as
extract I.href as href,
  regex /[A-Z][a-z]+/ on 1 token in I.anchortext as word
from InterestingLinks I;

-- Map spans in the InterestingWords view back to the original
-- HTML or XML source of the document.
create view InterestingWordsHTML as
select I.href as href, Remap(I.word) as word
from InterestingWords I;

Documentación de la sentencia detag con AQL Doc

El comentario AQL Doc correspondiente a una sentencia detag contiene la siguiente información:

  • Descripción general de la función de la sentencia.
  • @field para cada campo de texto de la vista de entada en la que se debe ejecutar el proceso de eliminación de etiquetas (detag).
  • @auxView especifica el nombre de la vista.
  • @auxViewField especifica el nombre completo de la columna de la vista.
/**
* Detags the input document
* @field text the detagged text of the document
* @auxView Anchor stores the anchor points from tagged doc
* @auxViewField Anchor.linkTarget stores the href attribute of anchor tag
*/

detag Document.text as DetaggedDoc
  annotate element 'a' as Anchor
  with attribute 'href' as linkTarget;

Las sentencias create dictionary y create external dictionary

Las sentencias create dictionary y create external dictionary sirven para definir diccionarios de palabras o de frases para identificar términos coincidentes en el texto de entrada mediante sentencias extract o funciones de predicado. La sentencia create dictionary permite especificar el contenido del diccionario en código AQL de origen, y el contenido del diccionario se serializa dentro de la representación compilada del módulo (el archivo .tam). La sentencia create external dictionary le permite especificar el contenido del diccionario cuando se crea una instancia del extractor, en lugar de hacerlo en el código de AQL de origen, y así no tiene que volver a compilar el módulo. Por lo tanto, los diccionarios externos constituyen potentes construcciones que permiten al desarrollador de AQL exponer puntos de personalización en un módulo compilado.

Los diccionarios se pueden crear a partir de tres fuentes:

  • Archivos de diccionario
  • Declaraciones de diccionario en línea
  • Tablas que se crean con la sentencia create table y la sentencia create external table.

Sintaxis

La sentencia interna create dictionary tiene tres formas sintácticas: from file, from table y un formato en línea.

  • Diccionario interno

    From file:

    create dictionary <dictionary name>
    
     from file '<file name>'
     [with language as '<language code(s)>']
     [and case (exact | insensitive)]
     [and lemma_match];
    

    From table:

    create dictionary <dictionary name>
    
      from table <table name>
      with entries from <column name>
      [and language as '<language code(s)>']
      [and case (exact | insensitive)]
      [and lemma_match];
    

    Formato en línea

    create dictionary <dictionary name>
    [with language as '<language code(s)>']
    [and case (exact | insensitive)]
    [and lemma_match]
     as
        (
        '<entry 1>', '<entry 2>', ... , '<entry n>'
        )
    ;
    
  • Diccionario externo

    create external dictionary <dictionary-name>
    required [true|false]
    [with language as '<language codes\>']
    [and case (exact | insensitive )]
    [and lemma_match];
    

Descripción

  • <dictionary name\>

    Especifica un nombre para el nuevo diccionario interno o externo. Puede ser un identificador simple o un identificador entre comillas dobles.

  • '<file name\>'

    Especifica el nombre del archivo que contiene entradas de diccionario. Los archivos de diccionario son archivos de texto delimitado por retorno de carro con una entrada de diccionario por línea. Las entradas de un archivo de diccionario pueden constar de varias señales.

  • <table name\>

    Especifica el nombre de la tabla desde la que se añaden entradas de diccionario. Los diccionarios no se pueden crear a partir de una tabla importada desde otro módulo.

  • <column name\>

    Especifica el nombre de la columna de la tabla desde la que se añaden entradas de diccionario.

  • required [true|false]

    Especifica si el contenido externo para el diccionario externo es obligatorio para ejecutar el módulo.

    • true

      Si la cláusula es required true, debe especificar un URI a la ubicación del archivo que contiene el contenido externo. El archivo especificado debe tener contenido. Si no se especifica el URI, o si el archivo no tiene contenido, el componente de tiempo de ejecución genera una excepción.

    • false

      Si la cláusula es required false, el módulo se puede ejecutar correctamente aunque no se especifique un URI al contenido externo para este diccionario. Si no se especifica un URI, el componente de tiempo de ejecución lo trata como un diccionario vacío.

    El uso de create external dictionary <dictionary-name\> allow_empty ahora está en desuso y da como resultado un aviso del compilador.

  • '<language code(s)\>'

    Especifica una lista delimitada por comas de códigos de idioma de dos letras, como por ejemplo en (inglés) o zh (chino) para los idiomas o para los idiomas del documento para diccionarios externos en los que se evalúa el diccionario. El diccionario no genera ningún resultado en los documentos cuyo código de idioma no esté contenido en esta serie.

    Si se omite el parámetro language, el idioma del diccionario se establece de forma predeterminada en uno de los siguientes conjuntos de idiomas:

    • Los conjuntos de idiomas especificados mediante la sentencia set default language, si se ha declarado, en el módulo que lo contiene.
    • Los conjuntos de idiomas que contienen alemán (de), español (es), inglés (en), francés (fr), italiano (it) y el idioma no especificado (x_unspecified).
  • lemma_match

    Utilice la lematización para localizar coincidencias de palabras similares a un término de diccionario de sus documentos.

    La lematización es el proceso de determinar el lema de una determinada palabra. Un lema es una palabra que se puede utilizar como coincidencia de un término único determinado. Por ejemplo, el término “go” puede coincidir con los términos “goes”, “going”, “gone” o “went”. Este proceso implica tareas complejas, como por ejemplo comprender el contexto y determinar la categoría léxica de una palabra en una frase. La lematización está disponible para todos los idiomas para los que el señalizador multilingüe de IBM proporciona soporte de categoría léxica.

    La coincidencia de lema solo se realiza para los diccionarios que se han declarado con la cláusula lemma match.

    La semántica de la extracción de diccionario con la cláusula lemma_match es la siguiente:

    • Se calcula la forma lematizada de cada señal del documento de entrada.
    • El diccionario se evalúa en relación con el documento lematizado. No puede utilizar la opción lemma_match con la opción case exact. Si se utilizan ambas opciones, se devuelve un error del compilador.
  • case (exact | insensitive)

    Especifica el tipo de conversión a mayúsculas que realiza el diccionario cuando determina si una región específica del documento coincide.

    • exact

      Especifica una coincidencia exacta de mayúsculas y minúsculas.

    • insensitive

      Especifica una coincidencia que no distingue entre mayúsculas y minúsculas. Esta opción es el valor predeterminado.

  • '<entry 1\>', '<entry 2\>', ... , '<entry n\>'

    Especifica las series que desea incluir en el diccionario en línea. Las entradas de un diccionario en línea pueden constar de una o varias señales.

Notas de uso

  • Se recomiendan los formatos from file y from table, especialmente cuando se prevé modificar las entradas o cuando se tienen muchas entradas. Con estos formatos, puede modificar el contenido del diccionario sin modificar el código.

  • Cuando el compilador AQL modular procesa la sentencia create dictionary, las referencias a las ubicaciones del archivo de diccionario especificadas en la sintaxis de create dictionary ... from file deben ser relativas a la raíz del módulo en el que se emite esta sentencia create dictionary.

  • Puede especificar comentarios en un archivo de diccionario especificando el carácter # antes del comentario. Los comentarios pueden comenzar en cualquier parte de una línea.

  • Si desea especificar comentarios que abarcan varias líneas, debe preceder cada línea con el carácter de comentario. Si el carácter de comentario forma parte de una entrada del diccionario, lo debe especificar con el carácter de barra inclinada invertida (\), como en \#. Si el carácter de barra inclinada invertida es parte de la entrada del diccionario, lo debe especificar como \\.

  • En el caso de diccionarios externos, cuando se cargan los módulos debe especificar una lista de URI a diccionarios externos, que es lo que necesitan los módulos que se cargan.

  • Lematización de diccionarios: la principal diferencia entre la semántica de coincidencia de un diccionario existente y la semántica lematizada es que la comparación se realiza con la forma lematizada del documento, en lugar de con la forma original del documento.

    Las entradas de diccionario que pertenecen a un diccionario con la coincidencia de lema habilitada tienen estos requisitos previos:

    • Una entrada del diccionario puede contener una o varias señales, donde cada señal de entrada es un lema. Para crear un diccionario de lemas, puede utilizar la función escalar [GetLemma.
    • Las señales de una entrada del diccionario deben estar separadas por un espacio en blanco. Si la señal contiene espacios en blanco, los espacios en blanco se deben especificar con el carácter de barra inclinada invertida (\).
  • En la tabla siguiente se muestran las diferencias entre la sentencia create external dictionary y la sentencia create dictionary:

create external dictionary create dictionary
  • Define un marcador para un diccionario cuyo contenido se proporciona en el momento de la inicialización.
  • Requiere que el contenido del diccionario esté disponible en tiempo de compilación.
  • Serializado en la representación compilada (.tam) de un módulo.

Ejemplos

Ejemplo 1: Creación de un diccionario externo

Se espera que el diccionario externo, PersonPositiveClues, se llene con valores de un archivo externo en el momento de cargarlo. También se espera que se compare con algunos idiomas occidentales, tal como especifican sus distintivos.

module PersonModuleEnglish;

create external dictionary PersonPositiveClues
  allow_empty false
  with case exact;

export dictionary PersonPositiveClues;

Ejemplo 2: Lematización

Supongamos que un diccionario tiene habilitada la coincidencia de lemas y contiene dos entradas: go shop y went shopping. El documento contiene el texto Anna went shopping. La forma lematizada del documento de entrada es Anna go shop. La comparación de lemas devuelve went shopping como una coincidencia para entrada go shop. El texto del documento original no se compara con las entradas del diccionario, solo el texto del documento lematizado. Por lo tanto, no hay ninguna coincidencia en el documento para la entrada went shopping.

Documentación de las sentencias create dictionary y create external dictionary con AQL Doc

El comentario AQL Doc correspondiente a una sentencia create dictionary contiene la siguiente información:

Descripción general sobre el diccionario.

/**
* A dictionary of terms used to greet people.
*
*/

create dictionary GreetingDict as
(
  'regards', 'regds', 'hello', 'hi', 'thanks', 'best', 'subj', 'to', 'from'
);

El comentario de AQL Doc correspondiente a la sentencia create external dictionary contiene la descripción general sobre el diccionario que se crea. La siguiente serie ilustra el formato:

/**
 * Customizable dictionary of given names.
 * Evaluated on English, French, Italian, German, Portuguese, Spanish text.
 */
create external dictionary CustomFirstNames_WesternEurope
  allow_empty true;

La sentencia create table

La sentencia create table crea una tabla de AQL.

La sentencia create table en AQL se utiliza para definir tablas de búsqueda estática para aumentar las anotaciones con información.

Sintaxis

create table <table name> (
    <colname> <type> [,  <colname> <type>]* )
 as values
    ( <value> [, <value>]*),
    ...
    ( <value> [, <value>]*);

Descripción

  • <table name\>

    Especifica el nombre de la tabla que se va a crear. El <table name\> puede ser un identificador simple o un identificador de comillas dobles.

  • <colname\>

    Especifica el nombre de la columna que se va a crear.

  • <type\>

    Especifica el tipo de datos de AQL para la columna asociada. Todas las columnas deben ser de tipo Text, Integer, Float o Boolean.

  • <value\>

    Especifica las tuplas que se van a rellenar en la tabla creada.

Ejemplos

Ejemplo 1: Creación de una tabla de nombres de empresas

En este ejemplo, la sentencia create table añade más metadatos de ubicación a las anotaciones de nombre de empresa:

-- Create a dictionary of company names
create dictionary CompanyNames as
  ('IBM', 'BigCorp', 'Initech');

-- Find all matches of the company names dictionary.
create view Company as
  extract
    dictionary 'CompanyNames' on D.text as company
  from Document D;


-- Create a table that maps company names to locations of
-- corporate headquarters.
create table NameToLocation
  (name Text, location Text) as
  values
  ('IBM', 'USA'),
  ('BigCorp', 'Apex'),
  ('Initech', 'Dallas'),
  ('Acme Fake Company Names', 'Somewhere');

-- Use the table to augment the Company view with location
-- information.
create view CompanyLoc as
  select N2C.location as loc,
          C.company as company
  from Company C, NameToLocation N2C
  where Equals(GetText(C.company), GetText(N2C.name));

output view CompanyLoc;

Documentación de la sentencia create table con AQL Doc

El comentario AQL Doc correspondiente a una sentencia create table contiene la siguiente información:

  • Descripción general sobre la tabla.
  • @field correspondiente a cada nombre de columna del esquema de esta tabla.
/** Create a table that maps company names to locations
/** of corporate headquarters.
* @field name name of the company
* @field location location of corporate headquarters
*/

create table NameToLocation
  (name Text, location Text) as
 values
  ('IBM', 'USA'),
  ('Enron', 'UK'),
  ('Initech', 'Dallas'),
  ('Acme Fake Company Names', 'Somewhere');

La sentencia create external table

Puede utilizar la sentencia create external table para especificar una tabla con contenido establecido cuando se ejecuta un módulo compilado sobre todos los documentos de entrada. El contenido de la tabla se especifica durante el momento de la carga en lugar de hacerse en el código fuente de AQL, y no es necesario que vuelva a compilar el módulo.

Las tablas externas constituyen potentes construcciones que permiten al desarrollador de AQL exponer puntos de personalización en un módulo compilado.

Sintaxis

create external table <table-name\>
  (<colname\> <type\>
   [,  <colname\> <type\>]* )
   allow_empty <true|false>;

Descripción

  • <table-name\>

    Especifica el nombre de la tabla externa que se va a crear. El <table-name\> puede ser un identificador simple o un identificador de comillas dobles.

  • <colname\>

    Especifica el nombre de la columna que se va a crear.

  • <type\>

    Especifica el tipo de datos de AQL para la columna asociada. Todas las columnas deben ser de tipo Text, Integer, Float o Boolean.

  • [, <colname\> <type\>]*

    Especifica columnas y objetos AQL adicionales que se van a utilizar en la tabla externa.

  • allow_empty [true|false]

    Especifica el valor de la cláusula allow_empty.

    • true

      Si la cláusula es allow_empty true, el módulo se puede ejecutar correctamente aunque no se especifique un URI al contenido externo para esta tabla. Si no se especifica el URI, el componente de tiempo de ejecución la trata como una tabla vacía.

    • false

      Si la cláusula es allow_empty false, debe especificar un URI a la ubicación del archivo que contiene el contenido externo. El archivo especificado debe tener contenido. Si no se especifica el URI, o si el archivo no tiene contenido, el componente de tiempo de ejecución genera una excepción.

Notas de uso

  • La representación compilada del módulo contiene metadatos sobre los objetos externos (vistas, diccionarios y tablas) que define el módulo.
  • Cuando se cargan los módulos debe especificar una lista de URI a tablas externas, que es lo que necesitan los módulos que se cargan.
  • El formato soportado del contenido de una tabla externa es un archivo CSV (.csv) con cabecera.

En la tabla siguiente se muestran las diferencias entre la sentencia create external table y la sentencia create table:

create external table create table
  • Define un marcador para una tabla cuyo contenido se proporciona en el momento de la inicialización.
  • Requiere que el contenido de la tabla esté disponible en tiempo de compilación.
  • Serializado en la representación compilada (.tam) de un módulo.

Ejemplos

Ejemplo 1: Creación de una tabla externa que se llena en el momento de la carga

Se espera que la tabla externa, PersonNegativeClues, se llene en el momento de la carga debido al distintivo, allow_empty false.

module PersonModuleFrench;

create external table PersonNegativeClues (name Text)
  allow_empty false;

export table PersonNegativeClues;

Ejemplo 2: Creación de un diccionario con una tabla externa

Los diccionarios también se pueden crear a partir de tablas externas, de forma parecida a como se crean a partir de tablas en línea declaradas con la sentencia create table.

create external table Product (nickName Text, formalName Text)
allow_empty false;

/**
  * Dictionary of product nicknames, from the nickName field
  * of the customizable external table Product.
  */
create dictionary ProductDict
from table Product
with entries from nickName;

Documentación de la sentencia create external table con AQL Doc

El comentario AQL Doc correspondiente a una sentencia create external table contiene la siguiente información:

  • Descripción general sobre la tabla.
  • @field correspondiente a cada nombre de columna del esquema de esta tabla.
/** Create a table that maps company names to locations of corporate headquarters.
* @field name name of the company
* @field location location of corporate headquarters
*/
create external table Company2Location
  (name Text, location Text)
   allow_empty false;

La sentencia create external view

La sentencia create external view de AQL permite especificar más metadatos sobre un documento como una vista nueva, además de la vista Document predefinida que contiene el contenido textual y de etiquetas.

Sintaxis

create external view <view_name> (
        <colname> <type> [, <colname> <type>]*
        )
external_name '<view_external_name>';

Descripción

  • <view_name\>

    Especifica el nombre interno de la vista externa. Se hace referencia a la vista externa con este nombre en las reglas de AQL. Un <view_name\> puede ser un identificador simple o un identificador de comillas dobles. Un <view_name\> no puede contener el carácter de punto.

  • <colname\>

    Especifica el nombre de la columna que se va a definir en la vista externa.

  • <type\>

    Especifica el tipo de datos para la columna asociada. Los tipos de datos soportados para las columnas de vistas externas son Text, Span, Integer y Float.

  • '<view_external_name\>'

    Especifica el nombre externo de la vista externa. Los sistemas externos que llenan tuplas en la vista externa hacen referencia a la vista externa mediante el nombre externo. El '<view_external_name\>' debe ser una constante de serie que se encierre entre comillas simples ('ExternalName ').

Ejemplos

Para ilustrar las vistas externas, tomaremos como ejemplo una aplicación que requiere que identifique los nombres de las personas en los mensajes de correo electrónico.

Ejemplo 1: Identificación de los nombres de las personas en los mensajes de correo electrónico

Supongamos que el texto de un mensaje de correo electrónico es "Ena, please send me the document ASAP". Aunque un ser humano entiende por el texto del correo electrónico que Ena es el nombre de una persona, las reglas de AQL escritas para identificar nombres de personas con alta precisión en el texto general pueden ser demasiado conservadoras y quizás no sean capaces de llegar a la misma conclusión con un alto nivel de confianza, basándose en el hecho de que Ena es una palabra que empieza por mayúscula.

Una forma de aumentar la cobertura de las reglas consiste en utilizar palabras de los campos From (De), To (Para) y CC del correo electrónico como pruebas adicionales.

Si el correo electrónico va dirigido a "Ena Smith," y la aplicación pone esta información a disponibilidad del extractor, el desarrollador del extractor puede escribir más reglas de AQL para aumentar la cobertura del extractor que se basa en el conocimiento general de que los correos electrónicos suelen ir destinados a personas.

Por ejemplo, puede escribir reglas de AQL para identificar las señales de persona a partir de los campos de metadatos de correo electrónico. Puede utilizar esta información como pista fiable cuando decida si una señal que empieza por mayúscula en el texto del correo electrónico es un nombre de persona. En general, los metadatos del correo electrónico no forman parte del mensaje real del correo electrónico, pero la aplicación puede poner estos metadatos a disponibilidad del extractor mediante una vista externa.

Para cada correo electrónico que se debe procesar, la aplicación puede pasar el texto del correo electrónico como texto de documento (para llenar la vista Document) en el momento de la ejecución. También puede pasar los metadatos adicionales mediante una vista externa definida adecuadamente.

En la sentencia siguiente se define una vista externa llamada EmailMetadata. La vista externa tiene un esquema que contiene tres campos de tipo Text. En tiempo de ejecución, la vista EmailMetadata se llena automáticamente a partir de un tipo externo denominado EmailMetadataSrc. Luego puede hacer referencia a la vista EmailMetadata en las reglas de AQL, de forma similar a como haría referencia a cualquier otra vista.

create external view EmailMetadata
  (fromAddress Text, toAddress Text, ccAddress Text)
external_name 'EmailMetadataSrc';

Documentación de la sentencia create external view con AQL Doc

El comentario AQL Doc correspondiente a una sentencia create external view contiene la siguiente información:

  • Descripción general de la vista.
  • @field correspondiente a cada nombre de columna de la vista.
/**
* The external view named EmailMetadata, containing three fields
* of type Text. At run time, the view EmailMetadata is
* automatically populated from an external type named
* EmailMetadataSrc.
*
* @field from the fromAddress field of the email
* @field to the toAddress field of the email
* @field cc the ccAddress field of the email
*/

create external view EmailMetadata(fromAddress Text, toAddress Text, ccAddress Text)
external_name 'EmailMetadataSrc';

Formatos de archivo para artefactos externos

Se da soporte a tres tipos de artefactos externos: vistas externas, diccionarios externos y tablas externas.

Diccionario externo

El formato del archivo que contiene entradas para un diccionario externo se define aquí:

  • Archivo de texto delimitado por retorno de carro.
  • Una entrada de diccionario por línea.
  • La extensión de archivo recomendada es .dict, pero se pueden utilizar otras extensiones de archivo.
  • Las entradas del diccionario pueden constar de varias señales.
  • Los comentarios se pueden especificar anteponiendo el carácter # al contenido del comentario.
  • Los comentarios pueden comenzar en cualquier parte de una línea.
  • Los comentarios de varias líneas deben contener el carácter # al principio de cada línea.
  • Las entradas de diccionario pueden contener caracteres de comentario, si cada carácter de comentario se especifica con un carácter de barra inclinada invertida. Por ejemplo, \#.

Tabla externa

El formato de archivo soportado para el contenido de una tabla externa es un archivo .csv con cabecera.

En el ejemplo siguiente se muestra una sentencia create external table y el archivo .csv que especifica el contenido de esta tabla externa.

create external table Company2Location
  (name Text, location Text)
   allow_empty false;

La primera línea del archivo .csv contiene la cabecera. Las líneas restantes contienen los datos.

name,location
IBM,USA
Infosys,India
LG,Korea
Vodafone,UK

Vista externa

El contenido de las vistas externas se puede especificar de las formas siguientes:

  • Cuando ejecute un extractor, puede especificar el contenido de la vista externa para la colección de datos solo cuando utilice el formato de entrada JSON.

Funciones incorporadas

AQL tiene una colección de funciones incorporadas que puede utilizar en las reglas de extracción.

  • Funciones de agregación Las funciones de agregación se utilizan para implementar operaciones (como contar, operaciones matemáticas y otras operaciones) sobre un conjunto de valores de entrada. Estas funciones solo devuelven un resultado.
  • Funciones de predicado Las funciones de predicado prueban un determinado predicado sobre sus argumentos de entrada y devuelven un valor booleano correspondiente.
  • Funciones escalares Las funciones escalares realizan una operación sobre los valores de un campo en un conjunto de tuplas de entrada y devuelven un valor no booleano, como por ejemplo un valor de tipo Span, Text o Integer. Estas funciones se pueden utilizar dentro de la lista select de una sentencia select o de una sentencia extract. También se pueden utilizar como entradas para funciones de predicado.

Funciones de adición

Las funciones de agregación se utilizan para implementar operaciones (como contar, operaciones matemáticas y otras operaciones) sobre un conjunto de valores de entrada. Estas funciones solo devuelven un resultado.

Estas funciones se pueden utilizar dentro de la lista select de una sentencia select, pero no dentro de una sentencia extract.

A continuación se muestra un ejemplo del formato general de una llamada a una función de agregación:

Aggregate_Function_Name(argument)

El valor de argument puede ser:

  • Una expresión que contenga una columna de una vista en la cláusula from o una combinación de funciones escalares que impliquen columnas de las vistas de la cláusula from.

    En la mayoría de los casos, excepto en los que se indican, los valores nulos del argumento se pasan por alto.

  • El carácter * en el caso especial de la función de agregación Count(*).

    En este caso, se cuentan todas las filas de la salida, incluidos los valores nulos.

Función de agregación Tipo de argumento Tipo de retorno Valor de retorno
Avg(expresión) Integer, Float Float El promedio de todos los valores de entrada o nulo si no se selecciona ninguna fila
Count(*) Entero El número de todas las filas de entrada
Count(expresión) Cualquiera Entero El número de todos los valores de entrada no nulos
List(expresión) Integer, Float, Text, Span Lista de valores escalares del mismo tipo que el argumento de entrada Una lista no ordenada de valores de entrada no nulos: una bolsa, no un conjunto, puede por lo tanto contener duplicados. Una lista vacía si solo se seleccionan valores nulos
Max(expresión) Integer, Float, Text, Span Igual que el tipo de argumento El elemento máximo entre todos los valores de entrada o nulo si no se selecciona ninguna fila
Min(expresión) Integer, Float, Text, Span Igual que el tipo de argumento El elemento mínimo entre todos los valores de entrada o nulo si no se selecciona ninguna fila
Sum(expresión) Integer, Float Igual que el tipo de argumento La suma de todos los valores de entrada o nulo si no se selecciona ninguna fila

Limitaciones de la versión actual:

La versión actual de AQL da soporte a la creación de valores escalares mediante la lista de la función aggregate.

Ejemplos

En el ejemplo siguiente se muestra cómo las funciones de agregación pueden contar el número de anotaciones de nombres de persona o calcular conjuntos de nombres propios asociados a cada apellido distinto identificado en un documento:

-- identify occurrences of given names in the document
create view FirstName as
extract dictionary 'firstNames.dict' on D.text as name
from Document D;

-- identify occurrences of surnames in the document
create view LastName as
extract dictionary 'lastNames.dict' on D.text as name
from Document D;

-- identify complete person names in the document
create view Person as
select F.name as firstname, L.name as lastname
from FirstName F, LastName L
where FollowsTok(F.name, L.name, 0, 0);

-- count the number of person annotations in the document
create view CountPerson as
select Count(*)
from Person;

-- for each distinct surname, output a list of given names associated with it in the document
create view FamilyMembers as
select GetText(P.lastname) as lastname, List(GetText(P.firstname)) as firstnames
from Person P
group by GetText(P.lastname);

En el ejemplo siguiente se muestra el uso de las funciones Min y Max:

-- Extract stop words from input text
create view StopWords as
extract
regex /\s(the|in|a|an|as|to|from)\s/ on D.text as match
from Document D;


-- Count the number of times each stop word matched above, was used in the text
create view StopWordsCount as
select
GetText(S.match) as stopword,
Count(S.match) as stopwordcount
from StopWords S
group by GetText(S.match);

-- Retrieve the most used and least used stop word count
create view StopWordUsageCount as
        select Min(S.stopwordcount) as least, Max(S.stopwordcount) as most
from StopWordsCount S;

Funciones de predicado

Las funciones de predicado prueban un determinado predicado sobre sus argumentos de entrada y devuelven un valor booleano correspondiente.

Los argumentos de entrada de las funciones de predicado incluyen valores de retorno de otras funciones escalares o de agregación, además de diccionarios, expresiones regulares y más. Estas funciones se pueden utilizar dentro de la cláusula where de una sentencia select y de la cláusula having de una sentencia extract.

Y

La función And acepta un número variable de argumentos booleanos y devuelve los resultados de una operación AND sobre todos los argumentos de entrada.

El optimizador de AQL no intenta optimizar el orden de evaluación de los argumentos de esta función como parte de la operación AND lógica. Si alguna entrada es null, el resultado es null.

Examine este formato de consulta:

select ...
from ...
where And(predicate1, predicate2);

Como resultado, un formato de consulta que utiliza la operación AND se suele ejecutar con bastante más lentitud que la misma consulta con el formato:

select ...
from ...
where predicate1 and predicate2;

Siempre que sea posible, utilice el estilo SQL y la palabra clave en lugar de esta función.

Contiene

La función Contains toma dos tramos como argumentos:

Contains(<span1>, <span2>)

Esta función devuelve TRUE si span1 contiene por completo el tramo 2 (span2). Si span2 empieza al principio de span1 o después y termina al final de span1 o antes, span2 está contenido por completo. Si algún argumento es null, la función devuelve null.

ContainsDict

La función ContainsDict comprueba si el texto de un tramo contiene alguna entrada de un diccionario determinado. Esta función acepta como argumentos de entrada un diccionario, una especificación de distintivo opcional y un tramo que evaluar.

ContainsDict('<dictionary>', ['<flags>', ]<span>)

La función ContainsDict devuelve TRUE si el tramo contiene una o varias coincidencias del diccionario. Los distintivos pueden ser Exact o IgnoreCase.

  • Si se utiliza Exact, se realiza una comparación que distingue entre mayúsculas y minúsculas de cada término del diccionario.
  • Si se utiliza IgnoreCase, la comparación que se realiza sobre cada término del diccionario no distingue entre mayúsculas y minúsculas.
  • Si no se especifica ningún distintivo, el diccionario realiza la comparación en función de cualquier distintivo que se haya especificado al crearlo. Si no se ha especificado ningún distintivo durante la creación, realiza la comparación utilizando solo el distintivo IgnoreCase.

Si el tramo es null, la función devuelve null.

En el ejemplo siguiente se muestra el uso de la función ContainsDict:

create dictionary EmployeePhoneDict as
(
 '121-222-2346', '121-234-1198', '121-235-8891'
);

create view PhoneNum as
extract regex /(\d{3})-(\d{3}-\d{4})/
    on between 4 and 5 tokens in D.text
    return
        group 1 as areaCode
        and group 2 as restOfNumber
        and group 0 as number
from Document D;

create view PhoneNumbers as
select P.number as number
from PhoneNum P
where ContainsDict('EmployeePhoneDict',P.number);

Los diccionarios siempre se evalúan en los límites de la señal. Por ejemplo, si un diccionario contiene el término fish, no hay ninguna coincidencia en el texto Let's go fishing!.

ContainsDicts

La función ContainsDicts comprueba si el texto de un tramo contiene alguna entrada de un diccionario determinado. Esta función acepta como argumentos de entrada dos o más diccionarios, una especificación de distintivo opcional y un tramo que evaluar.

ContainsDicts('<dictionary>','<dictionary>','<dictionary>', ['<flags>', ]<span>)

La función ContainsDicts devuelve TRUE si el tramo contiene una o varias coincidencias de al menos uno de los diccionarios especificados. Los distintivos pueden ser Exact o IgnoreCase.

  • Si se utiliza Exact, se realiza una comparación que distingue entre mayúsculas y minúsculas de cada uno de los términos de los diccionarios.
  • Si se utiliza IgnoreCase, la comparación que se realiza sobre cada uno de los términos de los diccionarios no distingue entre mayúsculas y minúsculas.
  • Si no se especifica ningún distintivo, el diccionario realiza la comparación en función de cualquier distintivo que se haya especificado al crearlo. Si no se ha especificado ningún distintivo durante la creación, realiza la comparación utilizando solo el distintivo IgnoreCase.

Si alguno de los argumentos, o ambos, es nulo, la función devuelve null.

En el ejemplo siguiente se muestra el uso de la función ContainsDicts con el distintivo Exact:

create view PersonWithFirstName as
select P.reference as reference
from Person P
where ContainsDicts(
'FirstNamesUsedGlobally',
'FirstNamesUsedInGermanyLong',
'NickNamesUsedGlobally',
'FirstNamesUsedInGermanyShort',
'FirstNamesUsedInItaly',
'FirstNamesUsedInFrance',
'Exact',
P.reference);

ContainsRegex

La función ContainsRegex comprueba si el texto de un tramo coincide con una expresión regular determinada. Esta función acepta una expresión regular con la que se realiza la comparación, una especificación de distintivo opcional y el tramo de entrada sobre el que se realiza la comparación.

ContainsRegex(/<regular expression>/, ['<flags>', ]<span>)

La función devuelve TRUE si el texto del tramo, que se toma como una serie Java™ independiente, contiene una o varias coincidencias de la expresión regular. La función devuelve null si el tramo es null. Los distintivos opcionales afectan al comportamiento de la comparación, de forma similar a los distintivos utilizados en las expresiones regulares Java.

La serie de distintivos se forma combinando uno o varios de los distintivos siguientes utilizando | como separador:

  • CANON_EQ
  • CASE_INSENSITIVE
  • DOTALL
  • LITERAL
  • MULTILINE
  • UNICODE (no tiene sentido sin CASE_INSENSITIVE)
  • UNIX_LINES

Un ejemplo de una serie de distintivos es

'UNICODE | CASE_INSENSITIVE'

Observe este ejemplo en el que ContainsRegex identifica nombres de productos junto con sus menciones de número de versión en ambos lados. A diferencia del ejemplo correspondiente a MatchesRegex, una comparación de número de versión no se identifica de forma estricta mediante regex, sino mediante el contexto que rodea una mención de un nombre de producto que contiene una señal que se compara con regex.


-- dictionary of product names
create dictionary ProductNamesDict as
(
  'IBM WebSphere Application Server',
  'Microsoft Windows',
  'Apple Mac OS',
  'IBM Rational Application Developer',
  'Apache HTTP Server',
  'Eclipse',
  'Google Android'
);

-- extract product names from input text
create view ProductNames as
extract
  dictionary 'ProductNamesDict'
  on D.text as name
from Document D;

-- gather context around product name mention
create view ProductNamesWithContext as
select
  P.name as name,
  LeftContext(P.name, 5) as leftctxt,
  RightContext(P.name, 5) as rightctxt
from ProductNames P;

-- use a regex to identify products with version number mentions on either sides of the product mention
create view ProductsWithVersionNumbers as
(
  select
    P.name as productname,
    P.leftctxt as productversion
  from ProductNamesWithContext P
  where ContainsRegex (/v\d((\.\d)+)?/, P.leftctxt)
)
union all
(
  select
    P.name as productname,
    P.rightctxt as productversion
  from ProductNamesWithContext P
  where ContainsRegex (/v\d((\.\d)+)?/, P.rightctxt)
);

Igual que

La función Equals toma dos argumentos de tipo arbitrario:

Equals(<arg1>, <arg2>)

Se considera que dos tramos son iguales si ambos empiezan y terminan en los mismos desplazamientos y contienen el mismo texto. Si alguno de los argumentos, o ambos, es nulo, la función devuelve null.

En el ejemplo siguiente se muestra el uso de la función Equals.

-- Select phone number spans whose text is equal to 001-543-2217
create view PhoneNumber as
select P.number as number
from PhoneNum P
where Equals('001-543-2217',GetText(P.number));

Sigue a

La función del predicado Follows toma dos argumentos span (tramo) y dos argumentos integer (entero):

Follows(<span1>, <span2>, <minchar>, <maxchar>)

La función devuelve TRUE si el número de caracteres entre el final de span1 y el principio de span2 se encuentra entre minchar y maxchar, ambos inclusive. Si algún argumento es null, la función devuelve null.

FollowsTok

La función del predicado FollowsTok es una versión de Follows; sin embargo, los argumentos de distancia FollowsTok se especifican en términos de señales en lugar de caracteres:

FollowsTok(<span1>, <span2>, <mintok>, <maxtok>)

La función FollowsTok devuelve TRUE si el número de señales entre el final de span1 y el principio de span2 se encuentra entre mintok y maxtok, ambos inclusive. Si algún argumento es null, la función devuelve null.

GreaterThan

La función del predicado GreaterThan toma dos argumentos de tipo arbitrario:

GreaterThan(<arg1>, <arg2>)

La función devuelve TRUE si <arg1> es mayor que <arg2>. La función devuelve FALSE si alguno de los argumentos es null.

IsNull

La función IsNull prueba si los datos son nulos o no son nulos. Toma un solo argumento de cualquier tipo y devuelve TRUE si el argumento único es null y FALSE si no es así. El comportamiento de este predicado y del predicado NotNull ya definido es diferente de todos los demás predicados que devuelven nulo si una entrada es nula.

MatchesDict

La función MatchesDict toma un diccionario (como en una extracción de diccionario), una especificación de distintivo opcional y un tramo como argumentos:

MatchesDict('<dictionary>', ['<flags>', ]<span>)

La función MatchesDict devuelve TRUE si el tramo coincide exactamente con uno o varios de los términos del diccionario. Los distintivos pueden ser Exact o IgnoreCase.

  • Si se utiliza Exact, se realiza una comparación que distingue entre mayúsculas y minúsculas de cada término del diccionario.
  • Si se utiliza IgnoreCase, la comparación que se realiza sobre cada término del diccionario no distingue entre mayúsculas y minúsculas.
  • Si no se especifica ningún distintivo, el diccionario realiza la comparación en función de cualquier distintivo que se haya especificado al crearlo. Si no se ha especificado ningún distintivo durante la creación, realiza la comparación utilizando solo el distintivo IgnoreCase.

Si algún argumento es null, la función devuelve null.

Los diccionarios siempre se evalúan en los límites de la señal. Por ejemplo, si un diccionario contiene el término fish, no hay ninguna coincidencia en el texto Let's go fishing!.

MatchesRegex

La función MatchesRegex tiene una sintaxis similar a ContainsRegex. A diferencia de la función ContainsRegex, la función MatchesRegex solo devuelve TRUE si todo el texto del tramo, tomado como una serie Java distinta, coincide con la expresión regular. Si algún argumento es null, la función devuelve null. Los distintivos opcionales afectan al comportamiento de la comparación, de forma similar a los distintivos utilizados en las expresiones regulares Java.

MatchesRegex(/<regular expression>/, ['<flags>', ]<span>)

La serie de distintivos se forma combinando un subconjunto de estos distintivos utilizando | como separador:

  • CANON_EQ
  • CASE_INSENSITIVE
  • DOTALL
  • LITERAL
  • MULTILINE
  • UNICODE (no tiene sentido sin CASE_INSENSITIVE)
  • UNIX_LINES

Un ejemplo de una serie de distintivos es

'UNICODE | CASE_INSENSITIVE'

Observe este ejemplo en el que se utiliza MatchesRegex para identificar nombres de productos junto con sus menciones de número de versión a la derecha. A diferencia del ejemplo de la sección ContainsRegex, el número de versión exacto se identifica como la señal inmediatamente después de la mención del nombre del producto.

-- gather right context around product name mention
create view ProductNamesWithContext as
select
  P.name as name,
  RightContext(P.name, 5) as rightctxt
from ProductNames P;

-- use a regex to identify products with version number mentions to the right
create view ProductsWithVersionNumbers as
select
  P.name as productname,
  P.rightctxt as productversion
from ProductNamesWithContext P
where MatchesRegex (/v\d((\.\d)+)?/, P.rightctxt);

No

La función Not toma un único argumento booleano y devuelve su complemento. Si el argumento es null, la función devuelve null.

NotNull

La función NotNull toma un solo argumento de cualquier tipo.

Tal como sugiere su nombre, la función NotNull devuelve TRUE si el valor del argumento no es nulo y FALSE si el argumento es null.

O

La función Or toma un número variable de argumentos booleanos no nulos. Si algún argumento es null, la función devuelve null.

La función Or devuelve TRUE si alguno se evalúa como TRUE.

Solapamientos

La función Overlaps toma dos argumentos span (tramo):

Overlaps(<span1>, <span2>)

La función devuelve TRUE si los dos tramos de entrada se solapan en el texto del documento. La función devuelve null si alguno de los argumentos es null.

Funciones escalares

Las funciones escalares realizan una operación sobre los valores de un campo en un conjunto de tuplas de entrada y devuelven un valor no booleano, como por ejemplo un valor de tipo Span, Text o Integer. Estas funciones se pueden utilizar dentro de la lista select de una sentencia select o de una sentencia extract. También se pueden utilizar como entradas para funciones de predicado.

Si se especifica un objeto de tipo Text donde se necesita uno de tipo Span, se genera automáticamente un objeto Span convertido, que se basa en este objeto Text, con desplazamientos inicial y final que cubren toda la longitud del objeto Text.

Si se especifica un objeto de tipo Span donde se necesita uno de tipo Text, se genera automáticamente un objeto de tipo Text convertido a partir del valor de texto del objeto Span.

Chomp

La función Chomp es similar al operador Chomp en Perl, excepto en que Chomp opera sobre tramas en lugar de sobre series:

Chomp(<span1>)

En el ejemplo siguiente se muestra el uso de la función Chomp.

detag Document.text as DetaggedDoc
annotate
element 'a' as Anchor
with attribute 'href' as linkTarget;

create view Links as
select Chomp(A.linkTarget) as link
from Anchor A;

Si el tramo de entrada contiene un espacio en blanco al principio o al final, la función Chomp reduce el tramo lo suficiente para eliminar el espacio en blanco. A continuación, la función devuelve un nuevo tramo sin ningún espacio en blanco inicial ni final. Si el tramo de entrada no tiene un espacio en blanco inicial o final, la función Chomp devuelve el mismo tramo. Si el tramo de entrada es null, Chomp devuelve null.

CombineSpans

La función CombineSpans toma dos tramos como entrada y devuelve el tramo más corto que cubre por completo ambos tramos de entrada si los tramos se basan en el mismo objeto de texto.

CombineSpans(['IgnoreOrder',] <span1>, <span2>)

La función CombineSpans tiene en cuenta el orden de sus tramos de entrada, a menos que utilice el parámetro IgnoreOrder. Cuando se utiliza el parámetro opcional IgnoreOrder, no se tiene en cuenta el orden de los dos tramos.

En el ejemplo siguiente se muestra el uso de la función CombineSpans.

create view FullName as
     select
             CombineSpans('IgnoreOrder',F.name, L.name) as fullName
     from
             FirstName F,
             LastName L
     where
             FollowsTok(F.name, L.name, 0,0);

La semántica de la función es la siguiente:

  • Si span1 o span2 es null, o si los dos tramos pertenecen a distintos objetos Text, la función devuelve null.
  • De lo contrario, si span1 es más corto que span2 o si se utiliza el parámetro IgnoreOrder, la función devuelve el tramo más corto que cubre tanto span1 como span2.
  • Si (span1 es más largo que span2 y no se utiliza IgnoreOrder), la función devuelve un error de tiempo de ejecución.

En función de la definición de Span, los distintos tipos de argumentos de la función CombineSpans son los siguientes:

  • El intervalo 2 siempre está después del intervalo 1. Es decir, se mantiene el orden de izquierda a derecha:

    CombineSpans([0,7], [3,7]) returns the span [0,7]
    CombineSpans([0,7], [8,10]) returns the span [0,10]
    CombineSpans([0,7], [3,6]) returns the span [0,7]
    CombineSpans([0,7], [0,7]) returns the span [0,7]
    
  • El intervalo 2 no va después del intervalo 1. Es decir, el orden de izquierda a derecha no se mantiene:

    CombineSpans(‘IgnoreOrder’, [0,10], [0,7]) returns the span [0,10]
    CombineSpans(‘IgnoreOrder’, [3,6], [0,7]) returns the span [0,7]
    CombineSpans(‘IgnoreOrder’, [3,7], [0,7]) returns the span [0,7]
    CombineSpans(‘IgnoreOrder’, [8,10], [0,7]) returns the span [0,10]
    CombineSpans([3,6], [0,7]) will result in Runtime error as the IgnoreOrder flag has not been specified.
    

GetBegin y GetEnd

La función GetBegin toma un único argumento span y devuelve el desplazamiento inicial del tramo de entrada.

Por ejemplo:

GetBegin([5, 10])

devuelve el valor 5.

Del mismo modo, la función GetEnd devuelve el desplazamiento final de su tramo de entrada.

En el ejemplo siguiente se muestra el uso de las funciones GetBegin y GetEnd.

create view PersonOffsets as
select GetBegin(P.name) as offsetBegin, GetEnd(P.name) as offsetEnd
from Person P;

Para estas dos funciones, si el argumento es null, la función devuelve null.

GetLanguage

La función GetLanguage toma un único argumento span y devuelve el código de idioma de dos letras del texto de origen del tramo. Si el argumento es null, la función devuelve null.

Esta sentencia solo genera resultados significativos si el origen de los datos son campos de texto etiquetados con los idiomas adecuados.

GetLemma

La función GetLemma toma un solo objeto Span o Text como argumento y devuelve una serie que contiene la forma lematizada del tramo de entrada. Si el argumento es null, la función devuelve null. Con entradas del diccionario para la comparación de lemas, esta función puede determinar la forma lematizada de varias señales devueltas por el señalizador. Por ejemplo, para el tramo went shopping, GetLemma devuelve la serie del lema go shop.

Los resultados de esta función siguen estas reglas:

  • Si el intervalo de entrada comienza al principio de una señal y termina al final de una señal, el resultado contiene la secuencia de lemas que comienza con el lema de la primera señal, seguido por un espacio en blanco, seguido por el lema de la segunda señal, seguido por un espacio en blanco, y así sucesivamente (por ejemplo, perro gato pez pájaro...). Si el lema correspondiente a una señal consiste en espacios en blanco, especifique el espacio en blanco entre caracteres de barra inclinada invertida ( \ ).
  • Si el tramo de entrada empieza o termina por un espacio en blanco (por ejemplo, empieza entre dos señales o termina entre dos señales), la función pasa por alto el espacio en blanco inicial y final.
  • Si el tramo de entrada empieza en medio de una señal o termina en medio de una señal, la salida consiste en el siguiente contenido, en este orden, y separado por un espacio en blanco:
    • La forma superficial de la primera señal parcial, si existe.
    • La secuencia de lemas correspondiente a las señales completas entre la primera y la última. Si el lema correspondiente a cualquiera de las señales completas consiste en espacios en blanco, especifique los espacios en blanco entre caracteres de barra inclinada invertida (\).
    • La forma superficial de la última señal parcial, si existe.

Esta función devuelve un error si el señalizador que se utiliza no es capaz de producir lemas.

Puede utilizar la función GetLemma() para crear diccionarios de formas lematizadas. Llame a la función GetLemma() en una entrada que contenga los términos cuya forma lematizada desea incluir en el diccionario.

GetLength

La función GetLength toma un único argumento span y devuelve la longitud del tramo de entrada. Si el argumento es null, la función devuelve null.

Por ejemplo:

GetLength([5, 12])

devuelve el valor 7.

GetLengthTok

La función GetLengthTok toma un único argumento span y devuelve la longitud del tramo de entrada en señales. Si el argumento de entrada es null, la función devuelve null.

GetString

La función GetString toma un solo objeto AQL como su argumento y devuelve un objeto de tipo Text formado a partir de la representación de serie del objeto.

En el caso de los argumentos span y text, los valores que se devuelven son distintos de los que devuelve la función GetText(). En el caso de objetos Text, el valor devuelto incluye la serie de texto entre comillas simples. En el caso de objetos span, el valor devuelto incluye además desplazamientos entre corchetes.

Para listas escalares, esta función devuelve los valores GetString() de los elementos de la lista, concatenados con signos de punto y coma. En el caso de argumentos Integer, Float, Boolean y String, esta función devuelve el valor del argumento como una serie. En el caso de argumentos null, esta función devuelve null.

GetText

La función GetText toma un solo tramo o texto como un argumento. Si la entrada es un tramo, devuelve el objeto de texto en función de la serie de texto real que marca el tramo. Si la entrada es texto, devuelve el objeto de texto de entrada. Si la entrada es null, esta función devuelve null. Por ejemplo:

GetText([5, 12])

El tramo devuelve la subserie del documento de la posición de caracteres 5-12.

La función GetText tiene dos usos principales.

Prueba de la igualdad de series entre el texto marcado por dos tramos.

-- Create a dictionary of company names
create dictionary CompanyNames as
('IBM', 'BigCorp', 'Initech');

-- Find all matches of the company names dictionary.
create view Company as
extract
    dictionary 'CompanyNames' on D.text as company
from Document D;


-- Create a table that maps company names to locations of
-- corporate headquarters.
create table NameToLocation (name Text, location Text) as
values
    ('IBM', 'USA'),
    ('BigCorp', 'Apex'),
    ('Initech', 'Dallas'),
    ('Acme Fake Company Names', 'Somewhere');

-- Use the table to augment the Company view with location
-- information.
create view CompanyLoc as
select N2C.location as loc, C.company as company
from Company C, NameToLocation N2C
where Equals(GetText(C.company), GetText(N2C.name));

output view CompanyLoc;

División de un documento en subdocumentos más pequeños.

Por ejemplo, si el documento principal es un blog consistente en varias entradas de blog, puede utilizar GetText para crear un subdocumento para cada entrada de blog.

detag Document.text as DetaggedBlog
annotate
    element 'blog' as Blog
    with attribute 'name' as title;


create view BlogEntry as
select B.match as entry, B.title as title
from Blog B;

-- Turn each tuple in the BlogEntry view into a sub-document
create view BlogEntryDoc as
select GetText(B.title) as title, GetText(B.entry) as body
from BlogEntry B;

output view BlogEntryDoc;

--Dictionary for Companies
create dictionary CompanyNameDict as
(
    'A Corporation', 'B Corporation'
);

-- Run an extraction over the sub-documents.
-- The spans that this "extract" statement creates will have
-- offsets relative to the blog entries themselves, as opposed
-- to the original multi-entry document.
create view CompanyName as
extract dictionary 'CompanyNameDict' on B.body as name
from BlogEntryDoc B;

output view CompanyName;

LeftContext y RightContext

La función LeftContext toma un argumento Span y uno Integer como entrada:

LeftContext(<input span>, <nchars>)

La función LeftContext(<input span\>, <nchars\>) devuelve un nuevo intervalo que contiene los caracteres nchars del documento inmediatamente a la izquierda de <input span\>. Si el intervalo de entrada comienza menos de <nchars\> caracteres desde el principio del documento, LeftContext() devuelve un intervalo que comienza al principio del documento y continúa hasta el principio del intervalo de entrada.

Por ejemplo, LeftContext([20, 30], 10) devuelve el tramo [10, 20]. El tramo LeftContext([5, 10], 10) devuelve [0, 5].

Si la entrada empieza en el primer carácter del documento, LeftContext() devuelve un tramo de longitud cero. De forma similar, la función RightContext devuelve el texto que hay a la derecha de su tramo de entrada. Para ambas funciones, si algún argumento es null, la función devuelve null.

LeftContextTok y RightContextTok

Las funciones LeftContextTok y RightContextTok son versiones de LeftContext y RightContext que toman las distancias en términos de señales:

LeftContextTok(<input span>, <num tokens>)
RightContextTok(<input span>, <num tokens>)

En el ejemplo siguiente se muestra el uso de la función RightContextTok.

create view Salutation as
extract
 regex /Mr\.|Ms\.|Miss/
  on D.text as salutation
  from Document D;

--Select the token immediately following a Salutation span
create view NameCandidate as
select RightContextTok(S.salutation, 1) as name
from Salutation S;

Para ambas funciones, si algún argumento es null, la función devuelve null.

Remap

La función Remap toma un solo argumento span:

Remap(<span>)

Si el tramo de entrada está sobre un objeto de texto generado mediante la transformación de otro objeto de texto, la función Remap convierte el tramo en un tramo sobre el texto de "origen" original.

Por ejemplo, si el tramo N.name está sobre un documento sin etiquetas generado mediante la ejecución de HTML sobre la sentencia de AQL detag, entonces

Remap(<N.name>)

devuelve un tramo equivalente sobre el HTML original.

Si el argumento span se ha generado mediante la ejecución de la sentencia detag sobre un documento vacío, la función vuelve a correlacionar los tramos con el principio del documento (es decir, Document.text[0-0]). Además, si la sentencia detag genera un aserie vacía, la función vuelve a correlacionar los tramos con el principio del documento. La única parte de AQL que genera este tipo de objeto de texto derivado es la sentencia detag.

En el ejemplo siguiente se muestra el uso de la función Remap:

-- Detag the HTML document and annotate the anchor tags
detag Document.text as DetagedDoc
    annotate
    element 'a' as Anchor;

-- Remap the Anchor Tags
create view AnchorTag as
select Remap(A.match) as anchor
from Anchor A;

Si el argumento de Remap no es un objeto de texto derivado o un tramo sobre un objeto de texto derivado, la función genera un error. Si el argumento es null, la función devuelve null.

SpanBetween

La función SpanBetween toma dos tramos como entrada y devuelve el tramo que cubre exactamente el texto comprendido entre los dos tramos si los tramos se basan en el mismo objeto de texto, y devuelve null si se basan en distintos objetos de texto:

SpanBetween(['IgnoreOrder',] <span1>, <span2>)

Si se utiliza el parámetro opcional IgnoreOrder, el compilador de AQL no tiene en cuenta el orden de los dos tramos.

Si no existe texto entre los dos intervalos, SpanBetween devuelve un intervalo vacío que comienza al final de <span1>.

Al igual que CombineSpans, SpanBetween es sensible al orden de sus entradas, a menos que utilice el parámetro IgnoreOrder. Así,

SpanBetween([5, 10], [50, 60])

devuelve el tramo [10, 50], mientras que

SpanBetween([50, 60], [5, 10])

devuelve el tramo [60, 60].

Si el argumento de SpanBetween es null, la función devuelve null.

SpanIntersection

La función SpanIntersection toma dos tramos como entrada y devuelve un tramo que cubre el texto que cubren ambas entradas si los tramos se basan en el mismo objeto de texto, y devuelve null si se basan en distintos objetos de texto:

SpanIntersection(<span1>, <span2>)

Por ejemplo:

SpanIntersection([5, 20], [10, 60])

devuelve el tramo [10, 20], mientras que

SpanIntersection([5, 20], [7, 10])

devuelve el tramo [7, 10].

Si los dos tramos no se solapan, SpanIntersection devuelve null. Si la entrada de algún tramo es null, la función devuelve null.

SubSpanTok

La función SubSpanTok toma como entrada un tramo y un par de desplazamientos en el tramo:

SubSpanTok(<span>, <first_tok>, <last_tok>)

Como sugiere el nombre de la función, los argumentos <first_tok> y <last_tok> son distancias en las señales, de acuerdo con cualquier simbolizador que el sistema esté configurado para utilizar.

La función SubSpanTok devuelve un nuevo tramo que cubre el rango de señales indicado, incluido, dentro del tramo de entrada. Si el rango especificado empieza dentro del tramo y va más allá del final del tramo, se devuelve la parte del rango que está contenida. Si <first_tok> representa una distancia más allá del intervalo de destino, SubSpanTok devuelve un intervalo de longitud cero que comienza al principio del intervalo de entrada.

Si alguna entrada es null, la función devuelve null.

ToLowerCase

La función ToLowerCase toma un solo objeto como su argumento y devuelve una representación del objeto como una serie en minúsculas. La conversión en una serie se produce de la misma forma en que la función GetString() realiza la conversión.

Esta función se utiliza principalmente para realizar uniones de igualdad que no distingan entre mayúsculas y minúsculas:

where Equals(ToLowerCase(C.company), ToLowerCase(N2C.name))

Si el objeto de entrada es null, la función devuelve null.

La sentencia create function

Para realizar operaciones sobre valores extraídos que no reciben soporte de AQL, puede definir funciones personalizadas que se utilizarán en las reglas de extracción denominadas funciones definidas por el usuario (UDF).

AQL admite funciones escalares definidas por el usuario y funciones de tabla definidas por el usuario. Java™ y PMML son los únicos lenguajes de implementación admitidos para las UDF. Una función escalar devuelve un solo valor escalar, y una función de tabla devuelve una o varias tuplas, es decir, una tabla.

Para implementar funciones definidas por el usuario (UDF), siga estos pasos:

  1. Implementación de la función

    AQL admite funciones definidas por el usuario (UDF) implementadas en Java o PMML.

  2. Declaración de la misma en AQL.

    Puede hacer que las funciones escalares definidas por el usuario y los modelos de aprendizaje automático procedentes de los archivos PMML estén disponibles en AQL mediante la sentencia create function.

  3. Utilización de la misma en AQL.

    Las funciones definidas por el usuario funcionan con las sentencias y las cláusulas de AQL.

  4. Depuración de la UDF.

    Puesto que las funciones definidas por el usuario (UDF) basadas en Java se implementan como métodos públicos en las clases Java, las UDF se depuran de la misma forma que se depuran los programas Java.

Implementación de funciones definidas por el usuario

AQL admite funciones definidas por el usuario (UDF) implementadas en Java™ o PMML.

Esta sección se centra específicamente en las UDF que se implementan en Java. Para las UDF implementadas en PMML, el modelo de aprendizaje automático se almacena dentro del archivo XML de PMML. Consulte la documentación de PMML para ver cómo se crean estos modelos: [http://dmg.org/pmml/v4-1/GeneralStructure.html]

Puede implementar una UDF escalar como un método público en una clase Java. Puede implementar una UDF de tabla como un método público en una clase Java que amplíe la API com.ibm.avatar.api.udf.TableUDFBase. Además, una UDF de tabla puede modificar el método initState() de la superclase com.ibm.avatar.api.udf.TableUDFBase.

Si la UDF tiene un parámetro de entrada de tipo Span, Text o ScalarList, o si el tipo de retorno de la UDF es Span, Text o ScalarList, la clase Java debe importar las clases com.ibm.avatar.algebra.datamodel.Span, com.ibm.avatar.algebra.datamodel.Text o com.ibm.avatar.algebra.datamodel.ScalarList para compilar.

Las funciones de tabla requieren API adicionales para proporcionar información del esquema de salida. Estas API pertenecen a la clase base com.ibm.systemt.api.udf.TableUDFbase. Si una subclase contiene más de una función de tabla, se crea un objeto Java independiente para cada instancia.

Para que el código de la UDF recupere recursos que no sean de clase de su archivo JAR, el único método admitido es getResourceAsStream(). No se admiten otros métodos para acceder a los recursos (como getResource(), getResources(), getSystemResource()). Por ejemplo, un archivo JAR de UDF que contenga el archivo de propiedades my.properties en el paquete com.ibm.myproject.udfs, puede acceder al mismo con la siguiente sentencia Java:

InputStream in = this.getClass().getClassLoader().
  getResourceAsStream(“com/ibm/myproject/udfs/my.properties”);

Ciclo de vida de las UDF implementadas en Java

Se realizan las siguientes operaciones cuando el extractor se compila (API CompileAQL.compile()), cuando se crea una instancia (API OperatorGraph.createOG()) y cuando se valida (API OperatorGraph.validateOG()), exactamente una vez por cada sentencia create function en AQL:

  1. Se carga la clase Java que contiene el método UDF, utilizando un nuevo cargador de clases. Se accede a la clase dentro del JAR de UDF especificado en la sentencia create function correspondiente. También se accede a cualquier otra clase necesaria cuando se carga esta clase dentro del mismo archivo JAR de UDF y, si no se encuentra, la búsqueda se delega en el cargador de clases (classloader) que ha creado la instancia del tiempo de ejecución.
  2. Se crea una instancia de esta clase.
  3. Para las UDF de tabla, se invoca el método initState().

Puesto que estos pasos se realizan para cada sentencia create function, si una clase Java contiene varios métodos de UDF (y todos los métodos se utilizan en AQL en distintas sentencias create function), la clase se cargará varias veces, cada una de ellas en un cargador de clases diferente (Paso 1). Además, se crean varias instancias de la clase (Paso 2) y se llama al método initState() una vez por cada instancia (Paso 3). El motivo de que cada UDF dé como resultado un cargador de clases independiente es permitir que diferentes UDF utilicen distintas versiones de la misma clase (o biblioteca).

En tiempo de ejecución (API OperatorGraph.execute()), la clase de la UDF no se vuelve a cargar, porque la clase se carga durante la creación de la instancia del extractor. El método Java que implementa la UDF se invoca cuando es necesario para calcular las partes de la salida. Cuando se utiliza el extractor dentro de una sola hebra, significa que existen entre cero invocaciones y posiblemente muchas invocaciones para cada documento de entrada (y probablemente varias invocaciones a lo largo de la vida del objeto Operator Graph). Cuando el extractor se comparte entre varias hebras, las distintas hebras pueden acceder al método aproximadamente al mismo tiempo (con distintas entradas).

Si necesita que una parte específica del código de la UDF se evalúe exactamente una vez, por ejemplo para iniciar las estructuras de datos que necesita el método de la UDF a través de las invocaciones, no se debe colocar este código en el método de evaluación de la UDF, ya que es muy probable que este método se ejecute varias veces a lo largo de la vida del extractor (al igual que el objeto OperatorGraph), y se puede acceder al mismo simultáneamente si el extractor se comparte entre varias hebras. En su lugar:

  1. Para las UDF escalares, siga los principios de programación estándares de Java. Por ejemplo, coloque el código en un bloque estático.
  2. Para las UDF de tabla, coloque el código en el método initState() o siga los principios de programación estándares de Java. Por ejemplo, coloque el código en un bloque estático.

Cuando lo haga, recuerde que la clase se puede cargar varias veces durante la compilación, creación de instancias y validación del extractor, tal como se ha explicado en los pasos 1-3 anteriores. Si el código que inicializa la UDF se coloca en un bloque estático, ese código se ejecuta cada vez que se cargue la clase (potencialmente varias veces), por lo que se introducirá una sobrecarga durante la compilación y la creación de instancias del objeto Operator Graph. Si la sobrecarga es grande, siga estas prácticas recomendadas:

  • Para minimizar la sobrecarga durante el tiempo de compilación, la práctica recomendada consiste en colocar los recursos que requieren mucho tiempo de compilación, como diccionarios o UDF con mucho tiempo de inicialización, en un módulo AQL independiente y exportarlos. Intente compilar solo los módulos de AQL que han cambiado y otros módulos que dependen de ellos.
  • Para minimizar la sobrecarga durante la creación de instancias y la validación del objeto Operator Graph:
    1. Si solo un método de UDF necesita el código de inicialización, coloque ese método de UDF en una clase Java independiente (y coloque el código que requiere muchas instancias en un inicializador estático como antes, o utilice algún otro mecanismo que asegure que el código se ejecute una vez).
    2. Si el código de inicialización se comparte entre varios métodos UDF, el tiempo de ejecución y AQL no proporcionan un mecanismo explícito para garantizar que el código de inicialización se ejecute exactamente una vez. En una situación de este tipo, si el tiempo de inicialización es excesivo, la única solución es colocar los recursos compartidos y el código de inicialización en la variable class path del sistema. Es decir, coloque el código de inicialización en una nueva clase MySeparateClass.java y guarde el resultado de la inicialización en una variable estática de esta clase, como por ejemplo MySeparateClass.myVar. Empaquete MySeparateClass.java junto con los recursos necesarios durante la inicialización en un archivo JAR y coloque ese archivo JAR en la variable class path del sistema. Los métodos de UDF pueden hacer referencia al modelo inicializado mediante la variable estática MySeparateClass.myVar. De este modo, el código de inicialización se ejecuta exactamente una vez, cuando el cargador de clases del sistema cargue la clase MySeparateClass.java.

Consejo:

La representación compilada de un módulo (el archivo .tam) contiene el código binario serializado de la UDF. Por lo tanto, si las sentencias create function hacen referencia a la misma UDF en dos módulos diferentes, el código UDF se serializa en la representación compilada de ambos módulos. Es decir, el código de la UDF se serializa dos veces. En estos casos, puede evitar la redundancia creando un módulo independiente que actúe como biblioteca de las UDF y reutilizando dicha biblioteca en otros módulos. Para crear una biblioteca de UDF, siga estos pasos:

  1. Cree un módulo.
  2. Coloque todos los archivos JAR de UDF dentro de ese módulo.
  3. Defina todas las funciones necesarias con sentencias create function.
  4. Expórtelas con sentencias export function para que se puedan importar y utilizar en otros módulos.

Ejemplos

Ejemplo 1: Implementación de una UDF escalar

En este ejemplo se muestra cómo implementar una UDF escalar llamada toUpperCase. Esta UDF toma como entrada un valor de tipo Span y genera un valor de serie que consiste en el contenido de texto de la entrada Span, convertido a mayúsculas.

package com.ibm.biginsights.textanalytics.udf;
import com.ibm.avatar.algebra.datamodel.Span;

/**
  * @param s input Span
  * @return all upper-case version of the text of the input Span
  */
public String toUpperCase(Span s) {
  return s.getText().toUpperCase();
}

Ejemplo 2: Implementación de una UDF escalar que utiliza una tabla como entrada

En este ejemplo se muestra cómo implementar una UDF escalar llamada TableConsumingScalarFunc. Esta UDF toma como entrada dos listas de tuplas y genera un valor de serie que concatena el contenido de las dos listas de tuplas de entrada.

import com.ibm.avatar.algebra.datamodel.TupleList;

/**
  * Example implementation of a user-defined scalar function using a table as input
*/
public class TableConsumingScalarFunc
{

  /**
    * Main entry point to the `scalar` function. This function takes two lists of tuples and concatenates them into a single string.
    *
    * @param arg1 first set of tuples to merge
    * @param arg2 second set of tuples to merge
    * @return the two sets of tuples, concatenated
    */
  public String eval (TupleList arg1, TupleList arg2)
  {
    StringBuilder sb = new StringBuilder ();

    sb.append("Input1: ");
    sb.append(arg1.toPrettyString ());
    sb.append("\nInput2: ");
    sb.append(arg2.toPrettyString ());

    return sb.toString ();
  }
}

Ejemplo 3: Implementación de una UDF de tabla que utiliza una tabla como entrada

En este ejemplo se muestra cómo implementar una UDF de tabla llamada TableConsumingTableFunc. Esta UDF toma como entrada dos listas de tuplas y genera una sola lista de tuplas que contiene tuplas de la primera entrada intercaladas con tuplas de la segunda entrada. Observe que la implementación se amplía desde la clase base com.ibm.avatar.api.udf.TableUDFBase, que proporciona las API para obtener los esquemas de entrada y de salida.

package com.ibm.test.udfs;

import java.lang.reflect.Method;

import com.ibm.avatar.algebra.datamodel.AbstractTupleSchema;
import com.ibm.avatar.algebra.datamodel.FieldCopier;
import com.ibm.avatar.algebra.datamodel.Tuple;
import com.ibm.avatar.algebra.datamodel.TupleList;
import com.ibm.avatar.algebra.datamodel.TupleSchema;
import com.ibm.avatar.api.exceptions.TableUDFException;
import com.ibm.avatar.api.udf.TableUDFBase;

/**
  * Example implementation of a user-defined table function
*/
public class TableConsumingTableFunc extends TableUDFBase
{

  /** Accessors for copying fields from input tuples to output tuples. */
  private FieldCopier arg1Copier, arg2Copier;

  /**
    * Main entry point to the `table` function. This function takes two lists of tuples and generates a new list of wide
    * tuples, where element i of the returned list is created by joining element i of the first input with element i of
    * the second input.
    *
    * @param arg1 first set of tuples to merge
    * @param arg2 second set of tuples to merge
    * @return the two sets of tuples, interleaved
    */
  public TupleList eval (TupleList arg1, TupleList arg2)
  {

    TupleSchema retSchema = getReturnTupleSchema ();
    TupleList ret = new TupleList (retSchema);

    // We skip any records that go off the end
    int numRecs = Math.min (arg1.size (), arg2.size ());

    for (int i = 0; i < numRecs; i++) {
      Tuple retTuple = retSchema.createTup ();

      Tuple inTup1 = arg1.getElemAtIndex (i);
      Tuple inTup2 = arg2.getElemAtIndex (i);

      arg1Copier.copyVals (inTup1, retTuple);
      arg2Copier.copyVals (inTup2, retTuple);

      // System.err.printf ("%s + %s = %s\n", inTup1, inTup2, retTuple);

      ret.add (retTuple);
    }

    return ret;
  }

  /**
    * Initialize the internal state of the `table` function. In this case, we create accessors to copy fields from input
    * tuples to output tuples.
    *
    * @see com.ibm.avatar.api.udf.TableUDFBase#initState() for detailed description
    */
  @Override
  public void initState () throws TableUDFException
  {
    // Create accessors to do the work of copying fields from input tuples to output tuples
    AbstractTupleSchema arg1Schema = getRuntimeArgSchema ().getFieldTypeByIx (0).getRecordSchema ();
    AbstractTupleSchema arg2Schema = getRuntimeArgSchema ().getFieldTypeByIx (1).getRecordSchema ();
    TupleSchema retSchema = getReturnTupleSchema ();

    // Create offsets tables for a straightforward copy.
    String[] srcs1 = new String[arg1Schema.size ()];
    String[] dests1 = new String[arg1Schema.size ()];
    String[] srcs2 = new String[arg2Schema.size ()];
    String[] dests2 = new String[arg2Schema.size ()];

    for (int i = 0; i < srcs1.length; i++) {
      srcs1[i] = arg1Schema.getFieldNameByIx (i);
      dests1[i] = retSchema.getFieldNameByIx (i);
    }
    for (int i = 0; i < srcs2.length; i++) {
      srcs2[i] = arg2Schema.getFieldNameByIx (i);
      dests2[i] = retSchema.getFieldNameByIx (i + srcs1.length);
    }

    arg1Copier = retSchema.fieldCopier (arg1Schema, srcs1, dests1);
    arg2Copier = retSchema.fieldCopier (arg2Schema, srcs2, dests2);
  }

  /**
    * Check the validity of tuple schemas given in the AQL “create function”.
    *
    * @see com.ibm.avatar.api.udf.TableUDFBase#validateSchema(TupleSchema, TupleSchema, TupleSchema, Method, Boolean) for
    *      description of arguments
    */
  @Override
  public void validateSchema (TupleSchema declaredInputSchema, TupleSchema runtimeInputSchema,
    TupleSchema returnSchema, Method methodInfo, boolean compileTime) throws TableUDFException
  {
    // The output schema should contain the columns of the two input schemas in order.
    AbstractTupleSchema arg1Schema = declaredInputSchema.getFieldTypeByIx (0).getRecordSchema ();
    AbstractTupleSchema arg2Schema = declaredInputSchema.getFieldTypeByIx (1).getRecordSchema ();

    System.err.printf ("TableConsumingTableFunc: Input schemas are %s and %s\n", arg1Schema, arg2Schema);

    // First check sizes
    if (returnSchema.size () != arg1Schema.size () + arg2Schema.size ()) { throw new TableUDFException (
      "Schema sizes don't match (%d + %d != %d)", arg1Schema.size (), arg2Schema.size (), returnSchema.size ()); }

    // Then check types
    for (int i = 0; i < arg1Schema.size (); i++) {
      if (false == (arg1Schema.getFieldTypeByIx (i).equals (returnSchema.getFieldTypeByIx (i)))) { throw new TableUDFException (
        "Field type %d of output doesn't match corresponding field of first input arg (%s != %s)", i,
        returnSchema.getFieldTypeByIx (i), arg1Schema.getFieldTypeByIx (i)); }
    }

    for (int i = 0; i < arg2Schema.size (); i++) {
      if (false == (arg2Schema.getFieldTypeByIx (i).equals (returnSchema.getFieldTypeByIx (i + arg1Schema.size ())))) { throw new TableUDFException (
        "Field type %d of output doesn't match corresponding field of first input arg (%s != %s)", i
          + arg1Schema.size (), returnSchema.getFieldTypeByIx (i + arg1Schema.size ()), arg2Schema.getFieldTypeByIx (i)); }
    }
  }

}

Declaración de funciones definidas por el usuario

Puede hacer que las funciones escalares definidas por el usuario y los modelos de aprendizaje automático procedentes de los archivos PMML estén disponibles en AQL mediante la sentencia create function.

Sintaxis

La sintaxis general de la sentencia create function es la siguiente:

create function <function-name>(<input-schema-definition>)
return <return-type> [like <column-name>] | table ( <output-schema-definition)
external_name <ext-name>
language [java | pmml]
[deterministic | not deterministic]
[return null on null input | called on null input];
<input-schema-definition>
<column-name> <data-type> | table (<output-schema-definition>) as locator [,<column-name> <data-type> | table (<output-schema-definition>) as locator ]*
<output-schema-definition>
<column-name> <data-type> [,<column-name> <data-type>]*

Descripción

  • <function-name\>

    El <function-name\> declara el nombre AQL de la UDF. En el código de AQL se hace referencia a la UDF con este nombre

  • <input-schema-definition\>

    Especifica los parámetros de entrada de la UDF. Un parámetro de entrada tiene un nombre, que se especifica como <column-name\>, y puede ser un tipo escalar o un localizador de tablas. Si el lenguaje es PMML, la función debe tomar una sola tabla denominada params como argumento.

  • <column-name\>

    Especifica el nombre de una columna en la entrada o en la salida de la UDF.

  • <data-type\>

    El tipo de un parámetro scalar de entrada a la UDF, el tipo de una columna en el esquema de una tabla de entrada a la UDF o en el esquema de la tabla de salida de la UDF. Los valores posibles para <data-type\> son Integer, Float, String, Text, Span, Boolean o ScalarList.

  • table (<output-schema-definition\>) as locator

    Este tipo de entrada permite que una función tome como entrada todo el contenido de una determinada vista de AQL como si se hubiera calculado en el documento actual. El parámetro locator hace referencia a las vistas y a las tablas como argumentos.

  • <return-type\>

    Para las UDF escalares, <return-type\> especifica el tipo del valor escalar que devuelve la UDF. Los valores posibles para el tipo de retorno son: Integer, Float, String, Text, Span, Boolean o ScalarList. Si el tipo de retorno es Integer, la función de Java™ que implementa la UDF devuelve objetos de tipo Integer. La implementación de la UDF no puede devolver el tipo int primitivo. Si el tipo de retorno es Text o Span, especifique el parámetro de entrada del que se deriva el tipo de retorno. Puede especificar el parámetro de entrada mediante la especificación like opcional, ya que los tramos siempre proceden de una columna subyacente. Si el tipo de retorno es ScalarList, especifique el parámetro de entrada del que se debe deducir el tipo escalar dentro de ScalarList. Si el lenguaje es PMML, la función debe devolver una tabla.

  • <output-schema-definition\>

    Para las UDF de tabla, <output-schema-definition\> especifica el esquema de salida de la tabla que devuelve la UDF, incluidos los nombres de columna y sus tipos.

  • <ext-name\>

    El valor external_name especifica dónde encontrar la implementación de la UDF. Cuando el lenguaje es Java, es una serie del formulario '<jar-file-name\>:<fully-qualified-class-name\>!<method-name\>', que consta de tres partes:

    • Nombre de archivo JAR: cuando compila AQL modular, las referencias de ubicación de los archivos JAR de UDF deben ser relativas a la raíz del módulo en el que se hace la referencia.
    • Nombre de clase: nombre completo de la clase que contiene la implementación de la UDF
    • Nombre de método: el método debe ser un método público de la clase. La signatura del método debe coincidir con los tipos de parámetros especificados en la sentencia create function. El componente de tiempo de ejecución realiza la conversión automática de tipo. Si el lenguaje es PMML, la cláusula external_name especifica una serie que es la ubicación del archivo PMML relativo al directorio raíz del módulo. La implementación actual da soporte a los modelos que se expresan mediante la versión de PMML estándar 4.1 y los evalúa utilizando la versión 1.0.22 de la biblioteca org.jpmml.
  • language

    La especificación language apunta al lenguaje de implementación de la UDF. El componente de tiempo de ejecución solo admite UDF implementadas en Java™.

  • deterministic/not deterministic

    El valor opcional deterministic/not deterministic especifica si se trata de una función sin estado. Una función determinista siempre devuelve el mismo valor para el mismo conjunto de valores de entrada.

  • return null on null input

    El valor opcional return null on null input especifica el comportamiento de la función cuando uno o varios de los valores de entrada son nulos. Si se especifica return null on null input, el sistema devuelve null en una entrada nula sin invocar la UDF. Si se especifica called on null input, se invoca la UDF incluso para valores de entrada nulos.

Notas sobre el uso de UDF implementadas en PMML

Las funciones que se crean a partir de archivos PMML toman una sola tabla que se denomina params como argumento y generan como resultado una tabla. La implementación de la función correlaciona los campos de entrada entre el esquema de entrada y el de salida declarados en la sentencia create function y el esquema especificado en el archivo PMML. Es decir, la sección DataDictionary que describe los nombres y los tipos de campos que pueden aparecer en los registros de entrada y de salida que el modelo genera y consume, la sección MiningSchema que indica los archivos con nombre definidos en la sección DataDictionary que están en cada tupla que representa un vector de característica y la sección Output que indica los campos con nombre definidos en la sección DataDictionary aparecen en la representación externa de la salida del modelo. Estas funciones deben ser funciones de tabla; cada fila de la tabla se pasa al modelo PMML y generará una fila de salida.

Esta información de esquema es necesaria porque los sistemas de tipo PMML y AQL no coinciden perfectamente. Por ejemplo, PMML tiene varios tipos para representar indicaciones de fecha y hora, mientras que actualmente AQL necesita que los usuarios codifiquen las indicaciones de fecha y hora como valores de serie. La información de esquema también permite a los desarrolladores que conocen AQL pero no PMML comprender el conjunto de reglas de AQL.

El compilador de AQL compara el esquema de entrada con el esquema de entrada del archivo PMML para asegurarse de que los dos esquemas son compatibles. Si los dos esquemas contienen campos con el mismo nombre pero tipos incompatibles, la compilación falla con un mensaje de error apropiado. Si los esquemas de entrada o de salida de la función contienen demasiadas columnas o si faltan columnas, la función resulting pasa por alto dichas columnas y no genera ningún error. El orden de los nombres de columna puede ser diferente entre la definición de AQL y el archivo PMML. Si un nombre de columna aparece en los esquemas de entrada y de salida pero no en el esquema PMML, los valores de dicha columna se pasan a la salida de la función.

Ejemplos

Ejemplo 1: Declaración de UDF escalares con valores escalares como entrada utilizando Java

En el ejemplo siguiente se muestra una sentencia create function que declara una función denominada udfCombineSpans. La función definida por el usuario toma dos tramos como entrada y devuelve un tramo fusionado parecido al primer tramo de entrada. La función Java™ de UDF real se empaqueta en un archivo JAR denominado udfs.jar, bajo el directorio udfjars. El método que implementa la función es combineSpans en la clase com.ibm.test.udfs.MiscScalarFunc. El método también declara una función udfSpanGreaterThan que devuelve true si el intervalo es mayor que el tamaño especificado.

/**
* A function to combine two spans and return the resultant span from beginOffset of first span, to endOffset of second span
* @param p1 first input span
* @param p2 second input span
* @return a span from beginOffset of p1 till endOffset of p2
*/

create function udfCombineSpans(p1 Span, p2 Span)
return Span like p1
external_name 'udfjars/udfs.jar:com.ibm.test.udfs.MiscScalarFunc!combineSpans'
language java
deterministic
return null on null input;

/**
* A function to compare an input Span's size against an input size
* @param span input span
* @param size input size to be compared against
* @return Boolean true if input span's size is greater than input argument size, else false
*/

create function udfSpanGreaterThan(span Span, size Integer)
return Boolean
external_name 'udfjars/udfs.jar:com.ibm.test.udfs.MiscScalarFunc!spanGreaterThan'
language java
deterministic;

En el ejemplo siguiente se muestra cómo declarar una función llamada udfCompareNames a la que se proporciona una lista de nombres nameList y un solo nombre myName. La salida es una lista parecida a la lista de entrada, que solo contiene las entradas de nameList parecidas a myName.

/**
* A function to compare an input string against a list of names
* and returns a list of entries from nameList similar to myName.
* @param nameList a list of names
* @param myName a name to compare against the list
* @return a list of entries from nameList similar to myName
*/

create function udfCompareNames(nameList ScalarList, myName String)
return ScalarList like nameList
external_name 'udfjars/udfs.jar:com.ibm.test.udfs.MiscScalarFunc!compareNames'
language java
deterministic;

Ejemplo 2: Declaración de UDF escalares con tablas como entrada utilizando Java

En el ejemplo siguiente se muestra el uso del tipo de entrada table as locator. Muestra una sentencia create function que declara una función llamada MyScalarFunc. La implementación Java™ de la UDF está empaquetada dentro de la clase com.ibm.test.udfs.TableConsumingScalarFunc.

Esta UDF toma como entrada dos listas de tuplas y genera un valor de serie que concatena el contenido de las dos listas de tuplas de entrada. La implementación de Java™ de la UDF se incluye en el apartado sobre Implementación de funciones definidas por el usuario.

-- Declare a simple scalar function that turns two tables into a big string
create function MyScalarFunc(
    firstArg table( spanVal Span ) as locator,
    secondArg table( spanVal Span, strVal Text ) as locator
)
return String
external_name
  'udfjars/udfs.jar:com.ibm.test.udfs.TableConsumingScalarFunc!eval'
language java
deterministic
called on null input;

Ejemplo 3: Declaración de UDF de tabla mediante Java

En el ejemplo siguiente se muestra el uso de la cláusula return table. El ejemplo muestra una sentencia create function que declara una función de tabla llamada MyScalarFunc. La implementación Java™ de la UDF está empaquetada dentro de la clase com.ibm.test.udfs.TableConsumingTableFunc. Esta UDF toma como entrada dos listas de tuplas y genera una lista de tuplas que fusiona las listas de entrada. La implementación de Java™ de la UDF se incluye en el apartado sobre Implementación de funciones definidas por el usuario.

-- Declare a simple table function that "zips together" two input tables
create function MyTableFunc(
    firstArg table( spanVal Span ) as locator,
    secondArg table( spanVal Span, strVal Text ) as locator
)
return table( outSpan1 Span, outSpan2 Span, outStr Text)
external_name
  'udfjars/udfs.jar:com.ibm.test.udfs.TableConsumingTableFunc!eval'
language java
deterministic
called on null input;

Ejemplo 4: Declaración de una UDF de tabla implementada en PMML

En el ejemplo siguiente se muestra una sentencia create function que declara una función denominada IrisDecisionTree mediante el lenguaje PMML. La implementación PMML de la UDF se especifica en el archivo IrisTree.xml, que se muestra en el siguiente ejemplo. El modelo que se almacena en IrisTree.xml es un modelo de árbol de decisiones.

-- Scoring function based on a decision tree model stored in IrisTree.xml
create function IrisDecisionTree(
    params table(
        sepal_length Float,
        sepal_width Float,
        petal_length Float,
        petal_width Float
    ) as locator
)
return table( class Text, actual_class Text,
    -- This PMML file also defines additional output fields
    "Probability_Iris-setosa" Float,
    "Probability_Iris-versicolor" Float,
    "Probability_Iris-virginica" Float)
external_name 'IrisTree.xml'
language pmml;

IrisTree.xml

<?xml version="1.0"?>
<PMML version="3.2" xmlns="http://www.dmg.org/PMML-3_2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.dmg.org/PMML-3_2 http://www.dmg.org/v3-2/pmml-3-2.xsd">
  <Header copyright="Copyright (c) 2012 DMG" description="RPart Decision Tree Model">
  <Extension name="user" value="DMG" extender="Rattle/PMML"/>
  <Application name="Rattle/PMML" version="1.2.29"/>
  <Timestamp>2012-09-27 12:46:08</Timestamp>
  </Header>
  <DataDictionary numberOfFields="5">
  <DataField name="class" optype="categorical" dataType="string">
    <Value value="Iris-setosa"/>
    <Value value="Iris-versicolor"/>
    <Value value="Iris-virginica"/>
  </DataField>
  <DataField name="sepal_length" optype="continuous" dataType="double">
    <Interval closure="closedClosed" leftMargin="4.3" rightMargin="7.9"/>
  </DataField>
  <DataField name="sepal_width" optype="continuous" dataType="double">
    <Interval closure="closedClosed" leftMargin="2" rightMargin="4.4"/>
  </DataField>
  <DataField name="petal_length" optype="continuous" dataType="double">
    <Interval closure="closedClosed" leftMargin="1" rightMargin="6.91"/>
  </DataField>
  <DataField name="petal_width" optype="continuous" dataType="double">
    <Interval closure="closedClosed" leftMargin="0.1" rightMargin="2.5"/>
  </DataField>
  </DataDictionary>
  <TreeModel modelName="RPart_Model" functionName="classification" algorithmName="rpart" splitCharacteristic="binarySplit" missingValueStrategy="defaultChild">
  <MiningSchema>
    <MiningField name="class" usageType="predicted"/>
    <MiningField name="sepal_length" usageType="supplementary"/>
    <MiningField name="sepal_width" usageType="supplementary"/>
    <MiningField name="petal_length" usageType="active"/>
    <MiningField name="petal_width" usageType="supplementary"/>
  </MiningSchema>
  <Output>
    <OutputField name="class" optype="categorical" dataType="string" feature="predictedValue"/>
    <OutputField name="Probability_Iris-setosa" optype="continuous" dataType="double" feature="probability" value="Iris-setosa"/>
    <OutputField name="Probability_Iris-versicolor" optype="continuous" dataType="double" feature="probability" value="Iris-versicolor"/>
    <OutputField name="Probability_Iris-virginica" optype="continuous" dataType="double" feature="probability" value="Iris-virginica"/>
  </Output>
  <Node id="1" score="Iris-virginica" recordCount="105" defaultChild="3">
    <True/>
    <ScoreDistribution value="Iris-setosa" recordCount="33" confidence="0.314285714285714"/>
    <ScoreDistribution value="Iris-versicolor" recordCount="35" confidence="0.333333333333333"/>
    <ScoreDistribution value="Iris-virginica" recordCount="37" confidence="0.352380952380952"/>
    <Node id="2" score="Iris-setosa" recordCount="33">
    <SimplePredicate field="petal_length" operator="lessThan" value="2.6"/>
    <ScoreDistribution value="Iris-setosa" recordCount="33" confidence="1"/>
    <ScoreDistribution value="Iris-versicolor" recordCount="0" confidence="0"/>
    <ScoreDistribution value="Iris-virginica" recordCount="0" confidence="0"/>
    </Node>
    <Node id="3" score="Iris-virginica" recordCount="72" defaultChild="7">
    <SimplePredicate field="petal_length" operator="greaterOrEqual" value="2.6"/>
    <ScoreDistribution value="Iris-setosa" recordCount="0" confidence="0"/>
    <ScoreDistribution value="Iris-versicolor" recordCount="35" confidence="0.486111111111111"/>
    <ScoreDistribution value="Iris-virginica" recordCount="37" confidence="0.513888888888889"/>
    <Node id="6" score="Iris-versicolor" recordCount="37">
      <SimplePredicate field="petal_length" operator="lessThan" value="4.85"/>
      <ScoreDistribution value="Iris-setosa" recordCount="0" confidence="0"/>
      <ScoreDistribution value="Iris-versicolor" recordCount="34" confidence="0.918918918918919"/>
      <ScoreDistribution value="Iris-virginica" recordCount="3" confidence="0.0810810810810811"/>
    </Node>
    <Node id="7" score="Iris-virginica" recordCount="35">
      <SimplePredicate field="petal_length" operator="greaterOrEqual" value="4.85"/>
      <ScoreDistribution value="Iris-setosa" recordCount="0" confidence="0"/>
      <ScoreDistribution value="Iris-versicolor" recordCount="1" confidence="0.0285714285714286"/>
      <ScoreDistribution value="Iris-virginica" recordCount="34" confidence="0.971428571428571"/>
    </Node>
    </Node>
  </Node>
  </TreeModel>
</PMML>

Documentación de la sentencia create function con comentarios

El comentario de AQL Doc para una sentencia create function contiene la información siguiente:

  • Una descripción general sobre la función.
  • La descripción de @param que especifica cada nombre de parámetro utilizado en la función. Indica el tipo de parámetro (si es un tipo escalar o una tabla). Si el parámetro es una tabla, describe el esquema de la tabla, incluidos los nombres y tipos de columna en el orden en el que aparecen en el esquema de la tabla que se espera como entrada.
  • La descripción @return especifica la información que devuelve la función. Si la función devuelve una tabla, especifique el esquema de salida de la tabla, incluidos los nombres y tipos de columna en el orden en el que aparecen en el esquema de la tabla de salida.
/**
* A function to compare an input string against a list of names
* and returns a list of entries from nameList similar to myName.
* @param nameList a list of names
* @param myName a name to compare against the list
* @return a list of entries from nameList similar to myName
*/

create function udfCompareNames(nameList ScalarList, myName String)
  return ScalarList like nameList
  external_name 'udfjars/udfs.jar:com.ibm.test.udfs.MiscScalarFunc!compareNames'
  language java
  deterministic;

Utilización de funciones definidas por el usuario

Las funciones definidas por el usuario funcionan con las sentencias y las cláusulas de AQL.

Las funciones escalares definidas por el usuario funcionan con las sentencias y cláusulas de AQL, de forma similar a las funciones incorporadas. En concreto, las UDF escalares se pueden utilizar en las cláusulas select, where, having, group by y order by de la misma forma que las funciones escalares incorporadas, como GetBegin y LeftContext. Las funciones escalares definidas por el usuario que devuelven un tipo booleano se pueden utilizar como predicados en cláusulas where y having.

Las funciones de tabla definidas por el usuario (UDF de tabla) se pueden utilizar dentro de la cláusula from de una sentencia select o de una sentencia extract.

Ejemplos

Ejemplo 1: Utilización de UDF escalares implementadas en Java con valores escalares como entrada

En este ejemplo se muestra cómo utilizar las funciones udfCombineSpans y udfSpanGreaterThan declaradas en Declaración de funciones definidas por el usuario.

create function udfCombineSpans(p1 Span, p2 Span)
return Span like p1
external_name 'udfjars/udfs.jar:com.ibm.test.udfs.MiscScalarFunc!combineSpans'
language java
deterministic
return null on null input;

create function udfSpanGreaterThan(span Span, size Integer)
return Boolean
external_name 'udfjars/udfs.jar:com.ibm.test.udfs.MiscScalarFunc!spanGreaterThan'
language java
deterministic;

-- identify occurrences of given names in the document
create dictionary FirstNamesDict from file 'firstNames.dict';

create view FirstName as
extract dictionary 'FirstNamesDict' on D.text as name
from Document D;

-- Use a UDF to merge the name that is longer than 7 characters with the text to its right in a
-- way that is appropriate to the application.
create view NameAndContext as
select udfCombineSpans(F.name, RightContext(F.name, 50)) as name
from FirstName F
where udfSpanGreaterThan(F.name, 7);

Ejemplo 2: Utilización de UDF escalares implementadas en Java con tablas como entrada

En el ejemplo siguiente se muestra cómo utilizar una función escalar que utiliza tablas como entrada. En este ejemplo se muestra el uso de la función de la UDF de tabla MyScalarFunc, cuya implementación Java™ se incluye en el apartado sobre Implementación de funciones definidas por el usuario. Tienen los mismos tipos de columna, pero distintos nombres de columna.

-- Declare a simple scalar function that turns two tables into a big string
create function MyScalarFunc(
    firstArg table( spanVal Span ) as locator,
    secondArg table( spanVal Span, strVal Text ) as locator
)
return String
external_name
  'udfjars/udfs.jar:com.ibm.test.udfs.TableConsumingScalarFunc!eval'
language java
deterministic
called on null input;

-- Create two views to serve as inputs to the `table` function.
-- Note that column names don't match, but types do.
create view FirstInputView as
extract regex /\d+/ on 1 token in D.text as match
from Document D;

create view SecondInputView as
select S.match as spanCol, 'Dummy string' as textCol
from
    (extract regex /[A-Z][a-z]+/ on 1 token in D.text as match
    from Document D) S;

-- Call the `scalar` function defined above from the select list.
create view ScalarFuncOutput as
select MyScalarFunc(FirstInputView, SecondInputView) as func
from Document D;

Ejemplo 3: Utilización de UDF de tabla implementadas en Java

En este ejemplo se muestra el uso de la función de la UDF de tabla MyTableFunc, cuya implementación Java™ se incluye en el apartado sobre Implementación de funciones definidas por el usuario.

-- Declare a simple table function that "zips together" two input tables
create function MyTableFunc(
    firstArg table( spanVal Span ) as locator,
    secondArg table( spanVal Span, strVal Text ) as locator
)
return table( outSpan1 Span, outSpan2 Span, outStr Text)
external_name
  'udfjars/udfs.jar:com.ibm.test.udfs.TableConsumingTableFunc!eval'
language java
deterministic
called on null input;

-- Create two views to serve as inputs to the `table` function.
-- Note that column names don't match, but types do.
create view FirstInputView as
extract regex /\d+/ on 1 token in D.text as match
from Document D;


create view SecondInputView as
select S.match as spanCol, 'Dummy string' as textCol
from
    (extract regex /[A-Z][a-z]+/ on 1 token in D.text as match
    from Document D) S;

-- Use the `table` function
create view TabFuncOutput as
select T.outSpan1 as span1, T.outSpan2 as span2
from MyTableFunc(FirstInputView, SecondInputView) T;

Al igual que en Ejemplo 2, en este ejemplo se definen dos vistas: FirstInputView con el esquema (match Span) y SecondInputView con el esquema (spanCol Span, textCol Text). La última vista del ejemplo, TabFuncOutput, invoca la función table MyTableFunc en la cláusula from, con las dos vistas de entrada. Tal como se explica en el Ejemplo 2, una vista es compatible con un argumento de localizador de tablas de una función, siempre que el número de columnas y los tipos de columna del esquema de la vista de entrada y del localizador de tablas coincidan. Sin embargo, no es necesario que los nombres de columna coincidan.

Por último, la cláusula select descarta la columna outStr de la tabla de salida de MyTableFunc, manteniendo solo las dos primeras columnas, outSpan1 y outSpan2.

Ejemplo 4: Utilización de una UDF de tabla implementada en PMML

En este ejemplo se muestra el uso de la función de UDF de la tabla IrisDecisionTree declarada en el ejemplo 4 del apartado Declaración de funciones definidas por el usuario.

-- External view to hold the input records
create external view IrisData(
    sepal_length Float,
    sepal_width Float,
    petal_length Float,
    petal_width Float
)
external_name 'IrisData';
--Invoke the function on the input data records
create view IrisDecisionTreeOutput as
select * from IrisDecisionTree(IrisData);

output view IrisDecisionTreeOutput;