Referência de Annotation Query Language

A Anotation Query Language (AQL) é a linguagem principal usada para criar extratores de regras avançadas do IBM Watson® Knowledge Studio.

  • Modelo de dados: o modelo de dados para AQL é semelhante ao modelo relacional padrão usado por um banco de dados SQL, como o DB2®. Todos os dados em AQL são armazenados em tuplas, registros de dados de uma ou mais colunas, ou campos. Uma coleção de tuplas forma uma visualização. Todas as tuplas em uma visualização devem ter o mesmo esquema que são os nomes e os tipos dos campos em todas as tuplas.
  • Modelo de execução: o componente de tempo de execução tem um modelo de execução de um documento por vez. O componente de tempo de execução recebe uma coleção de documentos e executa o extrator em cada documento para extrair informações desse documento.
  • Instruções AQL: ao usar instruções AQL, é possível criar e, em seguida, usar módulos, visualizações, tabelas, dicionários e funções.
  • Funções integradas: a AQL tem uma coleção de funções integradas para uso em regras de extração.
  • A instrução create function: para executar operações em valores extraídos não suportados pela AQL, é possível definir funções customizadas para usar em regras de extração chamadas funções definidas pelo usuário (UDFs).

Sintaxe da Annotation Query Language (AQL)

Como muitas linguagens de programação, a AQL é baseada em sintaxe comum e gramática.

A estrutura lexical de uma linguagem de programação é o conjunto de regras elementares que definem os tokens ou componentes básicos dessa linguagem, como suas palavras reservadas, identificadores, constantes e muito mais.

A sintaxe da AQL é semelhante à da SQL, mas existem várias diferenças importantes:

  • A AQL faz distinção entre maiúsculas e minúsculas.

  • A AQL não suporta atualmente recursos avançados de SQL, como subconsultas correlacionadas e consultas recursivas.

  • A AQL tem um novo tipo de instrução, extract, que não está presente em SQL.

  • A AQL não permite palavras-chave (palavras reservadas), como nomes de visualização, de coluna ou de função.

  • A AQL permite, mas não requer, que as expressões regulares sejam expressas na sintaxe Perl. As expressões regulares começam com uma barra (/) e terminam com uma barra (/), como na sintaxe de Perl. A AQL também permite expressões regulares que começam com aspas simples (') e terminam com aspas simples ('). Por exemplo, é possível usar /regex/ em vez de 'regex' como a expressão regular em AQL.

  • Identificadores: são usados para definir os nomes de objetos AQL, incluindo nomes de módulos, visualizações, tabelas, dicionários, funções, atributos e parâmetros de função.

  • Palavras reservadas: são palavras que têm um significado fixo no contexto da estrutura AQL e não podem ser redefinidas. Palavras-chave são palavras reservadas que têm significados especiais dentro da sintaxe do idioma.

  • Constantes: são valores fixos que podem ser um destes tipos de dados: sequência, número inteiro, valor flutuante ou booleano.

  • Comentários: use comentários para aumentar o código AQL com descrições básicas para ajudar que outros entendam o código e para gerar módulos compilados autoexplicativos.

  • Expressões: uma expressão AQL é uma combinação de um ou mais valores e funções escalares que são avaliados para um único valor escalar.

Identificadores

Identificadores são usados para definir os nomes de objetos da AQL, incluindo nomes de módulos, visualizações, tabelas, dicionários, funções, atributos e parâmetros de função.

Existem dois tipos de identificadores AQL que fazem distinção entre maiúsculas e minúsculas:

  • Identificador simples

    Um identificador simples deve começar com uma letra minúscula (a-z) ou maiúscula (A-Z) ou com o caractere sublinhado (_). Os caracteres seguintes podem ser letras minúsculas ou maiúsculas, o caractere sublinhado ou dígitos (0-9). Um identificador simples deve ser diferente de qualquer palavra chave em AQL.

  • Identificador com aspas duplas

    Um identificador entre aspas duplas começa e termina com um caractere de aspas duplas ("). É possível usar qualquer caractere entre os caracteres de aspas duplas iniciais e finais. Os identificadores com aspas duplas não podem conter um caractere de ponto (.). Se um caractere de aspas duplas ocorrer dentro do nome, ele deverá ser escapado, prefixando-o com o caractere de barra invertida (\), por exemplo, \”.

Palavras reservadas

Palavras reservadas são palavras que têm um significado fixo dentro do contexto da estrutura AQL e não podem ser redefinidas. Palavras-chave são palavras reservadas que têm significados especiais dentro da sintaxe do idioma.

As palavras-chave reservadas de AQL a seguir não podem ser usadas como identificadores porque cada uma tem um propósito bem definido dentro da linguagem:

  • 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

As seguintes palavras reservadas são os nomes de tipos escalares embutidos:

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

Os outros nomes reservados a seguir não podem ser usados como identificadores:

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

Constantes

Constantes são valores fixos que podem ser um destes tipos de dados: String, Integer, Floatou Boolean.

As constantes são usadas na lista de seleção de uma cláusula select ou extract ou como argumentos em funções UDF ou integradas e predicados. A AQL suporta os tipos de constantes a seguir:

  • Constante de sequência

    Uma sequência colocada entre aspas simples ('), por exemplo, 'uma sequência'.

  • Constante inteira

    Um valor de número inteiro assinado de 32 bits que não é delimitado por aspas, por exemplo, 10 ou -1.

  • Constante flutuante

    Um valor de vírgula flutuante de 32 bits de precisão única, não delimitado por aspas, por exemplo 3,14 ou -1,2.

  • Constante booleana

    O valor true ou false não delimitado por aspas.

  • Constante nula

    O valor nulo que não é delimitado por aspas.

Comentários

Use comentários para aumentar o código AQL com descrições básicas para ajudar os outros a entenderem o código e a gerar módulos compilados autoexplicativos.

Os comentários permitem que os desenvolvedores de AQL aumentem o código AQL com descrições básicas, para facilitar o entendimento do código-fonte AQL, e eles geram os módulos AQL compilados autoexplicativos. Três tipos de comentários são suportados na AQL:

  • Comentários de linha única

    Os comentários de linha única começam com hifens duplos (--).

  • Comentários de múltiplas linhas

    Os comentários de várias linhas começam com uma barra e um asterisco (/*) e terminam com um asterisco e uma barra (*). Os comentários de várias linhas não podem ser aninhados. Por exemplo, o comentário de múltiplas linhas aninhadas a seguir não é permitido:

    /*
    A comment with a /*nested comment*/
    */
    
  • Comentários de AQL Doc

    Os comentários de AQL Doc fornecem uma maneira de descrever um módulo ou um objeto AQL em linguagem simples e de uma maneira rica em aspecto para compreensão contextual por outros usuários. Ao contrário dos comentários de linha única e dos comentários com diversas linhas, que são ignorados pelo Compilador AQL, os comentários de AQL Doc são serializados nos metadados de módulos compilados (arquivos .tam) e disponibilizados para consumo externo.

    Todos os comentários em AQL Doc para instruções e módulos têm o formato a seguir:

    • O comentário está em texto sem formatação (nenhuma tag HTML é suportada).

    • O comentário começa com uma barra seguida de dois asteriscos (/**) e termina com uma barra e um asterisco (*/). Opcionalmente, cada linha pode começar com um asterisco (*).

    • Qualquer número de espaços em branco pode ser usado antes do asterisco.

    • As tags especiais prefixadas por um símbolo de arroba (@) podem ser usadas no início de cada linha ou depois do asterisco opcional.

    • Os comentários de AQL Doc não podem ser aninhados. Dois níveis de granularidade são suportados no sistema AQL Doc. O formato para documentar cada artefato é explicado em detalhes no tópico que descreve sua instrução e sintaxe.

    • Comentários de nível de módulo

      Os comentários de nível de módulo estão contidos em um arquivo especial denominado module.info e localizado diretamente na pasta do módulo. Espera-se que os comentários descrevam a semântica do módulo e o esquema da visualização Document do módulo.

    • Comentários de nível de instrução

      Os comentários de nível de instrução estão contidos no arquivo AQL de origem, precedendo imediatamente a instrução que cria um objeto AQL. Os comentários de linha única e comentários de múltiplas linhas são permitidos entre o comentário de AQL Doc de uma instrução e a instrução em si.

      As instruções AQL de nível superior a seguir podem ser documentadas usando comentários de AQL Doc:

      • A instrução create external view
      • A instrução create external table
      • A instrução create external dictionary
      • A função create
      • A instrução detag
      • A instrução select... into Os comentários de AQL Doc são serializados dentro da representação compilada de um módulo.

Expressões

Uma expressão AQL é uma combinação de um ou mais valores e funções escalares que são avaliados para um único valor escalar.

As expressões podem ser de um dos quatro tipos:

  • uma constante
  • uma referência de coluna
  • uma chamada de função escalar
  • uma chamada de função agregada

Constante

Uma expressão pode ser uma constante do tipo Integer, Float ou String, como no exemplo a seguir:

select 'positive' as polarity

A expressão é a constante de sequência positive.

Referência de coluna

Uma expressão pode ser uma referência de coluna, como no exemplo a seguir:

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);

Essa visualização identifica texto que pode ser interpretado como o nome completo de uma pessoa (por exemplo, "Samuel Davis", "Vicky Rosenberg"). As expressões F.name e L.name são expressões de referência de coluna que retornam a coluna de nome das visualizações F e L, respectivamente. A instrução from define as visualizações F e L como os nomes locais para as visualizações FirstName e LastName (que definem nomes e sobrenomes válidos e não são mostrados nesse exemplo).

Chamada de função escalar

Uma expressão pode ser composta por uma ou mais chamadas de função escalar, cada uma podendo conter argumentos que também são expressões do tipo constante, referência de coluna ou chamada de função escalar. Uma chamada de função escalar pode ser uma das funções escalares integradas ou uma função escalar definida pelo usuário. Considere o exemplo a seguir:

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);

Essa visualização identifica os potenciais membros da família agrupando pessoas com os mesmos sobrenomes, imprimindo todos os nomes, com os sobrenomes em caracteres minúsculos (por exemplo, sobrenome keaton, nomes (Elyse, Alex, Diane)). As saídas das chamadas de função GetText são usadas como argumentos para a chamada de função ToLowerCase para exibir os nomes em minúsculas. As expressões de chamada de função scalar neste exemplo são: ToLowerCase, (GetText(P.lastname), ToLowerCase(GetText(P.firstname)) e GetText(P.lastname).

Chamada de função agregada

Uma expressão pode ser uma chamada de função agregada. Esse tipo de expressão pode ter como argumentos outra expressão do tipo referência de coluna ou do tipo chamada de função escalar. O exemplo a seguir mostra uma chamada de função agregada com a expressão do tipo referência de coluna:

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

A expressão é simplesmente Count(Person.lastname) e conta o número de anotações Person.lastname no documento. Um exemplo de chamada de função agregada com expressão do tipo chamada de função escalar existe no exemplo anterior como List(GetText(P.firstname)) com a função agregada List usando uma função escalar GetText como um argumento para gerar uma lista de nomes. As expressões de chamada de função agregada são permitidas somente como expressões na lista select de uma instrução select. As expressões de chamada de função agregada não são permitidas na lista select de uma instrução extract ou como argumentos para uma chamada de função escalar ou agregada.

Modelo de dados

O modelo de dados para AQL é semelhante ao modelo relacional padrão que é usado por um banco de dados SQL, como o DB2®. Todos os dados em AQL são armazenados em tuplas, registros de dados de uma ou mais colunas, ou campos. Uma coleção de tuplas forma uma visualização. Todas as tuplas em uma visualização devem ter o mesmo esquema que são os nomes e os tipos dos campos em todas as tuplas.

O conteúdo do documento de entrada é representado como uma visualização especial chamada Documento.

Os campos de uma tupla devem pertencer a um dos tipos de dados embutidos da AQL:

  • Booleano

    Um tipo de dados que tem um valor true ou false.

  • Valor flutuante

    Um número de vírgula flutuante de precisão única.

  • Número inteiro

    Um número inteiro assinado de 32 bits.

  • ScalarList

    Uma coleção de valores do mesmo tipo escalar (Número inteiro, Valor flutuante, Texto ou Período). Um valor de tipo de dados ScalarList pode ser obtido como resultado da função agregada integrada AQL List() ou como o resultado de uma UDF.

  • Intervalo

    Um Período é uma região contígua de um objeto de Texto, identificado por seus deslocamentos de início e de término no objeto de Texto. Suponha que seu texto de entrada seja:

    Amelia Earhart is a pilot.
    

    O texto no Span [0-6] é Amelia.

    Esse Span pode ser visualizado como:

    0A1m2e3l4i5a6
    

    Da mesma forma, o texto no Span[20-25] é pilot.

    Um Período de [x-x] representa o período entre o término de um caractere e o início do caractere seguinte. No exemplo anterior, [0-0] é uma sequência vazia antes do caractere A. Da mesma forma, um intervalo de [3-3] é uma sequência de caracteres vazia entre os caracteres e e l.

    Um valor do tipo Período pode ser obtido como resultado de uma instrução extract, de uma função escalar integrada ou de uma UDF.

  • Texto

    O tipo de dados AQL para representar uma sequência de caracteres. Um objeto de texto contém uma string Unicode, chamada de seu valor string. Quando uma sequência é formada como a concatenação de subsequências desconectadas de outro objeto de Texto, ela também contém referência ao objeto de Texto original e informações relevantes de mapeamento de deslocamento. Dois objetos Text serão considerados iguais entre si se todos os seus componentes forem correspondentemente iguais entre si.

  • Comparando valores do tipo Período e Texto Os fatores de priorização afetam as comparações entre valores dos tipos Período e Texto.

Comparando valores de tipo Span e Texto

Os fatores de priorização afetam as comparações entre os valores do tipo Span e o tipo Text.

Os valores do tipo Span e do tipo Text se comparam uns com os outros nestas maneiras:

  • Um valor de span nulo é sempre classificado mais baixo do que outros valores.
  • Um valor de texto é sempre classificado mais alto que um valor de span.
  • Os valores do tipo Text serão classificados primeiro pela ordem lexical de seus valores de sequência, em seguida, por suas ordens originais de Text e pelas informações de mapeamento de deslocamento, se aplicáveis.
  • Os valores do tipo Span são classificados primeiro por seus objetos de texto subjacentes, em seguida, por seu deslocamento inicial e, em seguida, por seu deslocamento final. O span com um deslocamento inicial menor é classificado mais baixo. Entre dois spans que iniciam no mesmo deslocamento, aquele com o menor deslocamento de extremidade inferior.

Modelo de execução

O componente de tempo de execução tem um modelo de execução de um documento por vez. O componente de tempo de execução recebe uma coleção de documentos e executa o extrator em cada documento para extrair informações desse documento.

Um extrator consiste em um ou mais módulos AQL para criar uma coleção de visualizações em que cada uma delas define uma relação. Algumas dessas visualizações são designadas como visualizações de saída, enquanto outras são visualizações não de saída. As visualizações não de saída podem incluir algumas visualizações que são importadas para um módulo ou exportadas dele. É importante notar que visualizações de saída e visualizações exportadas são ortogonais. Por exemplo, uma visualização que é exportada não se qualifica como uma visualização que é gerada. Além dessas visualizações, a visualização Document exclusiva representa o documento de entrada que é anotado por esse extrator.

Document view

No nível do módulo AQL, a visualização Document é uma visualização especial que representa o documento atual que está sendo anotado por esse módulo. Quando dois ou mais módulos são combinados para formar um extrator, a união sem duplicata de esquemas de Document de todos os módulos é a visualização Document necessária. Use a instrução require document with columns para especificar o esquema da visualização Document. Se essa instrução estiver ausente em um módulo, o esquema padrão assumido para a visualização Document será (text Text, label Text):

  • texto

    O conteúdo textual do documento atual.

  • rótulo

    O rótulo do documento atual que está sendo anotado.

A palavra-chave Document é reservada como um identificador para a visualização Document, que é preenchida automaticamente durante a execução. Portanto, não é possível definir outra visualização ou tabela com o mesmo nome. No entanto, é possível usar a palavra Document como um identificador para nomes de atributos e aliases.

Instruções de AQL

Ao usar instruções AQL, é possível criar e, em seguida, usar módulos, visualizações, tabelas, dicionários e funções.

As instruções a seguir são suportadas em AQL:

  • Instruções para criar módulos e declarar a interação entre eles

    A instrução module

    A instrução export

    A instrução import

  • Instruções para criação de objetos AQL: visualizações, dicionários, tabelas ou funções

    As instruções create dictionary e create external dictionary

    A instrução create table

    A instrução create view

    A instrução create external view

    A instrução detag

    A instrução extract

    A instrução select

    A instrução require document with columns

    A instrução set default dictionary language

    A instrução de criação de função

As especificações de sintaxe nas instruções AQL contêm colchetes ([ ]). Essas especificações indicam que os colchetes e as construções que eles contêm são opcionais quando a sintaxe correspondente é usada para escrever uma instrução. Além disso, elas representam itens temporários para definir como especificar instâncias adicionais de uma construção ou um argumento.

A instrução module

Use a instrução module para criar um módulo que tenha os recursos necessários autocontidos. É possível exportar e importar esses recursos como objetos AQL para/de outros módulos.

Sintaxe

module <module-name\>;

Descrição

  • <module-name\>

    Declara que o arquivo atual faz parte do módulo denominado <module-name\>. O nome do módulo deve ser um identificador simples. Os identificadores entre aspas dupla não são permitidos como nomes de módulo.

    Cada arquivo AQL dentro do módulo deve ter exatamente uma declaração de módulo, e esta declaração deve ser a primeira instrução em cada arquivo. Essa declaração estabelece um namespace idêntico ao module-name. Todas as visualizações (e outros objetos, como dicionários, tabelas e funções) declaradas em arquivos AQL dentro desse módulo estão localizadas nesse único namespace. Eles são acessíveis a todos os arquivos AQL neste espaço de nomes.

    Todos os arquivos declarados como parte do módulo <module-name\> devem estar em uma pasta chamada <module-name\> para fazer a aplicação deste namespace. Não existe nenhuma ordenação dos arquivos AQL dentro dessa pasta do módulo. O compilador de AQL examina todos os arquivos AQL do módulo e determina a ordem correta para compilar todas as visualizações, dicionários, tabelas e funções declaradas no módulo.

Observações de uso

  • Quando o arquivo AQL subjacente não é localizado como parte de um módulo (AQL modular) e é compilado no modo de compatibilidade, essa instrução não é suportada.
  • As dependências circulares entre as visualizações não são permitidas.
  • Os módulos AQL não suportam submódulos.
  • Os arquivos AQL dentro de subpastas da pasta do módulo de nível superior são ignorados.

Exemplos

Exemplo 1: módulo de amostra

No exemplo a seguir, a visualização TheMentions pertence ao módulo que é denominado sample.

module sample;

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

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

A instrução export

A instrução export em AQL é usada para exportar um objeto AQL do módulo atual para que ele possa ser importado e usado em outros módulos.

Sintaxe

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

Descrição

  • view|dictionary|table|function

    Define o tipo de objeto a ser exportado. O tipo de objeto pode ser uma visualização, um dicionário, uma tabela ou uma função.

  • <object-name\>

    Define o nome do objeto a ser exportado. O <object-name\> pode ser um identificador simples ou um identificador entre aspas duplas.

Observações de uso

  • Não é possível exportar nenhum dos objetos AQL importados. É possível criar o efeito de reexportar a visualização ou tabela no módulo atual criando uma nova visualização:

    select * from <imported_view_name_or_table_name>;
    
  • As instruções export view e output view que são mostradas nos exemplos são ortogonais entre si. Ou seja, uma visualização de saída não é automaticamente uma visualização exportada, mas ela deve ser exportada explicitamente usando uma instrução export. Uma visualização exportada não é automaticamente uma visualização de saída, mas ela deve ser explicitamente saída usando a instrução output view . Nos exemplos, a instrução export tenta exportar a visualização PersonName.FirstName, que é uma visualização importada. Essa tentativa causa um erro, o que significa que o desenvolvedor deve copiar a visualização importada para uma nova visualização e, em seguida, exportá-la.

Exemplos

Exemplo 1: criando visualizações e dicionários e, em seguida, exportando-os para uso em outros módulos

Este exemplo cria as visualizações FirstName e NotFirstName. A visualização FirstName coleta informações sobre os nomes representados no dicionário FirstNamesDictionary. A outra visualização coleta os nomes que permanecem ao excluir os nomes. Dois dicionários são necessários para tornar a extração de texto mais fácil. Um dicionário contém todos os nomes que você deseja procurar. O segundo dicionário, LastNamesDictionary, contém os sobrenomes a serem procurados. O dicionário FirstNamesDictionary é exportado para que possa ser usado em outros módulos. As visualizações FirstName e NotFirstName também são exportadas para que possam ser importadas e usadas em outros módulos, como a pessoa do módulo no Exemplo 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;

Exemplo 2: importando visualizações a serem usadas, mas exportando de forma inadequada, causando um erro

Este exemplo mostra a importação de duas visualizações. Essas visualizações foram exportadas do módulo personName no Exemplo 1. A pessoa do módulo agora pode importar e fazer referência a essas visualizações. No entanto, esse módulo tenta exportar a mesma visualização que ele importou, FirstName, o que causa um erro.

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;

A razão para o erro neste código é que uma visualização que é importada de um módulo não pode ser exportada no módulo atual. Além disso, as visualizações exportadas não são automaticamente visualizações de saída, a menos que você tenha definido uma visualização de saída com a instrução output view.

A instrução import

É possível usar a instrução import para referenciar objetos que são exportados de outros módulos no contexto do módulo atual.

Sintaxe

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

Descrição

  • view\|dictionary\|table\|function

    Identifica o tipo de objeto AQL a ser importado. O tipo do objeto é obrigatório.

  • <object-name\>

    O <object-name\> pode ser um identificador simples ou um identificador entre aspas duplas.

  • <module-name\>

    O <module-name\> deve ser um identificador simples.

  • <alias\>

    Esta forma da instrução de importação, também conhecida como alias import, importa o objeto AQL especificado com o nome <alias\> (não o nome original) no namespace do módulo atual. É possível referenciar o elemento importado usando um alias não qualificado ou um alias qualificado com o nome do módulo atual (o módulo no qual o objeto AQL foi importado). Não é possível usar originalModule.elementName porque a instrução alias import importa o elemento somente sob o nome de alias e não sob o nome original qualificado.

Observações de uso

  • Uma instrução de importação sem uma especificação de alias importa o objeto AQL especificado para o módulo atual. Ela torna o objeto AQL acessível às instruções AQL definidas no módulo atual com o nome qualificado <original\_module\_name\>.<object-name\>.

  • A instrução de importação é usada somente para importar objetos AQL de módulos diferentes do módulo atual. Um objeto que é declarado em um arquivo AQL do módulo é visível para qualquer outro arquivo AQL nesse mesmo módulo. Uma instrução de importação coloca objetos no contexto do módulo atual, e não no contexto do arquivo atual. Portanto, uma visualização que é importada por 1.aql dentro do módulo A torna-se visível para 2.aql dentro do mesmo módulo sem a necessidade de quaisquer instruções adicionais de importação.

  • Todas as instruções de importação devem seguir imediatamente após a declaração do módulo e devem preceder todos os outros tipos de instruções. Somente os objetos AQL que são exportados explicitamente de qualquer módulo podem ser importados em outro módulo. Se este requisito não for observado, resultará um erro de compilação.

  • Um erro de compilação é introduzido quando uma instrução import view introduz um conflito de nomenclatura com qualquer instrução create view ou outras instruções de importação do mesmo módulo (não apenas do arquivo atual). Essa restrição se aplica ao import de outros objetos além de visualizações.

  • O compilador de AQL adere às convenções de nomenclatura que são usadas em versões anteriores da AQL:

    • Um módulo não pode conter uma visualização e uma tabela com o mesmo nome.
    • Um dicionário com o mesmo nome de uma tabela ou visualização é permitido.
    • Uma função com o mesmo nome de uma tabela, visualização ou dicionário é permitida.
  • Um erro de compilação é introduzido quando diferentes instruções de importação dentro de um ou múltiplos arquivos AQL no módulo dão o mesmo nome a diferentes objetos AQL.

  • Um erro de compilação é introduzido quando um arquivo AQL dentro de um módulo tenta fazer referência a outra visualização exportada de um módulo sem usar a instrução import view. O mesmo se aplica a dicionários, tabelas ou funções.

  • Quando dois arquivos AQL dentro de um módulo importam a mesma visualização X de outro módulo sob dois aliases diferentes, por exemplo, A e B, os dois aliases são tratados de forma sinônima. Essa regra se aplica também a tabelas, dicionários e funções.

Exemplos

Exemplo 1: criar visualizações que você exporta para serem importadas para outros módulos.

Este exemplo cria duas visualizações, FirstName e NotFirstName. A visualização FirstName coleta informações sobre os nomes representados no dicionário FirstNamesDictionary. A segunda visualização coleta os nomes que ficam quando os nomes são excluídos. Dois dicionários são necessários para tornar a extração de texto mais fácil. Um dicionário contém todos os nomes que você deseja procurar. O segundo dicionário, LastNamesDictionary, contém os sobrenomes a serem procurados. As visualizações FirstName e NotFirstName são exportadas para que possam ser importadas e usadas em outros módulos, como o módulo person nos Exemplos 2 e 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;

Exemplo 2: importando a visualização FirstName usando a importação de alias

Este exemplo importa uma das visualizações criadas e exportadas no Exemplo 1. Em seguida, a visualização PersonFirstName é gerada para que seus resultados possam ser exibidos.

A instrução de importação de amostra é conhecida como uma importação de alias. Ela importa a visualização FirstName, sem qualificador de módulo, para o namespace do módulo atual, person. A visualização importada pode ser acessada somente por meio do nome de alias PersonFirstName e não por meio de qualquer outro formulário. Por exemplo, não é possível consultar a visualização importada como personName.FirstName porque ela é importada somente por meio do nome de alias.

module person;

`import view FirstName from module personName as PersonFirstName;`

output view PersonFirstName;

Exemplo 3: importando a visualização NotFirstname sem usar a importação de alias

Esta instrução de importação de amostra importa o nome qualificado personName.NotFirstName (não o nome não qualificado da visualização) para o namespace do módulo atual, person. Consulte sempre a visualização importada usando somente o nome qualificado. Qualquer outro modo de referência é sinalizado como erro do compilador.

module person;

`import view NotFirstName from module personName;`


output view personName.NotFirstName;

A instrução import module

É possível usar a instrução import module para importar e reutilizar os módulos AQL existentes.

Sintaxe

 import module <module-name\>;

Descrição

  • <module-name\>

    Especifica o módulo a ser importado. O <module-name\> deve ser um identificador simples.

Observações de uso

  • A instrução de importação é usada somente para importar objetos AQL de outros módulos, não do módulo atual.

  • Todas as instruções de importação devem seguir imediatamente após a declaração do módulo e devem preceder todos os outros tipos de instruções. Somente os objetos AQL que são exportados explicitamente de qualquer módulo podem ser importados em outro módulo. Se este requisito não for observado, resultará um erro de compilação.

  • Um erro de compilação é introduzido quando uma instrução import view introduz um conflito de nomenclatura com qualquer instrução create view ou outra instrução de importação do mesmo módulo (não apenas do arquivo atual). Esta restrição se aplica à import de outros objetos AQL, além de visualizações.

  • Um erro de compilação é introduzido quando um arquivo AQL dentro de um módulo tenta fazer referência a outra visualização exportada de um módulo sem usar a instrução import view. O mesmo se aplica a dicionários, tabelas ou funções.

  • Se dois arquivos AQL dentro de um módulo importarem a mesma visualização X de outro módulo sob dois aliases diferentes, por exemplo, A e B, os dois aliases serão tratados de forma sinônima. Essa regra se aplica também a tabelas, dicionários e funções.

Exemplos

Neste exemplo, a instrução import importa o nome qualificado de ambas as visualizações exportadas, personName.FirstName e personName.NotFirstName. Qualquer visualização que não seja exportada pelo módulo personName não será importada como parte da instrução de importação

  • Exemplo 1: importar ambas as visualizações FirstName e NotFirstName

    Este exemplo mostra todas as visualizações exportadas do módulo personName. As visualizações FirstName e NotFirstName foram criadas na seção de exemplo da instrução de exportação.

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

A instrução set default dictionary language

A instrução set default dictionary language permite que um desenvolvedor de extractor customize o conjunto padrão de idiomas de correspondência de dicionário para o módulo de contenção.

Sintaxe

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

Descrição

  • <language codes\>

    Especifica o idioma para compilação e a correspondência para dicionários do módulo que são declaradas sem uma especificação with language as explícita. O conjunto <language codes\> deve ser uma lista separada por vírgulas, sem espaços em branco, ao redor de cada código de idioma. A falha na observação desse requisito pode resultar em um erro de compilação.

    Essa instrução afeta os dicionários a seguir:

    • Os dicionários que são explicitamente declarados no módulo atual usando a instrução create dictionary ou create external dictionary e essa instrução não tem uma cláusula with language as.
    • Os dicionários de arquivos externos.
    • Em uma especificação de padrão de uma instrução extract pattern, átomos do tipo 'string' e do tipo <'string' [match parameters]> sem uma especificação explícita with language as. Quando esta instrução está ausente de um módulo, o componente de tempo de execução assume como padrão um conjunto de idiomas de alemão, espanhol, inglês, francês, italiano e o idioma não especificado x. Ele é definido como um conjunto: [de,es,en,fr,it,x_unspecified]. Em um módulo, apenas uma instância dessa instrução pode existir.

Observações de uso

  • A instrução set default dictionary language pode ser atualizada para melhorar a extensão de idiomas que são cobertos pelo extrator. Essa capacidade de incluir idiomas promove a facilidade de customização e a reutilização de extratores existentes.

Exemplos

Exemplo 1: especificando idiomas a serem usados para corresponder entradas de dicionário

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;

A instrução require document with columns

Usando a instrução require document with columns, é possível definir o esquema da visualização especial Document no tempo de compilação. Essa definição de esquema especifica a lista de campos obrigatórios e seus tipos a serem localizados em cada tupla da visualização Document.

Sintaxe

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

Descrição

  • <columnName\>

    Especifica o nome da coluna a ser usada no esquema. O <columnName\> é um identificador de atributo, que é um identificador simples ou um identificador entre aspas duplas.

  • <columnType\>

    Especifica o tipo de coluna a ser usado no esquema da visualização Document. O <columnType\> pode ser um dos tipos de dados a seguir: Número inteiro, Valor flutuante, Booleano ou Texto.

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

    Especifica nomes e tipos de colunas adicionais para o esquema da visualização Document. São seguidas as mesmas regras de <columnName\> e <columnType\>.

Em versões anteriores da AQL, o esquema da visualização especial Document era predefinido para consistir em um único campo (text Text) ou em dois campos (text text, label Text). A escolha entre esses esquemas foi decidida em tempo de execução. Usando a instrução require document with columns, é possível substituir o esquema de documento de entrada padrão no tempo de compilação.

Observações de uso

  • Para o código AQL modular, o escopo de qualquer instrução require document with columns é o módulo no qual ela está definida.
  • Somente uma instrução require document with columns é permitida por arquivo AQL. Dentro de um único módulo ou um módulo genérico, pode haver zero, um ou múltiplos arquivos AQL que tenham uma instrução require document with columns. Todos os arquivos AQL dentro de um módulo mesclam suas instruções require document with columns no nível do módulo inteiro para formar um require document with columns em todo o módulo. Essa instrução define o esquema da visualização Document para esse módulo. Se nenhum dos arquivos AQL de um módulo ou um módulo genérico conter uma instrução necessária, o módulo possui um esquema padrão para a visualização Document. Esse esquema consiste em duas colunas: (text Text, label Text). Nenhuma coluna padrão será estabelecida para a visualização especial Document se pelo menos um arquivo AQL no módulo tiver uma instrução require document with columns.
  • Quando múltiplos módulos são combinados para formar um extrator, o esquema da visualização Document do extrator inteiro é definido pela união sem duplicata de esquemas de Document para cada módulo. Uma exceção é emitida quando qualquer coluna localizada entre as diversas instruções require document with columns é localizada como conflitante em seus requisitos de tipo entre os módulos. Por exemplo, um módulo requer uma coluna X com o tipo Y quando outro módulo que está sendo carregado com ele requer uma coluna X com o tipo Z.
  • Uma exceção será emitida ao executar um extrator se a tupla de documento de entrada fornecida não contiver todas as colunas necessárias. Uma exceção também será emitida se uma coluna não se adequar ao seu tipo necessário correspondente.
  • Quando a instrução require document with columns está presente dentro de um módulo, cada coluna da visualização especial Document que é referenciada deve ser declarada em pelo menos uma das instruções require document with columns. A instrução pode ser localizada em diferentes arquivos AQL dentro do mesmo módulo. No entanto, todas as instruções require document with columns seriam mescladas no nível do módulo para formar uma instrução require document with columns em todo o módulo.

Exemplos

Exemplo 1: instrução require document com tipos de colunas semelhantes

O exemplo a seguir define um esquema de documento que contém quatro campos do mesmo tipo. Essa amostra AQL espera que cada tupla de documento da coleção de dados contenha quatro colunas, conforme definido no esquema do documento.

Consulte os formatos de documentos JSON para obter detalhes sobre como criar um documento que se adequa a um 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;

Exemplo 2: instrução require document com tipos de colunas variados

A amostra a seguir define um esquema de documento que contém colunas de tipos de campo variados.

module sample;

-- Require document statement with varying field types

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

Exemplo 3: mesclando esquemas de documento

O exemplo descreve como mesclar esquemas de documento que usam os arquivos first.aql, last.aql e 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;

O esquema mesclado é (firstName Text, lastName Text, socialSecurityNo Integer).

A instrução create view

Os componentes de nível superior de um extrator AQL são suas visualizações. As visualizações são instruções lógicas que definem, mas não necessariamente computam, um conjunto de tuplas.

Sintaxe

A instrução create view pode tomar uma das três formas. A forma mais simples define uma visualização lógica que é composta pelas tuplas de uma única instrução select ou extract. A segunda é um formato de várias junções que define uma visualização que abrange as tuplas que surgem da união de multiconjuntos de várias instruções select ou extract. A terceira forma define uma nova visualização que contém a diferença de conjunto entre as tuplas de duas instruções select ou 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\>);

Descrição

  • <viewname\>

    O <viewname\> pode ser um identificador simples ou um identificador entre aspas duplas. Ele não pode conter o caractere de ponto.

  • <select or extract statement\>

    A instrução select ou extract cria saída que é usada para computar as tuplas da visualização contendo.

Observações de uso

  • Os nomes da visualização fazem distinção entre maiúsculas e minúsculas. Por exemplo, Person, PERSON e person são nomes de visualização diferentes
  • Duas visualizações dentro do mesmo módulo AQL não podem compartilhar um nome, o que as tornaria duplicadas. No entanto, duas visualizações com o mesmo nome podem existir em dois módulos diferentes, uma vez que seus nomes completos são exclusivos.
  • Por padrão, uma visualização que é definida pela instrução create view é uma visualização não de saída até que ela seja especificada como uma visualização de saída.
  • As instruções select ou extract das formas union all e minus devem ter um esquema de saída compatível. Dois esquemas serão considerados compatíveis para uma operação union ou minus se tiverem o mesmo número de colunas, os nomes de colunas estiverem na mesma ordem e eles tiverem tipos de dados compatíveis:
    • Os campos do mesmo tipo de dados são compatíveis com union ou minus.
    • Os Tipos de Dados de span e Texto são union ou minus compatíveis. No caso de uma união entre um tipo Span e um Text, o tipo de saída é um Span. No entanto, os objetos do tipo Text não são convertidos automaticamente em um tipo Span; a conversão automática acontece somente quando necessário por chamadas de função.
    • Dois ScalarLists são compatíveis com union ou minus, independentemente do tipo escalar subjacente.

Exemplos

Exemplo 1: criando uma visualização com uma instrução select ou extract

No exemplo abaixo, a visualização Phone usa uma instrução extract para preparar suas tuplas. A visualização PhoneNumber usa uma instrução select para escolher campos específicos por meio da visualização 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;

Exemplo 2: criando uma visualização com a instrução Union All

A visualização AllPhoneNums prepara um conjunto sindicalizado das tuplas das visualizações Phone e Extension. As duas visualizações que estão sendo sindicalizadas têm o mesmo 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);

Exemplo 3: criando uma visualização com a instrução Minus

O exemplo a seguir mostra como é possível usar minus para filtrar tuplas indesejadas de um conjunto de tuplas.

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

Exemplo 4: compatibilidade de esquema para minus

É importante observar que os spans sobre um texto de destino diferente não são do mesmo tipo. Considere o exemplo de AQL a seguir que explica essa diferença usando uma literal de 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);

Em vez da saída esperada de uma lista de tuplas vazia, a saída é um conjunto de registros que têm 'uma sequência' como um valor de campo.

Embora os conteúdos das visualizações OneString e TheSameString pareçam idênticos, os valores de texto reais têm diferentes objetos AQL subjacentes. O tipo de OneString.match é 'Span sobre OneString.match'. O tipo de TheSameString.match é 'Span sobre TheSameString.match'. Uma vez que os tipos de campo são diferentes, eles não são compatíveis para propósitos de comparação.

Para obter a saída desejada da lista de tuplas vazias, deve-se comparar valores do mesmo tipo. No exemplo a seguir, a função GetString() converte objetos de período em objetos de sequência de caracteres para transmitir tipos compatíveis para a operação minus.

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

Documentando a instrução create view com o AQL Doc

O comentário do AQL Doc para uma instrução create view contém as seguintes informações:

  • Descrição geral sobre a visualização.
  • @field para cada nome de coluna na visualização.

Exemplo

/**
* 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;

A instrução output view

A instrução output view define uma visualização para ser uma visualização de saída. O componente de tempo de execução gera somente as tuplas de visualizações que são marcadas como visualizações de saída. O compilador de AQL compila somente visualizações que são marcadas como saída ou exportação ou atingíveis por meio de visualizações que são marcadas como saída ou exportação.

Sintaxe

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

Descrição

  • <view-name\>

    O nome da visualização a ser gerada, como conhecido no namespace do módulo atual. O <view-name\> é um identificador simples ou um identificador entre aspas duplas. A visualização integrada Document não pode ser gerada.

  • [as '<alias\>']*

    Define um nome <alias\> para a visualização de saída. Quando o alias opcional não é especificado, a visualização é gerada sob os nomes a seguir:

    • Na AQL modular, a visualização é emitida com o nome <module-name\>.<view-name\>, em que <module-name\> é o nome do módulo no qual a visualização é originalmente definida (que pode ser diferente do módulo no qual ela é gerada).
    • Na AQL 1.4 ou anterior, a visualização é gerada com o nome <view-name\> A instrução output ... as <alias\> é útil quando você personaliza um extrator para diferentes domínios. O uso do nome <alias\> ao definir uma visualização de saída garante que os nomes de saída sejam idênticos em diferentes implementações da customização.

    O nome <alias\> não pode ser usado em outra instrução select ou export. É necessário que <alias\> esteja entre aspas simples e o nome <alias\> pode conter períodos.

Observações de uso

  • Quando um extrator AQL é executado, ele computa tuplas resultantes para cada visualização que é definida como uma visualização de saída. As tuplas de qualquer visualização não de saída também são computadas, mas somente quando elas são necessárias para computar as tuplas resultantes de uma visualização de saída.
  • Em AQL modular, a instrução output view gera as tuplas da visualização sob o nome completo da visualização que é qualificado por seu nome do módulo. Considere o exemplo a seguir em que a instrução output view Person; resulta na saída da visualização personModule.Person:
module personModule;

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

output view Person;

Esse comportamento se aplica para qualquer saída de visualização sem um alias, independentemente de a visualização ser gerada no módulo no qual ela é definida ou em um módulo no qual ela é importada, mesmo quando a importação é de alias. Por exemplo, na visualização de saída MyPerson, esse exemplo resulta na visualização sendo gerada com seu nome qualificado original personModule.Person e não com seu alias local MyPerson

module employeeModule;

import view Person from module personModule as MyPerson;

output view MyPerson;
  • A instrução de alias de saída é útil quando se constrói bibliotecas de extratores nas quais o mesmo tipo de entidade pode ter muitas implementações diferentes, dependendo do domínio de aplicativo ou do idioma dos documentos de entrada. O principal benefício do uso de um alias quando você define uma visualização de saída é assegurar uma nomenclatura consistente entre as visualizações de saída. Uma nomenclatura consistente é esperada pela lógica do programa de um usuário quando você processa múltiplos módulos em que cada um deles gera uma visualização semanticamente semelhante. No AQL modular, quando um nome de alias é usado em uma instrução output view , as tuplas de uma visualização são saída sob o nome de alias especificado. Por exemplo, o código a seguir geraria os resultados sob o nome de alias PersonAlias e o nome de alias não é qualificado com o prefixo do módulo.
module personModule;

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

output view Person as 'PersonAlias';

Exemplos

Os exemplos a seguir contêm dois módulos, personModuleFrench e personModuleEnglish. Cada módulo gera uma visualização, nomeadas PersonNameFrench e PersonNameEnglish. Suponha que módulos semelhantes, cada um dos quais gere visualizações que sejam variantes semânticas de um extrator para nomes de pessoa. Esses módulos são customizados para idiomas diferentes com a variação na customização dessa visualização para um idioma de entrada especificado. Portanto, um usuário pode querer que um programa use módulos nos quais a visualização de saída buscada seja denominada PersonName, independentemente dos módulos processados. Essa expectativa é normal, uma vez que se espera que cada módulo customizado para um idioma, domínio ou outro propósito produza vários resultados. O consumidor desses módulos não precisa alterar o algoritmo de seu programa para acomodar nomes de visualização de saída variados quando a semântica subjacente é semelhante.

No exemplo, como o alias PersonName é usado, o consumidor não precisa alterar o nome da visualização que é buscado. No entanto, os resultados podem variar dependendo dos módulos que são processados. No exemplo, as correspondências resultantes baseiam-se no francês (Exemplo 1) e no inglês (Exemplo 2).

Exemplo 1: as correspondências de resultado são baseadas em francês

O exemplo a seguir define uma visualização PersonNameFrench e gera-a sob um nome de alias neutro de implementação, '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';

Exemplo 2: as correspondências de resultado são baseadas em inglês

O exemplo a seguir define uma visualização PersonNameEnglish e gera-a sob um nome de alias neutro de implementação, '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';

O consumidor dos módulos de exemplo pode acessar as tuplas de saída por meio do nome de alias 'PersonName'. O consumidor não precisaria saber o módulo real por meio do qual os resultados são buscados.

A instrução extract

A instrução extract é usada para extrair recursos básicos diretamente do texto.

Sintaxe

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>];

Descrição

  • <select list\>

    Uma lista delimitada por vírgula de expressões de saída. Os resultados dessas expressões de saída são retornados como a saída da instrução extract, com as tuplas geradas pela avaliação da especificação de extração. O formato de <select list\> é o mesmo que do <select list\> de uma instrução select.

  • <extraction specification\>

    Aplica a especificação de extração em todas as tuplas das visualizações definidas no <from list\>. Renomeia as colunas de tuplas de acordo com seus aliases correspondentes que são especificados na instrução extract. Você pode utilizar uma das seguintes especificações de extração:

    • Expressões regulares
    • Dicionários
    • Divisões
    • Bloqueios
    • Parte do discurso
    • Padrões de sequência
  • <from list\>

    Uma lista delimitada por vírgula que é a origem das tuplas por meio das quais os recursos devem ser selecionados. O formato de <from list\> é semelhante ao formato do <from list\> da instrução select. No entanto, se a instrução extract não tiver uma especificação padrão, <from list\> poderá conter um único item.

  • [having <having clause\>]

    Especifica um predicado de filtragem (no <having clause\>) que é aplicado a cada tupla de saída extraída. Os nomes de campo que são especificados no <having clause\> referem-se a quaisquer aliases que sejam especificados no <select list\>. Essa cláusula é opcional.

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

    Define como manipular intervalos de sobreposição conforme definido na consolidação <policy\>. Nesta especificação, <column\> deve ser o nome de um campo de saída que faz parte da instrução extract. Essa cláusula é opcional.

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

    Limita o número de tuplas de saída de cada documento para o máximo especificado. Essa cláusula é opcional.

Observações de uso

A semântica da instrução extract é a seguinte:

  • Avalie a especificação de extração sobre cada tupla da relação de entrada. Para cada resultado que a extração produz, é produzida uma tupla de saída que contém os valores extraídos, além de quaisquer colunas da tupla original especificadas em <select list\>.
  • Renomeie as colunas da tupla de saída de acordo com os aliases especificados como parte de <select list\> e de <extraction specification\>.
  • Aplique qualquer predicados na cláusula having opcional para a tupla de saída resultante.
  • Consolide as tuplas que passam os predicados de acordo com a cláusula consolidation opcional e inclua as tuplas resultantes na saída.
  • Se a cláusula limit opcional estiver presente, limite a saída para o número especificado de tuplas para cada documento.

A semântica da cláusula from de uma instrução extract pattern é diferente de outras formas de instruções extract que não têm uma especificação de padrão. Se pelo menos uma das visualizações em <from list\> não contém nenhuma tupla em um determinado documento, a saída da instrução extract está vazia. Essa saída está vazia porque o conjunto de todas as combinações de tuplas nas visualizações de entrada está vazio.

No caso especial de instruções extract pattern, a cláusula from é um item temporário que declara os nomes de relações que estão envolvidas na especificação de padrão. A semântica da instrução é acionada apenas pela especificação do padrão. Em particular, a saída da instrução pode ser não vazia mesmo quando algumas das visualizações de entrada estiverem vazias.

Exemplos

Exemplo 1: Extraindo números de telefone a partir de uma visualização pré-definida

Esta instrução extract de amostra avalia uma expressão regular para números de telefone dos Estados Unidos em todo o texto de entrada que é representado pela visualização predefinida Document. Em seguida, a saída é restrita aos três primeiros números de telefone que são identificados por documento. Os nomes de campo na cláusula having referem-se aos aliases no início da instrução 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;

Exemplo 2: extraindo blocos de palavras alteradas para letras maiúsculas

Neste exemplo, a instrução extract identifica blocos de duas a três palavras alteradas para letras maiúsculas. Em AQL, um bloco refere-se a um span contíguo de tokens, neste caso, de dois a três tokens. Este exemplo também usa uma política de consolidação para excluir blocos que estão contidos dentro de blocos maiores do conjunto de saída de tuplas.

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';

A cláusula consolidate é aplicada ao campo capswords pela especificação de blocos de extração. A diferença é que o campo de destino referido pela cláusula consolidation é um campo de saída da instrução extract. O campo de destino da instrução select é um campo de entrada. Esse comportamento é semelhante ao da cláusula having.

Exemplo 3: uma instrução extract ou select aninhado como um nome de visualização

A visualização de entrada para uma instrução extract pode ser um nome de visualização, como no Exemplo 2, ou uma instrução extract ou select aninhada, como neste exemplo:

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;

Exemplo 4: extrair uma instrução com uma lista de seleção

Neste exemplo, extraímos correspondências para um padrão e, ao mesmo tempo, selecionamos múltiplos atributos por meio das visualizações 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;
  • Expressões regulares Use uma especificação de extração de expressão regular para identificar os padrões de correspondência contidos pela expressão regular no texto de entrada.
  • Dicionários Use a especificação de extração de dicionário para extrair sequências do texto de entrada contidas em um dicionário de sequências.
  • Divisões Use a especificação de extração de divisão para dividir um período grande em vários períodos menores.
  • Blocos Use a especificação de extração de blocos para identificar blocos de períodos contíguos no texto de entrada.
  • Parte do discurso Use a especificação de extração de parte do discurso para identificar locais de diferentes partes do discurso no texto de entrada.
  • Padrões de sequência Use a especificação de extração de padrões para executar a correspondência de padrões em um documento de entrada e em outros períodos extraídos do documento de entrada.

Expressões regulares

Use uma especificação de extração de expressão regular para identificar padrões de correspondência que estão contidos pela expressão regular em todo o texto de entrada.

Sintaxe

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

Descrição

  • regex[es] /<regex1\>/

    Especifica as expressões regulares a serem usadas na extração. Por padrão, a AQL usa a sintaxe de Perl para as expressões regulares, o que significa que os literais de expressão regular são colocados em dois caracteres de barra (//). As sequências de escape de expressão regular têm precedência sobre outros caracteres de escape. A AQL permite expressões regulares na sintaxe de sequência SQL, portanto, uma expressão regular para os números de telefone dos Estados Unidos pode ser expressa como qualquer um dos exemplos:

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

    Lista mais expressões regulares para serem usadas na extração.

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

    Especifica uma combinação de sinalizações para controlar a correspondência de expressão regular. Este parâmetro é opcional. Essas sinalizações correspondem a um subconjunto das sinalizações que são definidas na implementação Java™. Se a cadeia de bandeiras não for fornecida, a AQL usa apenas a bandeira DOTALL por padrão.

    Para especificar múltiplas sinalizações, separe-as com o caractere |. Por exemplo, para especificar a correspondência de multilinhas, a correspondência sem distinção entre maiúsculas e minúsculas e a conversão em letras maiúsculas Unicode, use a sequência de sinalizações 'MULTILINE|CASE_INSENSITIVE|UNICODE'.

  • [<token spec\>]

    Indica se corresponde à expressão regular somente nos limites de token.

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

    As restrições de token são uma parte opcional da especificação. Se as restrições de token forem omitidas, a AQL retornará a correspondência sem sobreposição mais longa em cada posição do caractere no texto de entrada. Se as restrições de token estiverem presentes, a instrução extract retornará a correspondência mais longa em cada limite de token que estiver dentro do intervalo especificado de tokens em comprimento. Cada correspondência retornada deve iniciar no começo de um token e terminar no final de um token. Se várias correspondências de sobreposição existirem, a instrução extract retornará todas elas.

    Os locais de limites de token dependem de qual tokenizer o componente de tempo de execução está usando para converter em token o documento. Se o motor estiver usando o tokenizer Standard, então um token é definido como uma sequência de caracteres de palavras ou um único caractere de pontuação.

    Por exemplo, considere a sequência:

    "The fish are pretty," said the boy.
    

    Os limites de token são identificados nestes locais:

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

    O nome da visualização e o nome da coluna na qual a expressão regular é aplicada.

  • <grouping spec\>

    Determina como manipular a captura de grupos na expressão regular. Os grupos de captura são regiões da correspondência de expressão regular que são identificadas por parênteses na expressão original. Por exemplo, a expressão (fish)(cakes) tem três grupos de captura:

    • O grupo 0 é a correspondência inteira fishcakes.
    • O grupo 1 é fish.
    • O grupo 2 é cakes. Quando você especifica os IDs do grupo na cláusula de retorno da sintaxe, cada ID do grupo deve corresponder a um grupo válido dentro de cada expressão regular especificada como parte da cláusula extract regex na sintaxe.

    Este é o formato da especificação de agrupamento:

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

    Para retornar somente o Grupo 0 (a correspondência inteira), é possível usar um formato alternativo mais curto, como no Exemplo 1. Este formato é equivalente a return group 0 as <name>. O <name> pode ser um identificador simples ou um identificador entre aspas duplas.

Observações de uso

  • Em geral, a AQL suporta os mesmos recursos que a implementação de expressão regular Java 5, conforme descrito em [Padrão de classe: java.util.regex. O componente de tempo de execução contém várias implementações do mecanismo de expressão regular, incluindo a implementação integrada de Java. Durante a compilação, o Optimizer examina cada expressão regular e escolhe o mecanismo mais rápido que pode executar a expressão.

  • Os mecanismos alternativos de execução podem ter uma semântica um pouco diferente para determinados casos extremos. Em particular, a AQL não garante a ordem em que as alternativas são avaliadas.

    Por exemplo, suponha que uma instrução extract corresponda à expressão regular /fish|fisherman/ sobre o texto 'fisherman'. A instrução pode corresponder a 'fish' ou 'fisherman', dependendo de qual mecanismo de expressão regular é usado internamente.

Sequência de sinalização AQL Sinalização Java Descrição
CANON_EQ CANON_EQ Equivalência canônica: diferentes codificações Unicode de um mesmo caractere são consideradas equivalentes.
CASE_INSENSITIVE CASE_INSENSITIVE Execute uma correspondência sem distinção entre maiúsculas e minúsculas. Por padrão, a correspondência sem distinção entre maiúsculas e minúsculas supõe que somente caracteres no conjunto de caracteres US-ASCII são correspondidos. Correspondência de maiúsculas e minúsculas-a correspondência insensitiva pode ser ativada especificando a sinalização UNICODE com esta sinalização.
UNICODE UNICODE_CASE Caso a correspondência insensitiva case-insensitive seja especificada, use dobragem de caso Unicode para determinar se dois caracteres são equivalentes em uma comparação de caso-insensitivo de uma maneira consistente com o Padrão Unicode. Por padrão, a correspondência sem distinção entre maiúsculas e minúsculas supõe que somente caracteres no conjunto de caracteres US-ASCII são correspondidos. Nota: o comportamento dessa sinalização não é definido quando usado sem a sinalização CASE_INSENSITIVE.
DOTALL DOTALL Faça com que o caractere de ponto . corresponda a todos os caracteres, incluindo novas linhas.
LITERAL LITERAL Trate a expressão como uma sequência de caracteres literais, ignorando as sequências de escape normais de expressão normal.
MULTILINHAS MULTILINHAS Faça os caracteres ^ e $ correspondarem ao início e ao término de qualquer linha, em oposição ao início e ao término do texto inteiro de entrada.
UNIX_LINES UNIX_LINES Trate somente o caractere de nova linha do UNIX™ como uma quebra de linha, ignorando o caractere de retorno de linha \r.
  • Siga estas diretrizes para fazer com que seus extratores sejam executados mais rapidamente e sejam mais fáceis de manter:
    • Evite expressões regulares longas e complexas e use expressões regulares mais simples e menores que são combinadas com instruções AQL.
    • Evite o uso desnecessário de lookahead e lookbehind em expressões regulares. Geralmente, é possível alcançar o mesmo efeito incluindo predicados na cláusula having de sua instrução extract.
    • Use restrições de token em suas especificações de extração de expressão regular quando possível.

Exemplos

Exemplo 1: usando a equivalência canônica de Unicode para determinar correspondências

Este exemplo mostra como localizar palavras alteradas para letras maiúsculas que não são nomes fornecidos. A equivalência canônica de caractere Unicode é usada para determinar correspondências. Observe o uso da sinalização ‘CANON_EQ’ e que o regex é executado em tokens:

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));

Exemplo 2: uso de grupos de captura

O exemplo a seguir demonstra o uso de grupos de captura em uma instrução extract regex. O código extrai os campos de um número de telefone dos Estados Unidos usando 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;

Exemplo 3: aplicando múltiplos regex sobre o texto de entrada

É possível especificar diversas expressões regulares na mesma instrução extract regex usando a sintaxe 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;

Exemplo 4: uso indevido de especificação de agrupamento

A expressão regular nesta amostra de código não contém group -1 ou group 3000. Isso resulta em um erro de compilação.

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

Dicionários

Use a especificação de extração de dicionário para extrair sequências de texto de entrada que estão contidas em um dicionário de sequências.

Sintaxe

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

Descrição

  • '<dictionary\>'

    Referencie um dicionário que é criado usando a instrução create dictionary, a instrução create external dictionary ou um arquivo de dicionário no sistema de arquivos.

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

    Referencia dicionários adicionais para serem usados para extração.

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

    Controla correspondência de dicionário. Atualmente, duas opções são suportadas:

    • Exato

      Fornece correspondência exata com distinção entre maiúsculas e minúsculas.

    • IgnoreCase

      Fornece correspondência sem distinção entre maiúsculas e minúsculas.

Se nenhuma sinalização for especificada, a correspondência do dicionário se baseará em qualquer sinalização especificada durante sua criação. Se nenhuma sinalização for especificada durante a criação, ela corresponderá usando a sinalização IgnoreCase.

Observações de uso

  • Os dicionários são sempre avaliados em limites de token. Especificamente, uma entrada de dicionário corresponderá a uma região de texto se o primeiro token da entrada corresponder ao primeiro token da região de texto, o segundo token da entrada corresponder ao segundo token da região de texto e assim por diante. Os caracteres entre dois tokens consecutivos são ignorados.

    Por exemplo, suponha que você esteja usando um modelo de tokenização simples baseado em espaço em branco que seja apropriado para um idioma como o inglês. Além disso, suponha que o texto de entrada seja “Let’s go fishing!” Se um dicionário consistir no termo go fish, nenhuma correspondência existirá no texto para Let's go fishing!. No entanto, se o dicionário consistir na entrada go fishing (observe os dois espaços em branco entre go e fishing), existirá uma correspondência no texto Let's go fishing!. O espaço em branco especifica que go e fishing são dois tokens distintos. Se existir um ou mais caracteres de espaço em branco entre os dois tokens go e fishing no texto de entrada, uma correspondência será feita.

    Para cada correspondência de uma entrada de dicionário com texto de entrada, a instrução extract dictionary gera uma tupla de saída.

Exemplos

Exemplo 1: Extraindo termos de arquivos de dicionário

Localize nomes de pessoas usando arquivos de dicionário de nomes e sobrenomes comuns com correspondência que faça distinção entre maiúsculas e 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 seguir está o conteúdo de amostra de last.dict:

#Dictionary for surnames
Anthony
Aparicio
Cate
Lehmann
Radcliff

A seguir está o conteúdo de amostra de first.dict:

#Dictionary for given names
Aaron
Candra
Freeman
Mathew
Matthew
Zoraida

Nota:

  • Um sistema de arquivos de dicionário que é diretamente referenciado em uma instrução extract dictionary não pode ser configurado explicitamente com um conjunto de idiomas para que os dicionários sejam compilados e aplicados no tempo de execução. Em vez disso, o conjunto de idiomas será especificado com a instrução set default dictionary language se o módulo contiver essa instrução.

    Portanto, a referência direta de arquivos de dicionário em uma instrução extract dictionary não é recomendada e pode ser descontinuada no futuro. A prática preferencial é definir explicitamente um objeto de dicionário usando a instrução create dictionary from file e, em seguida, usar esse dicionário na instrução extract.

  • O compilador e o componente de tempo de execução tentam localizar arquivos de dicionário que são referenciados em AQLs sob o caminho de procura configurado.

Exemplo 2: extraindo termos de um dicionário sequencial

Localize conjunções usando um dicionário sequencial e a correspondência padrão sem distinção entre maiúsculas e 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;

Divisões

Use a especificação de extração dividida para dividir um span grande em vários spans menores.

Sintaxe

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

Descrição

A especificação de extração de divisão usa dois argumentos:

  • Uma coluna que contém abrangos de destino mais longos de texto.
  • Uma coluna que contém pontos de divisão.

O algoritmo de divisão funciona em duas passagens sobre a visualização de entrada. A primeira passagem agrupa todas as tuplas de entrada pela coluna de destino. A segunda passagem passa pelas tuplas em cada grupo, dividindo a coluna de destino com cada valor da coluna de divisão.

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

    Especifica os pontos de divisão para a extração.

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

    Especifica como tratar os terminais esquerdo e direito de cada resultado. Esse argumento é opcional.

    • Se retain left split point for especificado, cada span de saída também conterá o ponto de divisão à sua esquerda, se tal ponto de divisão existir.
    • Se retain right split point for especificado, o sistema fará com que cada span de saída contenha o ponto de divisão à sua direita.
    • A extração de divisão também aceita valores nulos como pontos de divisão. Para cada valor, a extração retorna uma tupla que contém o span de entrada inteiro.
  • <name\>.<column to split\>

    Especifica a coluna de destino para a extração.

  • <output name\>

    Define o nome da saída da extração.

Exemplos

Exemplo 1: Pontos de Split e a cláusula retain

Se os pontos de divisão forem todas as instâncias da palavra fish na frase fish are swimming in the fish pond, as várias versões da cláusula retain terão os efeitos a seguir:

  • Cláusula retain omitida

    " 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"

  • reter ambos os pontos de divisão

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

Exemplo 2: extração de divisão

Este exemplo divide o documento em sentenças. Ele usa primeiro uma expressão regular para identificar os limites de sentença, em seguida, usa a especificação de extração de divisão para dividir o texto do documento nos limites de sentença.

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;

Bloqueios

Use a especificação de extração de blocos para identificar blocos de spans contíguos através de texto de entrada.

Sintaxe

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

Descrição

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

    Especifica quantos spans podem compor um bloco. Os valores <min\> e <max\> especificam o número mínimo e máximo de intervalos que podem compor um bloco.

  • [between 0 and] <max\>

    Especifica a distância de separação que é permitida entre os spans antes que eles não sejam mais considerados contíguos.

  • (tokens| characters)

    Especifica se a distância de separação da amplitude representa o número de tokens ou o número de caracteres.

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

    O nome da visualização e o nome da coluna aos quais o operador de bloco deve ser aplicado.

  • <output name\>

    Especifica um nome para a saída do operador de blocos.

Observações de uso

  • Se as varreduras de entrada contiverem diversos blocos de sobreposição nos períodos de entrada, uma instrução de extração de bloco retornará todos os blocos possíveis. Use a consolidação para filtrar blocos redundantes.
  • Uma instrução extract com a especificação de extração de bloco produz blocos que consistem, cada um, em uma agregação de valores de um determinado campo de entre múltiplas tuplas de entrada. Portanto, sua lista de seleção não pode incluir campos de sua visualização de entrada.

Exemplos

Exemplo 1: extrair blocos de palavras dentro de um intervalo de caracteres

No código a seguir, a visualização TwoToThreeCapitalizedWords identifica blocos de duas a três palavras alteradas para letras maiúsculas dentro de 100 caracteres uma da outra.

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;

Exemplo 2: extrair blocos de palavras dentro de um intervalo de tokens

O código a seguir identifica blocos de exatamente duas palavras alteradas para letras maiúsculas dentro de cinco tokens uma da outra.

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

Parte do discurso

Use a especificação de extração de parte do discurso para identificar locais de diferentes partes da fala no texto de entrada.

Sintaxe

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>

Descrição

  • '<part of speech spec\>'

    Identifica as partes do discurso para extrair do texto de entrada. O '<part of speech spec\>' é uma das sequências a seguir:

    • Uma sequência que contém uma lista delimitada por vírgula de tags de parte do discurso que são geradas pelo tokenizer Multilingual
    • Uma combinação de um nome de parte interna-de-fala e sinalizadores, conforme definido por uma tabela de mapeamento
  • [and '<part of speech spec\>']*

    Identifica as tags de parte do discurso para extração.

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

    Especifica o idioma a ser usado na extração. O <language code\> é um código de idioma de duas letras em minúsculas, como 'en' ou 'ja'. Se esse argumento for omitido, o idioma para extração de parte do discurso será assumido como inglês

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

    Especifica o nome de uma tabela AQL que mapeia as tags brutas de parte do discurso, como "NOUN", para combinações de partes do discurso e de sinalizações de alto nível. Enquanto a tabela de mapeamento opcional pode ter nomes de variáveis, uma tabela de mapeamento de parte da fala é necessária para ter esses nomes de colunas:

    • Tag

      A coluna que contém uma tag de parte do discurso do tokenizer Multilingual.

    • basetag

      A coluna que contém a tag interna correspondente.

    • flagstr

      A coluna que contém uma lista delimitada por vírgula de sinalizações que estão associadas à parte do discurso indicada.

    A tabela de mapeamento deve ser definida usando a instrução create table no mesmo módulo que a instrução part_of_speech de extração que a usa. Ela não pode ser uma tabela importada e não pode ser uma tabela externa.

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

    Especifica a coluna da visualização de entrada a partir da qual se extraia informações de parte da fala.

  • <output column\>

    Especifica o nome da coluna na qual os spans dos tokens com as partes do discurso indicadas são enviados.

  • <input view\>

    Especifica a visualização de entrada por meio da qual extrair informações de parte do discurso.

Observações de uso

  • A extração de parte do discurso funciona somente quando está usando o tokenizer Multilingual. Se o sistema usar o tokenizer Standard, uma extração part_of_speech gerará um erro.

Tags de partes do discurso para idiomas

Para todos os idiomas suportados, o tokenizer Multilíngue usa as tags de parte do discurso que estão listadas na tabela a seguir.

Marcar Descrições
ADJ adjetivo
ADP adposição
ADV advérbio
AUX auxiliar
CCONJ conjunção coordenativa
DET determinador
INTJ interjeição
NOUN substantivo
NUM numeral
PART partícula
PRON pronome
PROPN substantivo próprio
PUNCT pontuação
SCONJ conjunção subordinativa
SYM símbolo
VERB verbo
X outro

Exemplos

Exemplo 1: usando uma tag de parte do discurso diretamente em uma instrução extract

A visualização EnglishNoun extrai substantivos em inglês (singular ou em massa) ou substantivos próprios (singular).

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

Padrões de sequência

Use a especificação de extração de padrão para executar a correspondência de padrão em um documento de entrada e em outros spans extraídos do documento de entrada.

Sintaxe

A sintaxe geral de um padrão de sequência é primeiro especificar o padrão a ser correspondido no texto e, em seguida, especificar o que deve ser retornado pelo extrator. A parte final do padrão de sequência especifica o que é a entrada para o padrão; pode ser uma coluna de uma visualização definida anteriormente ou o todo o texto do documento.

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

Descrição

  • <pattern specification\>

    Um <pattern specification\> é composto de diversos átomos. Um Atom individual pode ser uma coluna a partir de uma visão já definida, de uma sequência fixa ou de uma expressão regular. É possível especificar seus Átomos como opcionais e de repetição, além de especificar diferenças de token entre os Átomos.

    A especificação de padrões faz parte de uma instrução AQL maior, que inclui uma cláusula de extração.

    Aqui está um exemplo simples de como criar uma visualização que contém três correspondências adjacentes de visualizações definidas anteriormente. Neste exemplo, a combinação inteira é retornada à qual o group 0 se refere:

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

    Se os seus Átomos não precisarem ser exatamente adjacentes entre si, será possível usar diferenças de token entre os Átomos para permitir mais correspondências. Este exemplo localiza menções de pessoas que seguem dentro de 0 a 2 tokens por um número de telefone. Veja que a construção <Token>{0,2}, que indica que é permitido um intervalo de 0 a 2 tokens entre as anotações da pessoa e do telefone.

    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;
    

    As construções de diferença de token são restritas a ocorrer dentro das expressões de sequência. Além disso, cada diferença de token em uma sequência deve ser precedida e seguida por uma expressão "diferença não de token". Como resultado, as instruções extract pattern produzem exceções:

    -> 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 ...
    

    Use a sintaxe (min,max) para indicar o número de vezes que cada Atom repetirá. Também é possível usar a sintaxe ? para indicar que um Átomo ou um Átomo de repetição é opcional. Os átomos, juntamente com suas indicações para repetição e opcionais, são combinados para criar sequências.

    Aqui está um exemplo mais complexo que mostra como repetir elementos. Localize os nomes de hotéis candidatos identificando ocorrências de uma a três palavras alteradas para letras maiúsculas, seguidas de um token 'Hotel' ou '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;
    

    Também é possível usar o operador | para indicar uma escolha entre átomos, como em extract pattern <A.match>| <B.match> <C.match> as match from Apple A, Bacon B, Chocolate C;. Esse padrão pode ser explicado como “corresponder um A.match OU uma sequência de um B.match seguido de um C.match. É possível ver um exemplo completo que usa o operador | no Exemplo 1.

    Depois que você cria seu padrão, cada correspondência com seu <pattern specification> cria um resultado de saída de acordo com a cláusula de retorno da especificação do padrão, bem como o <select list> opcional no início da instrução extract. Os resultados são filtrados e consolidados de acordo com as cláusulas having, consolidatee limit da instrução extract . Por exemplo, se existirem diversas correspondências de sobreposição para a especificação de padrão, todas as correspondências possíveis serão retornadas e será possível usar uma cláusula consolidation para filtrar as saídas redundantes.

    Considere o exemplo anterior, mas agora o objetivo é remover as correspondências que contenham a palavra 'Sheraton' e consolidar as correspondências resultantes removendo aquelas que estão contidas dentro de uma correspondência maior. Por exemplo, não desejamos localizar “Best Garden Hotel” e também “Garden Hotel” no mesmo span 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';
    

Agora que você está familiarizado com a sintaxe e alguns exemplos, este diagrama descreve a sintaxe integral para a especificação de padrão. Consulte essa sintaxe integral quando iniciar a construção de padrões para ver como estruturar o padrão que você deseja construir.

Se você estiver familiarizado com expressões regulares baseadas em caracteres do POSIX, você reconhecerá que a sintaxe é semelhante. Nesse caso, a sintaxe permite espaço em branco entre os elementos e o que um elemento pode ser para se adequar aos propósitos de AQL também é definido. Observe que o termo Alternation neste caso significa escolha. O uso de uma barra vertical entre os elementos indica que existe uma escolha, que pode ser agrupada usando ( ).

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 )

Especificamente, um Atom pode ter seis formatos:

  • <view_name.column_name\>

    Especifica uma coluna de uma das visualizações, tabela ou referências de função de tabela que são nomeadas na lista from da instrução extract pattern.

  • 'string'

    Especifica uma correspondência para a sequência especificada usando a semântica de correspondência de dicionário padrão de AQL.

  • <'string' [match parameters]\>

    Especifica uma correspondência para a sequência especificada usando a semântica de correspondência de dicionário que é especificada pelo [match parameters]. O formato de [match parameters] é maiúsculas e minúsculas (exact | insensitive). Esse formato especifica o tipo de padronização de caracteres (maiúsculos ou minúsculos) usado para determinar as correspondências de sequência. Para especificar uma correspondência exata que faça distinção entre maiúsculas e minúsculas, selecione exact. Para especificar uma correspondência sem distinção entre maiúsculas e minúsculas, selecione o valor padrão insensitive.

  • /regex/

    Especifica uma correspondência de expressão regular baseada em caracteres com correspondência restrita a um único token no texto do documento. Além disso, a sintaxe permite que uma construção de diferença de token especial seja especificada em uma expressão de sequência para indicar uma correspondência entre o número min e max de tokens.

  • <token\>

    Uma correspondência para qualquer token.

  • [return clause]

    Gera os valores extraídos para cada correspondência da expressão padrão de acordo com a cláusula de retorno. A cláusula return tem a mesma semântica que a cláusula return em uma instrução extract regex.

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

    Para os Átomos, como os Átomos de sequência e de regex, a cláusula with inline_match determina qual objeto de texto o sistema usa para extração de sequência ou de regex. Por exemplo, se a cláusula for with inline_match on Email.subject, todos os dicionários e expressões regulares definidos em sequencial na especificação padrão serão aplicados no campo de assunto da visualização Email. Se o with inline_match estiver ausente, a extração de sequência e de expressão regular será executada por padrão no Document.text inteiro. Neste caso, o viewname deve ser o nome de uma view ou table que é definido no módulo atual, ou importado de outro módulo; as referências a funções de tabela não são permitidas na cláusula inline_match.

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

    Especifica uma lista delimitada por vírgulas de códigos de idioma de duas letras, como en (inglês) ou zh (chinês) para os idiomas nos quais avaliar a sequência. Não há correspondência em documentos cujo código de idioma não esteja contido nessa sequência. Se o parâmetro language for omitido, o idioma de avaliação será padronizado para um dos conjuntos de idiomas a seguir:

    • Se ele for declarado, os conjuntos de idiomas que são especificados por meio da instrução set default language no módulo de contenção.
    • Os conjuntos de idiomas que contêm alemão (de), espanhol (es), inglês (en), francês (fr), italiano (it) e o idioma não especificado (x_unspecified)

Observações de uso

  • A semântica de uma instrução extract pattern é acionada pela especificação de padrão. Cada correspondência constrói um resultado de saída de acordo com a cláusula de retorno da especificação de padrão e a lista de seleção na parte superior da instrução extract. Os resultados são filtrados e consolidados de acordo com as cláusulas having, consolidate e limit da instrução extract. Se existirem diversas correspondências de sobreposição para a especificação de padrão, uma extração de padrão gerará todas as correspondências possíveis. Use a consolidação para filtrar saídas redundantes.

  • A semântica da cláusula from de uma instrução extract pattern é diferente de outras formas de instruções extract que não têm uma especificação de padrão. A semântica geral de uma instrução extract requer que a especificação de extração seja avaliada em cada combinação das visualizações definidas em <from list\>. Se pelo menos uma das visualizações em <from list\> não contiver nenhum resultado em um documento específico, a saída da instrução de extração estará vazia, pois o conjunto de todas as combinações de resultados nas visualizações de entrada estará vazio. No caso especial de instruções extract pattern, a cláusula from é um item temporário que declara os nomes de relações que estão envolvidas na especificação de padrão. A semântica da instrução é acionada apenas pela especificação do padrão. Em particular, a saída da instrução pode ser não vazia mesmo quando algumas das visualizações de entrada estiverem vazias.

  • Uma instrução extract que usa a extração de padrão de sequência poderá transportar para frente as colunas de qualquer visualização na lista from, mas somente se o nome da visualização não aparecer em um elemento de repetição da especificação de padrão. Por exemplo, a instrução CapsWordOneToThree resulta em um erro de compilação. O erro ocorre porque a coluna transportada CW.type na parte superior da instrução extract pertence ao nome da visualização CW, que está no elemento de repetição <CW.word>{1,3} da especificação de padrão.

    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;
    

    Para as colunas que são transportadas de nomes de visualização que aparecem em elementos alternativos ou opcionais da especificação de padrão, o valor da coluna de saída é null quando a alternativa correspondente ou o elemento opcional não está presente no texto. Um exemplo que ilustra esse ponto está na visualização Person do Exemplo 1.

  • Os grupos que ocorrem sob um elemento de repetição não podem ser gerados na cláusula return da instrução. Por exemplo, a instrução a seguir causa uma exceção:

    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;
    

Exemplos

Exemplo 1: padrão de Sequência com grupos de captura

O objetivo deste exemplo é localizar nomes de pessoas identificando ocorrências do nome, opcionalmente seguido pela inicial do segundo nome, seguido por um sobrenome e a correspondência inteira que é opcionalmente precedida por uma saudação comum. Além disso, o extrator retorna a correspondência inteira como referência, o primeiro grupo como saudação e o segundo grupo como nome e transporta os valores do nome, da inicial do meio e do sobrenome das respectivas visualizações 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;

Uma vez que a expressão de subpadrão ('Mr.'|'Ms.'|'Miss')? é opcional, o valor da coluna de saída de saudação é null quando uma saudação não está presente no texto. Da mesma forma, uma vez que a subexpressão padrão <M.initial>? é opcional, o valor do meio da coluna de saída é null quando uma inicial média não está presente.

Exemplo 2: padrão de sequência com correspondência de sequência e parâmetros de correspondência

O objetivo deste exemplo é localizar ocorrências de notas de reunião para projetos conhecidos, examinando as anotações do título do documento. Observe a cláusula with inline_match, que especifica que a correspondência de sequência é feita sobre o campo de correspondência da visualização Title, em oposição ao texto do documento inteiro.

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;

Exemplo 3: padrão de sequência que retorna resultados não vazios mesmo quando uma visualização de entrada está vazia

A instrução a seguir gera resultados mesmo quando a visualização de entrada LastName está vazia. A segunda parte da especificação de padrão, <L.name\>?, contém um elemento opcional. A semântica da especificação de padrões é projetada para a saída de todas as spans que são compostas por uma amplitude FirstName.name ou um span FirstName.name que é imediatamente seguido por um LastName.name span. Portanto, em documentos para os quais a visualização LastName está vazia, o resultado da instrução consiste em todos os spans que compreendem um único span FirstName.name que é identificado por meio desse 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;

A instrução select

A instrução select em AQL fornece um mecanismo poderoso para o uso de várias especificações para construir e combinar conjuntos de tuplas.

Sintaxe

A instrução select é semelhante em estrutura a uma instrução SQL SELECT:

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>`];

Descrição

  • <select list\>

    Uma lista delimitada por vírgula de expressões de saída.

  • <from list\>

    Uma lista delimitada por vírgula que é a origem das tuplas a serem selecionadas.

  • [where <where clause\>]

    Define um predicado a ser aplicado sobre cada tupla que é gerada por meio do produto Cartesiano de todas as tuplas nas relações na cláusula from. Essa cláusula é opcional.

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

    Define uma política de consolidação para gerenciar spans de sobreposição. Essa cláusula é opcional.

  • [group by<group by list\>]

    Agrupa as tuplas que são produzidas por meio do mesmo documento por valores comuns de um campo especificado. Essa cláusula é opcional.

  • [order by<order by list\>]

    Ordena as tuplas de saída que são produzidas pela instrução select de cada documento. A ordem é baseada nos valores da lista order-by, uma lista de expressões delimitadas por vírgula. Essa cláusula é opcional.

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

    Limita o número de tuplas de saída para cada documento para o máximo especificado. Essa cláusula é opcional.

Notas de uso

A semântica da instrução select é a seguinte:

  • Determine os dados de entrada (em tuplas) usando o produto Cartesiano de relações na lista de origem.
  • Para cada tupla de entrada gerada, filtre-a aplicando os predicados na cláusula where (opcional).
  • Se a cláusula group by opcional estiver presente, agrupe as tuplas produzidas do mesmo documento pelos valores especificados na lista agrupar por e calcule o resultado das funções aggregate da lista de seleção.
  • Consolide as tuplas de sobreposição de acordo com a política definida na cláusula consolidation (opcional). Se a cláusula order by opcional estiver presente, solicite essas tuplas pelos valores da lista order-by.
  • Compute todas as expressões dentro da lista select em cada tupla e renomeie as colunas conforme especificado pelas cláusulas as.
  • Se a cláusula limit opcional estiver presente, limite o número de tuplas de saída para o número especificado de tuplas para cada documento.

Exemplos

Um exemplo de como usar a instrução select é extrair números de telefone que correspondem a um padrão. Suponha que a visualização PhoneNumbers que extrai números de telefone do padrão XXX-XXX-XXXX para os Estados Unidos já esteja definida. Esta instrução select avalia a expressão regular para o padrão 444-888-XXXX em todo o texto de entrada. A visualização tem as colunas de saída documentText e phoneNumber. Além disso, a saída é limitada à primeira ocorrência desse padrão de número de telefone que é identificado por documento.

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

Outro exemplo de como é possível usar a instrução select é localizar mapeamentos aproximados de pessoas e seus números de telefone correspondentes. Suponha que a visualização Person já esteja definida e que tenha as colunas person e a visualização PhoneNumbers. Esta instrução select avalia a cláusula where para localizar spans de texto que contenham uma menção de pessoa seguida de um número de telefone dentro de 1 3 palavras ou tokens. A entrada para essa instrução é representada por uma junção das visualizações Person e PhoneNumbers na 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);

A coluna personPhoneSpan conterá os spans correspondentes que fornecem o mapeamento aproximado de pessoa-telefone.

personPhoneSpan
John : 433-999-1000
Martha Mob 433-999-1001
  • A lista de seleção A lista de seleção em uma instrução AQL select ou extract consiste em uma lista delimitada por vírgulas de expressões de saída.
  • A lista de origem A segunda parte de uma instrução select ou extract na AQL é a da lista de origem. A lista from é uma lista separada por vírgula que é a origem das tuplas a serem selecionadas ou extraídas.
  • A cláusula where A cláusula where opcional define um predicado a ser aplicado em cada tupla gerada do produto Cartesiano de todas as tuplas nas relações na cláusula from.
  • A cláusula consolidate on A cláusula consolidate on opcional especifica como os períodos de sobreposição são resolvidos nas tuplas geradas por uma instrução select ou extract. Tuplas com spans não sobrepostos não são afetadas quando essa cláusula é usada.
  • A cláusula group by A cláusula group by opcional de uma instrução select direciona o componente de tempo de execução para agrupar as tuplas produzidas do mesmo documento por valores comuns de um campo especificado.
  • A cláusula order by A cláusula order by opcional direciona o componente de tempo de execução para ordenar as tuplas de saída produzidas pela instrução select de cada documento com base nos valores da lista order by, que é um conjunto de expressões delimitado por vírgulas
  • A cláusula limit A cláusula limit opcional especifica um limite no número de tuplas de saída produzidas pela instrução select para um documento.
  • A instrução select... into A instrução select ... into é útil para definir uma visualização e especificar que é uma visualização de saída em uma única instrução.

A lista de seleção

A lista de seleção em uma instrução AQL select ou extract consiste em uma lista delimitada por vírgula de expressões de saída.

Sintaxe

Cada expressão select deve estar em uma das formas a seguir:

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>

Descrição

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

    • <viewname\>

      Especifica a visualização por meio da qual selecionar colunas.

    • <colname\>

      Especifica a coluna nessa visualização.

    • <alias\>

      Especifica o nome pelo qual o campo selecionado é conhecido. Esse campo é um campo opcional. Ele é selecionado para fazer parte de cada tupla de saída. Se <alias\> não for especificado, o nome da coluna será <colname\> por padrão. Pode ser um identificador simples ou um identificador duplo citado.

  • <viewname\>.*

    Especifica o nome de uma visualização. Essa sintaxe indica que todas as colunas da visualização especificada devem ser transportadas para a instrução select ou extract circundante.

    Como a SQL, a AQL permite a instrução select * abreviada. O efeito dessa instrução é selecionar todas as colunas de todas as entradas que estão especificadas na cláusula from da instrução select. No entanto, a instrução extract * abreviada não é suportada.

  • <expr\> as <alias\>

    Representa a designação de uma expressão para um atributo da visualização abrangente.

    • <expr\>

      Especifica uma expressão que é composta por chamadas de função escalar, chamadas de função agregada ou uma constante.

    • <name\>

      Representa o nome da coluna que detém o resultado da expressão especificada por <expr\> como <alias\>. Se <alias\> não for especificado, o nome da coluna será <name\> por padrão. Pode ser um identificador simples ou um identificador duplo citado.

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

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

      Especifique funções escalares que retornam o tipo Boolean.

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

      Especifique expressões que sejam compostas de chamadas de função escalar e devem retornar o mesmo tipo.

    Se o resultado de <function1()\> for true, o resultado da expressão case será o resultado de <expr1\> e nenhuma das cláusulas when subsequentes serão avaliadas. Caso contrário, as cláusulas when subsequentes (se houver) serão avaliadas da mesma maneira.

    Quando nenhuma das condições das cláusulas when é atendida, o resultado dessa expressão de caso é o resultado da expressão padrão <expr\_default\>. Essa expressão é especificada na cláusula else opcional. Se a cláusula [else] estiver ausente, o resultado desta expressão case é null.

Observações de uso

  • A instrução a seguir não é suportada:

    select * from Document;
    

    Os conteúdos da visualização Document podem não ser totalmente conhecidos no contexto ou escopo atual do arquivo .aql em que esta instrução select é emitida. A falta de informações sobre os conteúdos é porque múltiplas instruções require document with columns fornecidas fora do arquivo atual .aql podem alterar a definição de esquema eventual dessa visualização Document especial quando ela é usada no nível de um módulo. A instrução Document.* abreviada não é uma construção AQL válida.

  • É possível selecionar explicitamente os campos por meio da visualização Document. O exemplo a seguir mostra uma seleção explícita válida de campos por meio de uma visualização Document:

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

Exemplos

Os exemplos a seguir ilustram várias formas da lista de seleção.

Exemplo 1: designação de valor explícito usando uma constante

Este exemplo mostra a designação de um valor constante a um atributo de visualização dentro da lista de seleção. O campo chamado polaridade indica se a polaridade de PS.match é positiva ou negativa (Observe a designação explícita de um valor constante para esse 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;

Exemplo 2: designação de valor explícito usando chamada de função

O exemplo a seguir ilustra como o resultado de uma chamada de função é explicitamente designado a um atributo de visualização dentro da lista de seleção.

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

Exemplo 3: expressão select list de uma extração de dicionário

O exemplo a seguir ilustra como a expressão select list pode escolher valores do tipo Span a partir de um resultado de extração de dicionário.

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

Exemplo 4: Exemplos de expressões de caso

Este primeiro exemplo mostra como especificar a manipulação nula em 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;

Este exemplo explica como classificar dados:

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;

A lista de

A segunda parte de uma instrução select ou extract em AQL é a lista from. A lista from é uma lista separada por vírgula que é a origem das tuplas a serem selecionadas ou extraídas.

Sintaxe

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

Descrição

  • <from list item\>

    Uma visualização, tabela, referência de função de tabela ou instrução AQL aninhada. Todas as instruções aninhadas em AQL devem ser circundadas por parênteses.

  • <name\>

    Nome local do <from list item\>, que tem o escopo definido na instrução select ou na instrução extract. Um nome local pode ser um identificador simples ou um identificador com aspas duplas. Os nomes locais que contêm espaços, caracteres de pontuação ou palavras-chave AQL devem estar entre aspas duplas.

Exemplos

Exemplo 1: Uma lista from com uma visualização e uma instrução aninhada

Este exemplo mostra uma lista from que referencia uma visualização e uma instrução extract aninhada. O exemplo designa o resultado da instrução ao nome local FN. O exemplo também designa as saídas da visualização LastName para o nome 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);

Os nomes a seguir estão contidos no dicionário externo first.dict:

#Dictionary for given names
Aaron
Candra
Freeman
Mathew
Matthew
Zoraida

A cláusula where

A cláusula where opcional define um predicado a ser aplicado a cada tupla gerada por meio do produto Cartesiano de todas as tuplas nas relações na cláusula from.

Sintaxe

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

Descrição

  • <where clause\>

    Especifica um ou mais predicados. Uma junção ocorre quando qualquer predicado em uma cláusula where envolve campos de mais de uma visualização que pertence à lista from. Este predicado deve ser uma conjunção de um conjunto de funções de predicado integrado ou outras funções definidas pelo usuário que retornam o tipo de dados Boolean:

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

    A cláusula where é opcional e poderá ser omitida de uma instrução select se não existir nenhum predicado para aplicar.

Exemplos

Exemplo 1: filtrar as tuplas associadas usando um predicado na cláusula WHERE

Este exemplo mostra uma cláusula where que localiza apenas as frases que consistem em nomes válidos seguidos de 0 a 1 caractere por sobrenomes 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);

Os nomes a seguir estão contidos no dicionário externo first.dict:

#Dictionary for given names
Aaron
Candra
Freeman
Mathew
Matthew
Zoraida

Os nomes a seguir estão contidos no dicionário externo last.dict:

#Dictionary for surnames
Anthony
Lehman
Radcliff

A cláusula consolidate on

A cláusula consolidate on opcional especifica como os spans de sobreposição são resolvidos entre as tuplas que são geradas por uma instrução select ou extract. Tuplas com spans não sobrepostos não são afetadas quando essa cláusula é usada.

Sintaxe

O código a seguir é um exemplo da estrutura geral dessa cláusula:

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

Descrição

  • <target\>

    Especifica uma coluna em uma visualização na cláusula from ou uma expressão que é composta de chamadas de função escalar envolvendo colunas de visualizações que são especificadas na cláusula from como argumentos.

  • '<policy\>'

    Especifica uma das políticas de consolidação a seguir que são suportadas por Análise de texto:

    • ContainedWithin

      Essa política é a inadimplência. Se os spans A e B se sobrepuserem e A contiver completamente B, essa política removerá a tupla que contém o span B da saída. Se A e B forem os mesmos, então removerá um deles. A escolha de qual tupla será removida é arbitrária.

    • NotContainedWithin

      Se spans A e B se sobrepõem, e A contém completamente B, esta política então remove o span A da saída. Se A e B forem os mesmos, então removerá um deles. A escolha de qual tupla será removida é arbitrária.

    • ContainsButNotEqual

      Essa política é a mesma que ContainedWithin, exceto que os spans que são exatamente iguais são retidos.

    • ExactMatch

      Se um conjunto de spans cobrir a mesma região de texto, essa política retornará exatamente um deles. Todos os outros spans serão deixados intocados.

    • LeftToRight

      Essa política processa os spans em ordem da esquerda para a direita. Quando a sobreposição ocorre, ela mantém o span de sobposição mais à esquerda, mais longo e sem sobreposição. Essa política emula a política de manipulação de sobreposição da maioria dos mecanismos de expressão regular.

  • <priority\_column\>

    Especifica uma coluna do tipo Text, String, Integer ou Float. Pode ser especificado apenas com a política de consolidação LeftToRight.

  • <priority\_order\>

    Especifica ordem crescente ou decrescente. Pode ser especificado apenas com a política de consolidação LeftToRight. A ordem crescente assegura que se uma tupla T1 tiver prioridade 1 e uma tupla T2 tiver prioridade 2, T1 terá uma prioridade mais alta que T2. Por contraste, se a ordem de prioridade for decrescente, o T2 tem uma prioridade maior. O valor padrão da ordem de prioridade é crescente.

Observações de uso

  • Quando a cláusula de prioridade está presente, a semântica da consolidação segue esta ordem:
    • O processo abrange da esquerda para a direita e, quando os spans se sobrepõem, eles retêm os spans mais à esquerda.
    • Se você tiver múltiplos spans de sobreposição que se iniciam no mesmo deslocamento, retenha aqueles com a prioridade mais alta de acordo com a ordem de prioridade.
    • Quebre os empates restantes mantendo os spans mais longos entre os spans com a mesma prioridade.
  • A consolidação trata os nulos como idênticos. Todas as entradas com um <consolidate target\> nulo resultam em uma tupla de saída única, que é escolhida aleatoriamente entre essas entradas. Esse comportamento é semelhante a como as tuplas são consolidadas com um span idêntico na coluna de destino. A exceção para resultar em uma tupla de saída única será se a política for ContainsButNotEqual. Nesse caso, o <consolidate target\> nulo gera todas as entradas com destino de consolidação nulo.

Exemplos

Exemplo 1: consolidar em coluna única

Este exemplo direciona o sistema para examinar o campo Person.name de todas as tuplas de saída e para usar a política de consolidação ContainedWithin para resolver a sobreposição.

consolidate on Person.name
  using 'ContainedWithin'

Exemplo 2: Consolidar na expressão, envolvendo várias colunas

Este exemplo direciona o sistema para examinar o resultado da aplicação da função escalar CombineSpans para os campos Person.firstname e Person.lastname em cada tupla de saída. Ele resolve a sobreposição usando a política de consolidação ContainedWithin.

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

Exemplo 3: consolidar usando a política LeftToRight e a ordem de prioridade

Suponha que as tuplas de Termo a seguir sejam extraídas do texto de entrada John Doe:

match: `John`,
priority: `1`

e

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

Ambos os spans têm o mesmo deslocamento inicial. Ao consolidar usando a política LeftToRight para a ordem de prioridade crescente, a tupla (match: John, priority: 1) é retida porque ela tem a prioridade mais alta. Ao consolidar usando a ordem de prioridade decrescente, a tupla (match: John Doe, priority: 2) é retida, como no exemplo a seguir:

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;

A cláusula group by

A cláusula opcional group by de uma instrução select direciona o componente de tempo de execução para agrupar tuplas que são produzidas do mesmo documento por valores comuns de um campo especificado.

Sintaxe

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

Descrição

  • <group by list\>

    Especifica uma lista delimitada por vírgula de expressões que envolve colunas das visualizações na cláusula from e nas chamadas de função escalar. Ao aplicar a cláusula group by, cada grupo de tuplas que compartilha valores comuns para todas as expressões group by produz uma tupla de saída única que é representativa para o grupo inteiro.

    Um campo ou expressão que não aparece na cláusula group by não pode aparecer na lista de seleção, a menos que ela seja usada em uma chamada de função agregada. A ordem de expressões na lista não importa.

    A cláusula group by trata todos os nulos como idênticos. O Group by em uma coluna com valores nulos resulta em um único grupo.

Exemplos

Exemplo 1: computando valores agregados

Use a cláusula group by para computar valores agregados. Este exemplo conta o número de ocorrências de cada nome no documento. Neste exemplo, Count é uma função agregada.

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);

Nesse caso, first.dict é um dicionário externo que contém as entradas a seguir:

#Dictionary for given names
Aaron
Candra
Freeman
Matthew
Zoraida

As etapas a seguir descrevem a semântica dessa instrução:

  1. Agrupe tuplas que são produzidas pela subconsulta na cláusula from pelo conteúdo de texto de seu campo firstname.
  2. Para cada grupo, conte o número de tuplas com um valor de firstname não nulo. Produza uma tupla de saída única para cada grupo desse tipo, com dois valores, o nome e o número de tuplas nesse grupo.

Exemplo 2: problemas com o agrupamento de campos dissimilares

Este exemplo ilustra uma instrução que não é 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);

A inclusão de GetText(P.lastname) no select list não é aceita, uma vez que as tuplas com os mesmos valores de firstname podem ter valores de lastname diferentes, o que leva à ambiguidade.

A cláusula order by

A cláusula order by opcional direciona o componente de tempo de execução a ordenar as tuplas de saída que são produzidas pela instrução select por meio de cada documento com base nos valores da ordem por lista, que é um conjunto delimitado por vírgula de expressões.

Sintaxe

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

Descrição

  • <order by list\>

    Especifica uma lista de expressões delimitadas por vírgula.

    A ordem é baseada nos valores de uma lista de expressões delimitadas por vírgula. A cláusula order by suporta expressões que retornam tipos de dados numéricos (Número inteiro ou Valor flutuante), Texto ou Período. Se uma expressão na cláusula order by retornar um tipo Span, as tuplas de resultado serão comparadas por meio da comparação dos valores de span relevantes. No exemplo a seguir, os valores de span do campo person são comparados.

    order by P.person
    
    

    A cláusula order by trata nulos como não ordenados (entre si). Os nulos são ordenados mais baixos que outros objetos.

Exemplos

Exemplo 1: ordem por múltiplas expressões

Suponha que a pessoa seja um campo do tipo Span. A cláusula order by a seguir especifica que a instrução retorna tuplas dentro de cada documento. Elas são ordenadas lexicograficamente pelo texto do campo de pessoa e, em seguida, pelo início do campo de pessoa.

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

A cláusula limit

A cláusula limit opcional especifica um limite sobre o número de tuplas de saída que são produzidas pela instrução select para um documento.

Sintaxe

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

Descrição

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

    Especifica o número máximo de tuplas de saída para cada documento. Se o valor limite for maior ou igual ao número total de tuplas que poderiam ser retornadas, todas as tuplas serão retornadas.

Exemplos

Exemplo 1: limitando o número de retornos

Este exemplo retorna os três primeiros nomes de pessoa em cada documento:

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

A instrução select... into

A instrução select ... into é útil para definir uma visualização e especificar que se trata de uma visualização de saída em uma única instrução.

Sintaxe

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>];

Descrição

  • <output view name\>

    Especifica o nome da visualização de saída que é definida pela instrução. A instrução select ... into é idêntica à instrução select, exceto pela cláusula into <output view name\> adicional.

Exemplos

Exemplo 1: definindo uma visualização

Este exemplo define uma visualização que é chamada PersonPhone e também especifica essa visualização como uma visualização de saída.

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

Este exemplo é equivalente às duas instruções a seguir:

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

output view PersonPhone;

A instrução detag

A instrução detag em AQL fornece a função para desmarcar ou remover toda a marcação de documentos HTML ou XML antes de executar os extratores AQL.

A instrução detag também pode reter os locais originais de tags e todos os valores armazenados nelas. Quando uma instrução detag remove tags de um documento, o componente de tempo de execução lembra o mapeamento entre os deslocamentos do texto com tag removida e da origem de marcação original. A função Remap, uma função integrada especial que mapeia os spans do texto com tag removida de volta para seus spans equivalentes da origem original.

Sintaxe

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 ...]];

Descrição

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

    • <input view name\>

      Especifica o nome da visualização de entrada na qual fazer o processo de remoção de tag. O <input view name\> pode ser um identificador simples ou um identificador entre aspas duplas.

    • <text column\>

      Especifica o campo de texto da visualização de entrada na qual fazer o processo de remoção de tag. O <text column\> pode ser um identificador simples ou um identificador entre aspas duplas.

  • <output view name\>

    Especifica o nome da visualização de saída que contém o texto com tag removida. A visualização de saída contém uma única coluna que é chamada text, que contém o texto com tag removida. O <output view name\> pode ser um identificador simples ou um identificador entre aspas duplas.

  • always|never

    Especifica se deve verificar se os conteúdos são HTML ou XML antes de a instrução detag ser processada. Ao executar textos não HTML e não XML por meio de um removedor de tag, problemas podem ocorrer quando o texto contém caracteres especiais XML, como <, > ou &. Se a cláusula detect content_type estiver ausente, o valor padrão será always e o sistema sempre detectará o conteúdo.

    • always

      Especifica que a verificação sempre ocorre antes que a operação seja tentada para evitar problemas com a análise de documentos que não são HTML ou XML. Se o valor de <text column\> não parecer conter uma marcação, o sistema ignorará a remoção de tag do documento atual.

    • never

      Especifica que a verificação nunca ocorre antes que a operação de remoção de tag seja tentada. O sistema tenta remover tag do texto de destino, mesmo que o texto não contenha nenhum conteúdo HTML ou XML.

  • <element name\>

    Especifica o nome do elemento HTML ou XML a ser anotado. A cláusula annotate opcional pode direcionar o componente de tempo de execução para lembrar informações sobre as tags removidas criando uma ou mais visualizações.

  • <auxiliary view name\>

    Especifica o nome da visualização que é criada para conter as tags originais e seus atributos. Pode ser um identificador simples ou um identificador duplo citado.

  • <attribute name\>

    Nome de um atributo do elemento HTML ou XML.

  • <column name\>

    O nome da coluna em <auxiliary view name\> que é usado para armazenar os valores de <attribute name\>. Pode ser um identificador simples ou um identificador duplo citado.

Exemplos

Exemplo 1: especificando a visualização de saída de remoção de tag e uma visualização auxiliar

Neste exemplo, a visualização DetaggedDoc é criada para conter a versão com tag removida do texto original no atributo text da visualização Document. Além de criar uma visualização DetaggedDoc, a cláusula anotate cria uma visualização auxiliar chamada Anchor. Essa visualização auxiliar tem duas colunas. Uma coluna, chamada match, contém o texto âncora. A outra coluna, chamada linkTarget, contém o destino real do link como texto. Os spans na coluna de correspondência estão sobre o valor de texto da visualização DetaggedDoc.

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

Exemplo 2: usando a função Remap

O exemplo a seguir ilustra como a função Remap é usada para mapear os spans do texto com tag removida de volta para seus equivalentes na origem 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;

Documentando a instrução detag com o AQL Doc

O comentário do AQL Doc para uma instrução detag contém as seguintes informações:

  • Descrição geral sobre a função da instrução.
  • O @field para cada campo de texto da visualização de entrada na qual fazer o processo de remoção de tag.
  • @auxView especifica o nome da visualização.
  • O @auxViewField especifica o nome completo da coluna da visualização.
/**
* 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;

As instruções create dictionary e create external dictionary

As instruções create dictionary e create external dictionary são usadas para definir dicionários de palavras ou frases para identificar termos de correspondência no texto de entrada por meio de instruções de extração ou funções de predicado. A instrução create dictionary permite a especificação de conteúdo de dicionário no código AQL de origem e o conteúdo do dicionário é serializado dentro da representação compilada do módulo (o arquivo .tam). A instrução create external dictionary permite especificar o conteúdo do dicionário quando o extrator é instanciado, em vez de no código AQL de origem, e você não precisa recompilar o módulo. Portanto, os dicionários externos são construções poderosas que permitem que o desenvolvedor de AQL exponha pontos de customização em um módulo compilado.

Os dicionários podem ser criados por meio de três origens:

  • Arquivos de dicionário
  • Declarações de dicionário sequencial
  • As tabelas que são criadas com a instrução create table e a instrução create external table.

Sintaxe

A instrução create dictionary interna tem três formas sintáticas, from file, from table e um formato sequencial.

  • dicionário interno

    Do arquivo:

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

    Por meio da tabela:

    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 sequencial

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

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

Descrição

  • <dictionary name\>

    Especifica um nome para o novo dicionário interno ou externo. Pode ser um identificador simples ou identificador com aspas duplas.

  • '<file name\>'

    Especifica o nome do arquivo que contém entradas de dicionário. Os arquivos de dicionário são arquivos de texto delimitados por retorno de linha com uma entrada de dicionário por linha. As entradas em um arquivo de dicionário podem consistir em múltiplos tokens.

  • <table name\>

    Especifica o nome da tabela por meio da qual incluir entradas de dicionário. Os dicionários não podem ser criados por meio de uma tabela que é importada de outro módulo.

  • <column name\>

    Especifica o nome da coluna na tabela por meio da qual incluir entradas de dicionário.

  • required [true|false]

    Especifica se o conteúdo externo para o dicionário externo é necessário para executar o módulo.

    • true

      Se a cláusula for required true, você deve fornecer um URI para a localização do arquivo que contém o conteúdo externo. O arquivo especificado deve possuir conteúdo. Se o URI não for fornecido ou se o arquivo não contiver conteúdo, o componente de tempo de execução emitirá uma exceção.

    • false

      Se a cláusula for required false, o módulo poderá ser executado com sucesso mesmo se um URI para o conteúdo externo não for fornecido para esse dicionário. Se um URI não for fornecido, o componente de tempo de execução o tratará como um dicionário vazio.

    O uso de create external dictionary <dictionary-name\> allow_empty agora está descontinuado e resulta em um aviso do compilador.

  • '<language code(s)\>'

    Especifica uma lista delimitada por vírgulas de códigos de idioma de duas letras, como en (inglês) ou zh (chinês) para os idiomas ou para os idiomas de documentos para dicionários externos, nos quais avaliar o dicionário. O dicionário não produz resultados em documentos cujo código de idioma não está contido nessa sequência.

    Se o parâmetro de idioma for omitido, o idioma de dicionário será padronizado para um dos conjuntos de idiomas a seguir:

    • Os conjuntos de idiomas que são especificados por meio da instrução set default language, se ela for declarada, no módulo de contenção.
    • Os conjuntos de idiomas que contêm alemão (de), espanhol (es), inglês (en), francês (fr), italiano (it) e o idioma não especificado (x_unspecified).
  • lemma_match

    Use a lematização para localizar correspondências para palavras semelhantes a um termo de dicionário em seus documentos.

    Lemmatização é o processo de determinação da lima para uma determinada palavra. Um lema é uma palavra que pode ser usada como uma correspondência para um único termo determinado. Por exemplo, o termo "go" pode ser correspondido aos termos "goes", "indo", "gone", ou "went". Esse processo envolve tarefas complexas, como entender o contexto e determinar a parte do discurso de uma palavra em uma sentença. A lematização está disponível para todos os idiomas para os quais o tokenizer IBM Multilingual fornece suporte de parte do discurso.

    A correspondência de lema é executada somente para dicionários declarados com a cláusula lemma match.

    A semântica para extração de dicionário com a cláusula lemma_match é a seguinte:

    • A forma lematizada para cada token do documento de entrada é computado.
    • O dicionário é avaliado com relação ao documento lematizado. Não é possível usar a opção lemma_match com a opção case exact. Se ambas forem usadas, um erro do compilador será retornado.
  • case (exact | insensitive)

    Especifica o tipo de conversão, em letras maiúsculas, que o dicionário executa quando ele determina se uma região específica do documento corresponde.

    • exact

      Especifica uma correspondência exata com distinção entre maiúsculas e minúsculas.

    • insensitive

      Especifica uma correspondência sem distinção entre maiúsculas e minúsculas. Esta opção é o valor padrão.

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

    Especifica as sequências que você deseja incluir no dicionário sequencial. As entradas em um dicionário sequencial podem consistir em um ou mais tokens.

Observações de uso

  • Os formatos from file e from table são recomendados, especialmente quando você prevê a modificação das entradas ou quando há muitas entradas. Usando esses formatos, é possível modificar os conteúdos do dicionário sem modificar o código.

  • Quando a instrução create dictionary é processada pelo compilador modular AQL, as referências a locais do arquivo de dicionário especificadas na sintaxe create dictionary ... from file devem ser relativas à raiz do módulo no qual esta instrução create dictionary é emitida.

  • É possível especificar comentários em um arquivo de dicionário, precedendo o comentário com o caractere #. Os comentários podem começar em qualquer lugar em uma linha.

  • Para especificar comentários que abrangem diversas linhas, deve-se preceder cada linha com o caractere de comentário. Se o caractere de comentário fizer parte de uma entrada de dicionário, ele deverá ser escapado usando o caractere de barra invernada (\), como em \#. Se o caractere de barra invertida fizer parte da entrada do dicionário, ele deverá ser escapado consigo mesmo, como em \\.

  • Para os dicionários externos, quando os módulos estão sendo carregados, você deve especificar uma lista de URIs para dicionários externos, conforme requerido pelos módulos que estão sendo carregados.

  • Lematização de dicionários: a diferença primária entre a semântica correspondente do dicionário existente e a semântica lematizada é que a correspondência é executada com relação à forma lematizada do documento, em vez da forma original do documento.

    As entradas de dicionário pertencentes a um dicionário com a correspondência de lema ativada têm estes pré-requisitos:

    • Uma entrada de dicionário pode conter um ou mais tokens, em que cada token de entrada é um lema. Para criar um dicionário de lemas, é possível usar a função escalar [GetLemma.
    • Os tokens de uma entrada de dicionário devem ser separados por um espaço em branco. Se o token consistir em espaços em branco, eles deverão ser escapados usando o caractere de barra invertida (\).
  • A tabela a seguir mostra as diferenças entre a instrução create external dictionary e a instrução create dictionary:

create external dictionary create dictionary
  • Define um item temporário para um dicionário cujo conteúdo é fornecido no tempo de inicialização.
  • Requer que o conteúdo do dicionário esteja disponível no tempo de compilação.
  • Serializado na representação compilada (.tam) de um módulo.

Exemplos

Exemplo 1: criando um dicionário externo

O dicionário externo, PersonPositiveClues, espera ser preenchido com valores de um arquivo externo no tempo de carregamento. Ele também espera ser correspondido contra algumas línguas ocidentais conforme especificado por suas bandeiras.

module PersonModuleEnglish;

create external dictionary PersonPositiveClues
  allow_empty false
  with case exact;

export dictionary PersonPositiveClues;

Exemplo 2: lematização

Considere um dicionário que tenha a correspondência de lema ativada e contenha duas entradas: go shop e went shopping. O documento contém o texto Anna went shopping. A forma lematizada do documento de entrada é Anna go shop. A correspondência de lema retorna went shopping como uma correspondência para a entrada go shop. O texto do documento original não é comparado com as entradas de dicionário, somente o texto do documento lematizado. Portanto, não existe nenhuma correspondência no documento para a entrada went shopping.

Documentando as instruções create dictionary e create external dictionary com o AQL Doc

O comentário do AQL Doc para uma instrução create dictionary contém as seguintes informações:

Descrição geral sobre o dicionário.

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

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

O comentário do AQL Doc para uma instrução create external dictionary contém a descrição geral sobre o dicionário que é criado. A sequência a seguir ilustra o formato:

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

A instrução create table

A instrução create table cria uma tabela AQL.

A instrução create table em AQL é usada para definir tabelas de consulta estática para aumentar as anotações com mais informações.

Sintaxe

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

Descrição

  • <table name\>

    Especifica o nome da tabela a ser criada. O <table name\> pode ser um identificador simples ou um identificador entre aspas duplas.

  • <colname\>

    Especifica o nome da coluna a ser criada.

  • <type\>

    Especifica o tipo de dados AQL para a coluna associada. Todas as colunas devem ser do tipo Text, Integer, Float ou Boolean.

  • <value\>

    Especifica as tuplas a serem preenchidas na tabela criada.

Exemplos

Exemplo 1: criando uma tabela de nomes de empresas

Neste exemplo, a instrução create table inclui mais metadados de local para as anotações de nome 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;

Documentando a instrução create table com o AQL Doc

O comentário do AQL Doc para uma instrução create table contém as seguintes informações:

  • Descrição geral sobre a tabela.
  • @field para cada nome de coluna no esquema desta tabela.
/** 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');

A instrução create external table

É possível usar a instrução create external table para especificar uma tabela com conteúdo estabelecido quando um módulo compilado é executado em todos os documentos de entrada. Você fornece o conteúdo da tabela durante o tempo de carregamento em vez de no código AQL de origem e não precisa recompilar o módulo.

As tabelas externas são construções poderosas que permitem que o desenvolvedor de AQL exponha pontos de customização em um módulo compilado.

Sintaxe

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

Descrição

  • <table-name\>

    Especifica o nome da tabela externa a ser criada. O <table-name\> pode ser um identificador simples ou um identificador entre aspas duplas.

  • <colname\>

    Especifica o nome da coluna a ser criada.

  • <type\>

    Especifica o tipo de dados AQL para a coluna associada. Todas as colunas devem ser do tipo Text, Integer, Float ou Boolean.

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

    Especifica colunas adicionais e objetos AQL a serem usados na tabela externa.

  • allow_empty [true|false]

    Especifica o valor para a cláusula allow_empty.

    • true

      Se a cláusula for allow_empty true, o módulo pode ser executado com sucesso mesmo se um URI para o conteúdo externo não for fornecido para esta tabela. Se o URI não for fornecido, o componente de tempo de execução o tratará como uma tabela vazia.

    • false

      Se a cláusula for allow_empty false, será preciso fornecer um URI para o local do arquivo que tem o conteúdo externo. O arquivo especificado deve possuir conteúdo. Se o URI não for fornecido ou se o arquivo não contiver conteúdo, o componente de tempo de execução emitirá uma exceção.

Observações de uso

  • A representação compilada do módulo contém metadados sobre os objetos externos (visualizações, dicionários e tabelas) definidos pelo módulo.
  • Quando os módulos estão sendo carregados, deve-se especificar uma lista de URIs para tabelas externas, conforme necessário para os módulos sendo carregados.
  • O formato suportado para o conteúdo de uma tabela externa é um arquivo CSV (.csv) com cabeçalho.

A tabela a seguir mostra as diferenças entre a instrução create external table e a instrução create table:

create external table create table
  • Define um item temporário para uma tabela cujo conteúdo é fornecido no tempo de inicialização.
  • Requer que o conteúdo da tabela esteja disponível em tempo de compilação.
  • Serializado na representação compilada (.tam) de um módulo.

Exemplos

Exemplo 1: criando uma tabela externa que é preenchida no tempo de carregamento

A tabela externa, PersonNegativeClues, espera ser preenchida no tempo de carregamento por causa da sinalização, allow_empty false.

module PersonModuleFrench;

create external table PersonNegativeClues (name Text)
  allow_empty false;

export table PersonNegativeClues;

Exemplo 2: criando um dicionário com uma tabela externa

Os dicionários também podem ser criados por meio de tabelas externas, de forma semelhante aos criados por meio de tabelas sequenciais que são declaradas com a instrução 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;

Documentando a instrução create external table com o AQL Doc

O comentário do AQL Doc para uma instrução create external table contém as seguintes informações:

  • Descrição geral sobre a tabela.
  • @field para cada nome de coluna no esquema desta tabela.
/** 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;

A instrução create external view

A instrução create external view no AQL permite a especificação de mais metadados sobre um documento como uma nova visualização, além da visualização Document predefinida que mantém o conteúdo textual e de rótulo.

Sintaxe

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

Descrição

  • <view_name\>

    Especifica o nome interno da visualização externa. A visualização externa é referida por este nome nas regras AQL. Um <view_name\> pode ser um identificador simples ou um identificador entre aspas. Um <view_name\> não pode conter o caractere de ponto.

  • <colname\>

    Especifica o nome da coluna a ser definida na visualização externa.

  • <type\>

    Especifica o tipo de dados para a coluna associada. Os tipos de dados que são suportados para colunas de visualização externa são Text, Span, Integer e Float.

  • '<view_external_name\>'

    Especifica o nome externo da visualização externa. Os sistemas externos que preenchem as tuplas na visualização externa referem-se à visualização externa pelo nome externo. O '<view_external_name\>' deve ser uma constante do tipo Sequência de caracteres envolta em aspas simples ('ExternalName').

Exemplos

Para ilustrar visualizações externas, considere um aplicativo de exemplo que requer que você identifique os nomes de pessoas em e-mails.

Exemplo 1: identificando os nomes de pessoas em e-mails

Suponha que o texto de um e-mail seja "Ena, envie-me o documento ASAP". Embora um humano possa entender que Ena é um nome de uma pessoa com base no texto do e-mail, as regras de AQL escritas para identificar nomes de pessoas com alta precisão de texto geral podem ser muito conservadoras e incapazes de tirar a mesma conclusão com alta confiança, com base no fato de que Ena é uma palavra capitalizada.

Uma maneira de impulsionar a cobertura das regras é usar palavras dos campos From, To e CC do e-mail como mais evidências.

Se o e-mail for endereçado a "Ena Smith" e o aplicativo disponibilizar essas informações para o extrator, o desenvolvedor do extrator poderá gravar mais regras de AQL para impulsionar a cobertura do extrator que é baseada no conhecimento de domínio de que os e-mails geralmente são endereçados a pessoas.

Por exemplo, é possível escrever regras de AQL para identificar tokens de pessoas por meio dos campos de metadados de e-mail. Você então usa essa informação como pistas fortes quando você decide se um token capitalizado no texto do e-mail é um nome de pessoa. Em geral, os metadados de e-mail não fazem parte do e-mail real, mas o aplicativo pode disponibilizar esses metadados para o extrator usando uma visualização externa.

Para cada e-mail que deve ser processado, o aplicativo pode transmitir o texto do e-mail como texto do documento (para preencher a visualização Document) no tempo de execução. Ele também pode passar os metadados extras usando uma visualização externa adequadamente definida.

A instrução a seguir define uma visualização externa que é nomeada EmailMetadata. A visualização externa possui um esquema que contém três campos do tipo Texto. No tempo de execução, a visualização EmailMetadata é preenchida automaticamente por meio de um tipo externo denominado EmailMetadataSrc. Em seguida, é possível referenciar a visualização EmailMetadata em suas regras de AQL, de forma semelhante a como você referenciaria qualquer outra visualização.

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

Documentando a instrução create external view com o AQL Doc

O comentário do AQL Doc para uma instrução create external view contém as seguintes informações:

  • Descrição geral sobre a visualização.
  • @field para cada nome de coluna na visualização.
/**
* 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 arquivo para artefatos externos

Três tipos de artefatos externos são suportados: visualizações externas, dicionários externos e tabelas externas.

Dicionário externo

O formato para o arquivo que contém entradas para um dicionário externo é definido aqui:

  • Arquivo de texto delimitado por retorno de linha.
  • Uma entrada de dicionário por linha.
  • A extensão de arquivo recomendada é .dict, mas outras extensões de arquivo podem ser suportadas.
  • As entradas no dicionário podem consistir em múltiplos tokens.
  • Os comentários podem ser especificados precedendo o conteúdo do comentário com o caractere, #.
  • Os comentários podem começar em qualquer lugar em uma linha.
  • Os comentários de multilinhas devem conter o caractere # no início de cada linha.
  • As entradas de dicionário poderão conter caracteres de comentário, se cada caractere de comentário for escapado com um caractere de barra invertida. Por exemplo, \#.

Tabela externa

O formato de arquivo suportado para o conteúdo de uma tabela externa é um arquivo .csv com cabeçalho.

O exemplo a seguir mostra uma instrução create external table e o arquivo .csv que especifica o conteúdo dessa tabela externa.

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

A primeira linha do arquivo .csv contém o cabeçalho. As linhas restantes contêm os dados.

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

Visualização externa

O conteúdo de visualizações externas pode ser especificado das maneiras a seguir:

  • Quando você executa um extrator, você pode especificar conteúdo de visualização externa para uma coleta de dados apenas quando estiver usando o formato de entrada JSON.

Funções integradas

A AQL possui uma coleção de funções integradas para uso em regras de extração.

  • Funções agregadas As funções agregadas são usadas para implementar operações (como contagem, operações matemáticas e outras) em um conjunto de valores de entrada. Essas funções retornam apenas um resultado.
  • Funções de predicado As funções de predicado testam um determinado predicado sobre seus argumentos de entrada e retornam um valor booleano correspondente.
  • Funções escalares As funções escalares executam uma operação sobre os valores de um campo em um conjunto de tuplas de entrada e retornam um valor não booleano, como um Período, um Texto ou um Número inteiro. Essas funções podem ser usadas dentro da lista select de uma instrução select ou de uma instrução extract. Elas também podem ser usadas como entradas para funções de predicado.

Funções agregadas

As funções agregadas são usadas para implementar operações (como contagem, operações matemáticas e outras) em um conjunto de valores de entrada. Essas funções retornam apenas um resultado.

Essas funções podem ser usadas dentro da lista select de uma instrução select, mas não dentro de uma instrução extract.

O exemplo a seguir é a forma geral de uma chamada de função agregada:

Aggregate_Function_Name(argument)

O argument pode ser:

  • Uma expressão que consiste em uma coluna de uma visualização na cláusula from ou uma combinação de funções escalares que envolvem colunas das visualizações na cláusula from.

    Na maioria dos casos, exceto conforme indicado, os valores nulos para o argumento são ignorados.

  • O caractere * no caso especial da função agregada Count(*).

    Nesse caso, todas as linhas da saída são contadas, incluindo valores nulos.

Função agregada Tipo de argumento Tipo de retorno Valor de retorno
Avg(expression) Integer, Float Valor flutuante A média de todos os valores de entrada ou nulos, se nenhuma linha for selecionada
Count(*) Integer O número de todas as linhas de entrada
Count(expression) Qualquer Integer O número de todos os valores de entrada não nulos
List(expression) Integer, Float, Text, Span Lista de valores escalares do mesmo tipo que o argumento de entrada Uma lista não ordenada de valores de entrada não nulos: um pacote, não um conjunto, portanto, pode conter duplicatas. Uma lista vazia se somente valores nulos forem selecionados
Max(expression) Integer, Float, Text, Span O mesmo que o tipo de argumento O elemento máximo em todos os valores de entrada ou null se nenhuma linha for selecionada
Min(expression) Integer, Float, Text, Span O mesmo que o tipo de argumento O elemento mínimo em todos os valores de entrada ou nulos, se nenhuma linha for selecionada
Sum(expression) Integer, Float O mesmo que o tipo de argumento A soma de todos os valores de entrada ou nulos, se nenhuma linha for selecionada

Limitações da versão atual:

A versão atual de AQL suporta a criação de valores escalares por meio da Lista de funções aggregate.

Exemplos

O exemplo a seguir ilustra como as funções agregadas podem contar o número de anotações de nome de pessoa ou calcular conjuntos de nomes associados a cada sobrenome distinto identificado em um 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);

O exemplo a seguir ilustra o uso das funções Min e 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;

Funções de predicado

As funções de predicado testam um determinado predicado sobre seus argumentos de entrada e retornam um valor booleano correspondente.

Os argumentos de entrada para prever funções incluem valores de retorno de outras funções escalares ou agregadas, além de dicionários, expressões regulares e muito mais. Essas funções podem ser empregadas dentro da cláusula where de uma instrução select e a cláusula having de uma instrução extract.

E

A função And aceita um número variável de argumentos booleanos e retorna os resultados de uma operação lógica AND em todos os argumentos de entrada.

O otimizador de AQL não tenta otimizar a ordem de avaliação dos argumentos para essa função como parte da operação lógica AND. Se qualquer entrada for null, o resultado será null.

Considere este formato de consulta:

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

Como resultado, um formato de consulta que usa a operação AND frequentemente é executado consideravelmente mais lento do que a mesma consulta na forma de:

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

Quando possível, use o estilo SQL e a palavra-chave em vez dessa função.

Contém

A função Contains usa dois spans como argumentos:

Contains(<span1>, <span2>)

Esta função retorna TRUE se span1 completamente contém span2. Se span2 iniciar em ou após o início de span1 e terminar em ou antes do término de span1, o span2 estará completamente contido. Se qualquer argumento for null, a função retornará null.

ContainsDict

A função ContainsDict verifica se o texto de um span contém qualquer entrada de um determinado dicionário. Essa função aceita como argumentos de entrada um dicionário, uma especificação de sinalização opcional e um span para avaliar.

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

A função ContainsDict retornará TRUE se o span contiver uma ou mais correspondências do dicionário. As sinalizações podem ser Exact ou IgnoreCase.

  • Se Exact for usado, uma correspondência com distinção entre maiúsculas e minúsculas será executada com relação a cada termo no dicionário.
  • Se IgnoreCase for usado, a correspondência que é executada com relação a cada termo no dicionário não fará distinção entre maiúsculas e minúsculas.
  • Se nenhuma sinalização for especificada, a correspondência do dicionário se baseará em qualquer sinalização especificada durante sua criação. Se nenhuma sinalização tiver sido especificada durante a criação, ela corresponderá usando a sinalização IgnoreCase.

Se o span for null, a função retornará null.

O exemplo a seguir ilustra o uso da função 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);

Os dicionários são sempre avaliados em limites de token. Por exemplo, se um dicionário consistir no termo peixe, nenhuma correspondência existirá no texto Vamos pescar.

ContainsDicts

A função ContainsDicts verifica se o texto de uma span contém qualquer entrada de quaisquer dicionários fornecidos. Essa função aceita como argumentos de entrada dois ou mais dicionários, uma especificação de sinalização opcional e um span para avaliar.

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

A função ContainsDicts retornará TRUE se o span contiver uma ou mais correspondências de pelo menos um dos dicionários especificados. As sinalizações podem ser Exact ou IgnoreCase.

  • Se Exact for usado, uma correspondência com distinção entre maiúsculas e minúsculas será executada com relação a cada um dos termos nos dicionários.
  • Se IgnoreCase for usado, a correspondência executada com relação a cada um dos termos nos dicionários será sem distinção entre maiúsculas e minúsculas.
  • Se nenhuma sinalização for especificada, a correspondência do dicionário se baseará em qualquer sinalização especificada durante sua criação. Se nenhuma sinalização tiver sido especificada durante a criação, ela corresponderá usando a sinalização IgnoreCase.

Se um ou ambos os argumentos forem nulos, a função retornará null.

O exemplo a seguir ilustra o uso da função ContainsDicts com a sinalização 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

A função ContainsRegex verifica se o texto de um span corresponde a uma determinada expressão regular. Essa função aceita uma expressão regular com a qual corresponder, uma especificação de sinalização opcional e o span de entrada com relação com o qual corresponder.

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

A função retornará TRUE se o texto do span, que é usado como uma sequência Java™ separada, contiver uma ou mais correspondências da expressão regular. A função retornará null se o span for null. As sinalizações opcionais afetam o comportamento de correspondência, de forma semelhante a sinalizações usadas em expressões regulares Java.

A sequência de sinalizações é formada combinando uma ou mais das sinalizações a seguir usando | como o separador:

  • CANON_EQ
  • CASE_INSENSITIVE
  • DOTALL
  • LITERAL
  • MULTILINHAS
  • UNICODE (sem sentido sem CASE_INSENSITIVE)
  • UNIX_LINES

Um exemplo de uma sequência de sinalizações é

'UNICODE | CASE_INSENSITIVE'

Considere este exemplo em que ContainsRegex identifica nomes de produtos juntamente com suas menções de número de versão em ambos os lados. Ao contrário do exemplo para o MatchesRegex, uma correspondência de número de versão não é estritamente identificada usando-se o regex, mas pelo contexto em torno de uma menção de nome do produto contendo um token que corresponde contra o 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 a

A função Equals usa dois argumentos de tipo arbitrário:

Equals(<arg1>, <arg2>)

Dois spans serão considerados iguais se ambos iniciarem e terminarem nos mesmos deslocamentos e contiverem o mesmo texto. Se um ou ambos os argumentos forem nulos, a função retornará null.

O exemplo a seguir ilustra o uso da função 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));

Segue

A função predicado Follows leva dois argumentos de span e dois argumentos inteiros:

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

A função retornará TRUE se o número de caracteres entre o término de span1 e o início de span2 estiver entre minchar e maxchar, inclusive. Se qualquer argumento for null, a função retornará null.

FollowsTok

A função de predicado FollowsTok é uma versão de Follows; no entanto, os argumentos de distância FollowsTok são em termos de tokens em vez de caracteres:

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

A função FollowsTok retorna TRUE se o número de tokens entre o final de span1 e o início de span2 está entre mintok e maxtok, inclusive. Se qualquer argumento for null, a função retornará null.

GreaterThan

A função de predicado GreaterThan usa dois argumentos de tipo arbitrário:

GreaterThan(<arg1>, <arg2>)

A função retorna TRUE se <arg1> é maior que <arg2>. A função retornará FALSE se um dos argumentos for null.

IsNull

A função IsNull testa se os dados são, ou não, nulos. Ela usará um único argumento de qualquer tipo e retornará TRUE se o argumento único for null; caso contrário, FALSE. O comportamento desse predicado e o predicado NotNull já definido é diferente de todos os outros predicados que retornam nulo na entrada nula.

MatchesDict

A função MatchesDict usa um dicionário (como em uma extração de dicionário), uma especificação de sinalização opcional e um período como argumentos:

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

A função MatchesDict retornará TRUE se o span corresponder exatamente a um ou mais dos termos no dicionário. As sinalizações podem ser Exact ou IgnoreCase.

  • Se Exact for usado, uma correspondência com distinção entre maiúsculas e minúsculas será executada com relação a cada termo no dicionário.
  • Se IgnoreCase for usado, a correspondência que é executada com relação a cada termo no dicionário não fará distinção entre maiúsculas e minúsculas.
  • Se nenhuma sinalização for especificada, a correspondência do dicionário se baseará em qualquer sinalização especificada durante sua criação. Se nenhuma sinalização tiver sido especificada durante a criação, ela corresponderá usando a sinalização IgnoreCase.

Se qualquer argumento for null, a função retornará null.

Os dicionários são sempre avaliados em limites de token. Por exemplo, se um dicionário consistir no termo peixe, nenhuma correspondência existirá no texto Vamos pescar.

MatchesRegex

A função MatchesRegex tem uma sintaxe semelhante a ContainsRegex. Ao contrário da função ContainsRegex, a função MatchesRegex retornará TRUE apenas se o texto inteiro do período, usado como uma sequência Java separada, corresponder à expressão regular. Se qualquer argumento for null, a função retornará null. As sinalizações opcionais afetam o comportamento de correspondência semelhante a sinalizações usadas em expressões regulares Java.

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

A sequência de sinalizações é formada combinando um subconjunto dessas sinalizações usando | como o separador:

  • CANON_EQ
  • CASE_INSENSITIVE
  • DOTALL
  • LITERAL
  • MULTILINHAS
  • UNICODE (sem sentido sem CASE_INSENSITIVE)
  • UNIX_LINES

Um exemplo de uma sequência de sinalizações é

'UNICODE | CASE_INSENSITIVE'

Considere este exemplo em que MatchesRegex é usado para identificar nomes de produtos juntamente com suas menções de número de versão à direita. Ao contrário do exemplo na seção ContainsRegex, o número da versão exata é identificado como o token imediatamente seguinte à menção do nome do produto.

-- 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);

Not

A função Not usa um único argumento Boolean e retorna seu complemento. Se o argumento for null, a função retornará null.

NotNull

A função NotNull leva um único argumento de qualquer tipo.

Como seu nome sugere, a função NotNull retornará TRUE se o valor do argumento não for null e FALSE se o argumento for null.

Ou

A função Or usa um número variável de argumentos Boolean não nulos. Se qualquer argumento for null, a função retornará null.

A função Or retornará TRUE se qualquer uma delas for avaliada como TRUE.

Overlaps

A função Overlaps usa dois argumentos de span:

Overlaps(<span1>, <span2>)

A função retornará TRUE se os dois spans de entrada se sobrepuserem no texto do documento. A função retornará null se o argumento for null.

Funções escalares

Funções escalares executam uma operação sobre os valores de um campo por meio de um conjunto de tuplas de entrada e retornam um valor não booleano, como um Span, Text ou Integer. Essas funções podem ser usadas dentro da lista select de uma instrução select ou de uma instrução extract. Elas também podem ser usadas como entradas para funções de predicado.

Se um objeto Text for fornecido onde um objeto Span é necessário, um objeto Span convertido será automaticamente gerado, o qual é baseado nesse objeto Text, com deslocamentos iniciais e finais cobrindo todo o comprimento do objeto Text.

Se um objeto Span for fornecido onde um objeto Text é necessário, um objeto Text convertido será automaticamente gerado por meio do valor de texto do objeto Span.

Chomp

A função Chomp é semelhante ao operador Chomp em Perl, exceto que Chomp opera sobre spans em vez de sequências:

Chomp(<span1>)

O exemplo a seguir ilustra o uso da função 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;

Se o span de entrada contiver algum espaço em branco no início ou no término, a função Chomp reduzirá o span suficientemente para remover o espaço em branco. Em seguida, a função retornará um novo span sem nenhum espaço em branco à esquerda ou à direita. Se o span de entrada não tiver um espaço em branco à esquerda ou à direita, a função Chomp retornará o mesmo span. Se o span de entrada for null, o Chomp retornará null.

CombineSpans

A função CombineSpans usará dois spans como entrada e retornará o span mais curto que cobre completamente ambos os spans de entrada se os spans forem baseados no mesmo objeto de texto.

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

A função CombineSpans é sensível à ordem de seus spans de entrada, a menos que você use o parâmetro IgnoreOrder. Quando o parâmetro IgnoreOrder opcional é usado, a ordem dos dois spans é ignorada.

O exemplo a seguir ilustra o uso da função 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);

A semântica da função é a seguinte:

  • Se span1 ou span2 for null, ou as duas spans estiverem sobre diferentes objetos Texto, a função retornará null.
  • Caso contrário, se span1 for menor que span2 ou o parâmetro IgnoreOrder for usado, a função retornará o span mais curto que cobre span1 e span2.
  • Caso contrário (span1 é maior que span2 e IgnoreOrder não é usado), a função retornará um erro de tempo de execução.

Com base na definição de Span, os diferentes cenários de argumentos para a função CombineSpans são conforme a seguir:

  • O intervalo 2 é sempre após o intervalo 1. Em outras palavras, a ordem da esquerda para a direita é mantida:

    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]
    
  • O intervalo 2 não é após o intervalo 1. Em outras palavras, a ordem da esquerda para a direita não é mantida:

    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 e GetEnd

A função GetBegin usa um único argumento de span e retorna o deslocamento de início do span de entrada.

Por exemplo,

GetBegin([5, 10])

retorna o valor 5.

Da mesma forma, a função GetEnd retorna o deslocamento final de seu span de entrada.

O exemplo a seguir ilustra o uso das funções GetBegin e GetEnd.

create view PersonOffsets as
select GetBegin(P.name) as offsetBegin, GetEnd(P.name) as offsetEnd
from Person P;

Para ambas as funções, se o argumento for null, a função retornará null.

GetLanguage

A função GetLanguage usa um único argumento de span e retorna o código de idioma com duas letras do texto de origem do span. Se o argumento for null, a função retornará null.

Essa instrução produzirá resultados significativos somente se a origem de dados estiver identificando campos de texto com os idiomas apropriados.

GetLemma

A função GetLemma usa um único objeto Span ou Text como um argumento e retorna uma sequência que contém a forma lematizada do span de entrada. Se o argumento for null, a função retornará null. Com entradas do dicionário para correspondência de lema, essa função pode determinar a forma lematizada de vários tokens conforme retornada pelo tokenizer. Por exemplo, para o span went shopping, GetLemma retornará a sequência de lema go shop.

Os resultados dessa função seguem estas regras:

  • Se o intervalo de entrada começar no início de um token e terminar no final de um token, o resultado conterá a sequência de lemas que começa com o lema do primeiro token, seguida por um espaço em branco, pelo lema do segundo token, por um espaço em branco e assim por diante (por exemplo, cachorro cato peixe pássaro...). Se o lema para um token consistir em espaços em branco, escape o espaço em branco usando o caractere de barra invertida (\).
  • Se o período da entrada começar ou terminar com espaço em branco (por exemplo, ele começa entre dois tokens ou termina entre dois tokens), a função ignorará o espaço em branco inicial e final.
  • Se o período da entrada começar no meio de um token ou terminar no meio de um token, a saída consistirá no conteúdo a seguir, nesta ordem, e separada por um espaço em branco:
    • A forma superficial do primeiro token parcial, se ele existir.
    • A sequência de lemmas que correspondem ao primeiro a últimos tokens completos. Se o lema de qualquer um dos tokens completos consistir em espaços em branco, escape-os usando o caractere de barra invertida (\).
    • A forma superficial do último token parcial, se ele existir.

Essa função retorna um erro se o tokenizer que estiver sendo usado não for capaz de produzir lemas.

É possível usar a função GetLemma() para criar dicionários de formas lematizadas. Chame GetLemma() em uma entrada que contém os termos cuja forma lematizada você deseja incluir no dicionário.

GetLength

A função GetLength usa um único argumento de span e retorna o comprimento do span de entrada. Se o argumento for null, a função retornará null.

Por exemplo,

GetLength([5, 12])

retorna um valor de 7.

GetLengthTok

A função GetLengthTok usa um único argumento de span e retorna o comprimento do span de entrada em tokens. Se o argumento de entrada for null, a função retornará null.

GetString

A função GetString usa um único objeto AQL como seu argumento e retorna um objeto de Texto formado da representação de sequência do objeto.

Para argumentos de período e de texto, os valores retornados são diferentes dos retornados por GetText(). Para objetos de Texto, o valor retornado inclui aspas simples em torno da sequência de texto. Para objetos de span, o valor retornado incluirá, além disso, deslocamentos entre parênteses.

Para listas escalares, essa função retorna os valores de GetString() dos elementos da lista, concatenados com pontos e vírgulas. Para argumentos Integer, Float, Boolean e String, essa função retorna o valor do argumento como uma sequência. Para argumentos null, essa função retorna null.

GetText

A função GetText usa um único span ou texto como um argumento. Para entrada de span, ela retorna o objeto de texto com base na sequência de texto real que o span marca. Para entrada de texto, ele retorna o objeto de texto de entrada. Se a entrada for null, essa função retornará null. Por exemplo:

GetText([5, 12])

O span retorna a subsequência do documento da posição de caractere 5 - 12.

A função GetText tem dois usos primários.

Teste para igualdade de sequência entre o texto marcado por dois spans.

-- 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;

Dividindo um documento em subdocumentos menores.

Por exemplo, se o documento principal for um blog que consiste em múltiplas entradas de blog, será possível usar o GetText para criar um 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 e RightContext

A função LeftContext leva um Span e um Integer como entrada:

LeftContext(<input span>, <nchars>)

A função LeftContext(<input span\>, <nchars\>) retorna um novo intervalo que contém os caracteres nchars do documento imediatamente à esquerda de <input span\>. Se o intervalo de entrada começar menos de <nchars\> caracteres do início do documento, LeftContext() retornará um intervalo que começa no início do documento e que continua até o início do intervalo de entrada.

Por exemplo, LeftContext([20, 30], 10) retorna o período [10, 20]. O período LeftContext([5, 10], 10) retorna [0, 5].

Se a entrada começar no primeiro caractere do documento, LeftContext() retornará um período de comprimento zero. Da mesma forma, a função RightContext retorna o texto à direita de seu span de entrada. Para ambas as funções, se qualquer um dos argumentos for null, a função retornará null.

LeftContextTok e RightContextTok

As funções LeftContextTok e RightContextTok são versões de LeftContext e RightContext que tiram distâncias em termos de tokens:

LeftContextTok(<input span>, <num tokens>)
RightContextTok(<input span>, <num tokens>)

O exemplo a seguir ilustra o uso da função 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 as funções, se qualquer um dos argumentos for null, a função retornará null.

Remap

A função Remap usa um único argumento de span:

Remap(<span>)

Se o span de entrada estiver sobre um objeto de texto que foi produzido transformando outro objeto de texto, a função Remap converterá o span em um span sobre o texto de "origem" original.

Por exemplo, se o span N.name estiver sobre um documento com tag removida que é produzido executando HTML por meio da instrução AQL detag, então

Remap(<N.name>)

retornará um span equivalente sobre o HTML original.

Se o argumento de período tiver sido produzido executando a instrução detag em um documento vazio, a função remapeará os períodos para o início do documento (ou seja, Document.text[0-0]). Além disso, se a instrução detag produzir uma sequência vazia, a função remapeará os spans para o início do documento. A única parte de AQL que produz tal objeto de texto derivado é a instrução detag.

O exemplo a seguir ilustra o uso da função 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;

Se o argumento para Remap não for um objeto de texto derivado ou um span sobre um objeto de texto derivado, a função gerará um erro. Se o argumento for null, a função retornará null.

SpanBetween

A função SpanBetween leva duas spans como entrada e retorna a span que exatamente cobre o texto entre as duas spans se os spans se baseiam no mesmo objeto de texto, e retorna null se eles forem baseados em diferentes objetos de texto:

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

Quando o parâmetro IgnoreOrder opcional é usado, a ordem dos dois spans é ignorada pelo compilador de AQL.

Se não houver texto entre os dois intervalos, SpanBetween retornará um intervalo vazio que começa no final de <span1>.

Assim como CombineSpans,  SpanBetween reconhece à ordem de suas entradas, a menos que você use o parâmetro IgnoreOrder. Portanto,

SpanBetween([5, 10], [50, 60])

retorna o span [10, 50], enquanto

SpanBetween([50, 60], [5, 10])

retorna o span [60, 60].

Se o argumento para SpanBetween for null, a função retornará null.

SpanIntersection

A função SpanIntersection usará dois spans como entrada e retornará um span que cobre o texto que ambas as entradas cobrirão se os spans forem baseados no mesmo objeto de texto e retornará null se eles forem baseados em diferentes objetos de texto:

SpanIntersection(<span1>, <span2>)

Por exemplo,

SpanIntersection([5, 20], [10, 60])

retorna o span [10, 20], enquanto

SpanIntersection([5, 20], [7, 10])

retorna o span [7, 10].

Se os dois spans não se sobrepuserem, o SpanIntersection retornará null. Se uma das entradas de span for null, a função retornará null.

SubSpanTok

A função SubSpanTok usa como entrada um span e um par de deslocamentos para o span:

SubSpanTok(<span>, <first_tok>, <last_tok>)

Como o nome da função sugere, os argumentos <first_tok> e <last_tok> são distâncias em tokens, de acordo com o que o tokenizer do sistema estiver configurado para usar.

A função SubSpanTok retorna um novo span que cobre o intervalo indicado de tokens, inclusive, dentro do span de entrada. Se o intervalo especificado iniciar dentro do span e for além do término do span, a parte do intervalo que estiver contida será retornada. Se o <first_tok> representar uma distância além do intervalo de destino, SubSpanTok retornará um intervalo de comprimento zero que começa no início do intervalo de entrada.

Se qualquer entrada for null, a função retornará null.

ToLowerCase

A função ToLowerCase leva um único objeto como seu argumento e retorna uma representação de cadeia minússola do objeto. A conversão em uma sequência ocorre da mesma maneira que a função GetString() executa a conversão.

O uso primário dessa função é executar junções de igualdade que são sem distinção entre maiúsculas e minúsculas:

where Equals(ToLowerCase(C.company), ToLowerCase(N2C.name))

Se o objeto de entrada for null, a função retornará null.

A instrução create function

Para executar operações em valores extraídos que não são suportados pela AQL, é possível definir funções customizadas para usar em regras de extração chamadas de funções definidas pelo usuário (UDFs).

A AQL suporta funções escalares definidas pelo usuário e funções de tabelas definidas pelo usuário. Java™ e PMML são as únicas linguagens de implementação suportadas para UDFs. Uma função escalar retorna um único valor escalar e uma função de tabela retorna uma ou mais tuplas, em outras palavras, uma tabela.

Implemente funções definidas pelo usuário (UDFs) seguindo quatro etapas:

  1. Implementando a função

    A AQL suporta funções definidas pelo usuário (UDFs) que são implementadas em Java ou PMML.

  2. Declarando-a em AQL.

    É possível tornar as funções escalares definidas pelo usuário e os modelos de aprendizado de máquina de arquivos PMML disponíveis para a AQL usando a instrução create function.

  3. Usando-a em AQL.

    As funções definidas pelo usuário funcionam com as instruções e as cláusulas AQL.

  4. Depurando a UDF.

    Como as funções definidas pelo usuário (UDFs) baseadas em Java são implementadas como métodos públicos em classes Java, você depurará as UDFs da mesma maneira que depura os programas Java.

Implementando funções definidas pelo usuário

A AQL suporta funções definidas pelo usuário (UDFs) que são implementadas em Java™ ou em PMML.

Esta seção se concentra especificamente em UDFs que são implementadas em Java. Para UDFs implementadas em PMML, o modelo de aprendizado de máquina é armazenado dentro do arquivo XML de PMML. Consulte a documentação do PMML para saber como criar esses modelos: [http://dmg.org/pmml/v4-1/GeneralStructure.html]

É possível implementar uma UDF Escalar como um método público em uma classe Java. É possível implementar uma UDF de tabela como um método público em uma classe Java que amplia a API com.ibm.avatar.api.udf.TableUDFBase. Além disso, uma UDF de tabela pode, opcionalmente, substituir o método initState() da superclasse com.ibm.avatar.api.udf.TableUDFBase.

Se a UDF tiver um parâmetro de entrada do tipo Span, Text ou ScalarList ou o tipo de retorno da UDF for Span, Text ou ScalarList, a classe Java deverá importar as classes com.ibm.avatar.algebra.datamodel.Span, com.ibm.avatar.algebra.datamodel.Text ou com.ibm.avatar.algebra.datamodel.ScalarList para compilar.

As funções da tabela requerem APIs adicionais para fornecer informações do esquema de saída. Essas APIs pertencem à classe base com.ibm.systemt.api.udf.TableUDFbase. Se uma subclasse contiver mais de uma função da tabela, um objeto Java separado será criado para cada instância.

Para que o código UDF recupere recursos que não são de classe do arquivo JAR, o único método suportado é getResourceAsStream(). Outros métodos para acessar recursos (tais como getResource(), getResources(), getSystemResource()) não são suportados. Por exemplo, um arquivo JAR UDF que contém o arquivo de propriedades my.properties no package (pacote de arquivos) do pacote, pode acessá-lo com a seguinte instrução Java:

InputStream in = this.getClass().getClassLoader().
  getResourceAsStream(“com/ibm/myproject/udfs/my.properties”);

Ciclo de vida de UDFs implementadas em Java

As operações a seguir são executadas quando o extrator é compilado (a API CompileAQL.compile()), instanciado (API OperatorGraph.createOG()) e validado (API OperatorGraph.validateOG()), exatamente uma vez para cada instrução create function na AQL:

  1. Carregue a classe Java que contém o método UDF, usando um novo carregador de classes. A classe é procurada dentro do JAR de UDF especificado na instrução de função create correspondente. Quaisquer outras classes que forem necessárias ao carregar essa classe também serão procuradas dentro do mesmo JAR de UDF e, se não localizadas, a procura será delegada ao carregador de classes que instanciou o Runtime.
  2. Crie uma instância dessa classe.
  3. Para UDFs de tabela, chame o método initState().

Como essas etapas são executadas para cada instrução create function, se uma classe Java contiver diversos métodos UDF (e todos eles forem usados na AQL em diferentes instruções create function), a classe será carregada diversas vezes, cada vez em um carregador de classes separado (Etapa 1). Além disso, diversas instâncias da classe são criadas (Etapa 2) e o método initState() é chamado uma vez para cada instância (Etapa 3). O motivo de cada UDF resultar em um carregador de classes separado é permitir que diferentes UDFs usem versões diferentes da mesma classe (ou biblioteca).

No tempo de execução (API OperatorGraph.execute()), a classe UDF não é carregada novamente porque a classe é carregada durante a instanciação do extrator. O método Java que implementa a UDF é chamado, quando necessário, para computar partes da saída. Quando o extrator é usado em um encadeamento único, isso significa que existe de zero a possivelmente muitas chamadas para cada documento de entrada (e muito provavelmente diversas chamadas ao longo da vida do objeto Gráfico do operador). Quando o extrator é compartilhado entre diversos encadeamentos, diferentes encadeamentos podem atingir o método ao mesmo tempo (com entradas diferentes).

Se for necessário que uma parte específica do código UDF seja avaliada exatamente uma vez, por exemplo, para inicializar estruturas de dados necessárias para o método UDF nas chamadas, esse código não deverá ser colocado no método de avaliação UDF, uma vez que esse método é muito provavelmente executado diversas vezes ao longo da vida do extrator (como o objeto OperatorGraph), podendo ser atingido quase simultaneamente quando o extrator for compartilhado entre diversos encadeamentos. Em vez disso:

  1. Para UDFs escalares, siga os princípios padrão de programação Java. Por exemplo, coloque o código em um bloco estático.
  2. Para UDFs de tabela, coloque o código no método initState() ou siga os princípios de programação Java padrão. Por exemplo, coloque o código em um bloco estático.

Ao fazer isso, lembre-se de que a classe pode ser carregada diversas vezes durante a compilação, a instanciação e a validação do extrato, conforme explicado nas Etapas 1-3 acima. Se o código que inicializa a UDF for colocado em um bloco estático, esse código será executado cada vez que a classe for carregada (potencialmente diversas vezes), introduzindo, portanto, uma sobrecarga durante a compilação e a instanciação do gráfico do operador. Se a sobrecarga for grande, siga estas melhores práticas:

  • Para minimizar a sobrecarga durante o tempo de compilação, a melhor prática é colocar recursos pesados de tempo de compilação, como grandes dicionários ou UDFs com o tempo de inicialização grande em um módulo AQL separado e exportá-los. Tente compilar somente os módulos do AQL que foram mudados e outros módulos que dependam deles.
  • Para minimizar a sobrecarga durante a instanciação e validação do gráfico de operador:
    1. Se o código de inicialização for necessário para um único método UDF, coloque esse método UDF em uma classe Java separada (e coloque o código de instanciação pesado em um inicializador estático como antes ou use algum outro mecanismo que assegure que o código seja executado uma vez).
    2. Se o código de inicialização for compartilhado por múltiplos métodos UDF, o Runtime e o AQL não fornecerão um mecanismo explícito para assegurar que o código de inicialização seja executado exatamente uma vez. Nessa situação, se o tempo de inicialização for proibitivo, a única solução será colocar os recursos compartilhados e o código de inicialização no caminho de classe do sistema. Ou seja, coloque o código de inicialização em uma nova classe MySeparateClass.java e armazene o resultado da inicialização em uma variável estática dessa classe, como MySeparateClass.myVar. Compacte MySeparateClass.java com todos os recursos que são necessários durante a inicialização em um arquivo JAR e coloque esse JAR no caminho de classe do sistema. Os métodos UDF podem referir-se ao modelo inicializado usando a variável estática MySeparateClass.myVar. O código de inicialização agora é executado exatamente uma vez, quando a classe MySeparateClass.java é carregada pelo carregador de classes do sistema.

Dica:

A representação compilada de um módulo (o arquivo .tam) contém o código binário serializado da UDF. Portanto, se o mesmo código UDF for referenciado por instruções create function em dois módulos diferentes, o código UDF será serializado na representação compilada de ambos os módulos. Em outras palavras, o código UDF é serializado duas vezes. Nesses casos, é possível evitar a redundância criando um módulo separado que age como uma biblioteca de UDFs e reutilizar essa biblioteca em outros módulos. Para criar uma biblioteca de UDFs, siga estas etapas:

  1. Crie um módulo.
  2. Coloque todos os arquivos JAR de UDF dentro desse módulo.
  3. Defina todas as funções necessárias com as instruções create function.
  4. Exporte todas elas com instruções export function para que possam ser importadas e usadas em outros módulos.

Exemplos

Exemplo 1: implementando uma UDF escalar

Este exemplo mostra a implementação de uma UDF escalar denominada toUpperCase. Essa UDF usa como entrada um valor do tipo Span e gera um valor de sequência que consiste no conteúdo de texto da entrada Span, convertido em maiú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();
}

Exemplo 2: implementando uma UDF escalar que usa uma tabela como entrada

Este exemplo mostra a implementação de uma UDF escalar nomeada TableConsumingScalarFunc. Esta UDF toma como entrada duas listas de tuplas e gera um valor de sequência que concatena o conteúdo das duas 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 ();
  }
}

Exemplo 3: implementando uma UDF de tabela que usa uma tabela como entrada

Este exemplo mostra a implementação de uma UDF de tabela nomeada TableConsumingTableFunc. Essa UDF usa como entrada duas listas de tuplas e gera uma única lista de tuplas que contém tuplas da primeira entrada intercaladas com tuplas da segunda entrada. Observe que a implementação se amplia por meio da classe base com.ibm.avatar.api.udf.TableUDFBase, que fornece APIs para obter os esquemas de entrada e saída.

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)); }
    }
  }

}

Declarando funções definidas pelo usuário

É possível tornar as funções escalares definidas pelo usuário e os modelos de aprendizado de máquina de arquivos PMML disponíveis para a AQL usando a instrução create function.

Sintaxe

A sintaxe geral da instrução create function é conforme a seguir:

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>]*

Descrição

  • <function-name\>

    O <function-name\> declara o nome de AQL da UDF. A UDF é referida no código AQL com esse nome

  • <input-schema-definition\>

    Especifica os parâmetros de entrada da UDF. Um parâmetro de entrada tem um nome, que é especificado como <column-name\> e que pode ser um tipo escalar ou um localizador de tabelas. Quando a linguagem é PMML, a função deve usar uma única tabela chamada params como o argumento.

  • <column-name\>

    Especifica o nome de uma coluna na entrada ou na saída da UDF.

  • <data-type\>

    O tipo de um parâmetro escalar de entrada para a UDF, o tipo de uma coluna no esquema de uma tabela de entrada para a UDF ou no esquema da tabela de saída da UDF. Os valores possíveis para <data-type\> são: Integer, Float, String, Text, Span, Boolean ou ScalarList.

  • table (<output-schema-definition\>) as locator

    Esse tipo de entrada permite que uma função use como entrada os conteúdos inteiros de uma determinada visualização AQL conforme computado no documento atual. O parâmetro de localizador referencia visualizações ou tabelas como argumentos.

  • <return-type\>

    Para UDFs escalares, o <return-type\> especifica o tipo do valor escalar que é retornado pela UDF. Os valores possíveis para o tipo de retorno são: Integer, Float, String, Text, Span, Boolean ou ScalarList. Se o tipo de retorno for Integer, a função Java™ que implementa a UDF retornará objetos do tipo Integer. A implementação UDF não pode retornar o tipo int primitivo. Se o tipo de retorno for Texto ou Span, especifique o parâmetro de entrada a partir do qual o tipo de retorno é derivado. É possível especificar o parâmetro de entrada usando a especificação like opcional, uma vez que os spans são sempre de uma coluna subjacente. Se o tipo de retorno for ScalarList, especifique o parâmetro de entrada por meio do qual o tipo escalar dentro do ScalarList deve ser inferido. Quando a linguagem é PMML, a função deve retornar uma tabela.

  • <output-schema-definition\>

    Para UDFs de tabela, o <output-schema-definition\> especifica o esquema de saída da tabela que é retornado pela UDF, incluindo os nomes de colunas e seus tipos.

  • <ext-name\>

    O external_name especifica onde localizar a implementação da UDF. Quando o idioma é Java, ele é uma sequência do formulário '<jar-file-name\>:<fully-qualified-class-name\>!<method-name\>' que consiste em três partes:

    • Nome do arquivo JAR: quando você compila a AQL modular, as referências de local de arquivos JAR de UDF devem ser relativas à raiz do módulo no qual a referência é feita.
    • Nome de classe: nome completo de classe que contém a implementação UDF
    • Nome do método: o método deve ser um método público da classe. A assinatura de método deve corresponder aos tipos de parâmetro que são especificados na instrução create function. A conversão de tipo automático não é feita pelo componente de tempo de execução. Quando a linguagem é PMML, a cláusula external_name especifica uma sequência que é a localização do arquivo PMML em relação ao diretório-raiz do módulo. A implementação atual suporta modelos que são expressos usando o padrão PMML versão 4.1 e os avalia usando a biblioteca org.jpmml versão 1.0.22.
  • language

    A especificação de linguagem aponta para a linguagem de implementação da UDF. O componente de tempo de execução suporta somente UDFs que são implementadas em Java™.

  • deterministic/not deterministic

    O deterministic/not deterministic opcional especifica se a função é stateless. Uma função determinística sempre retorna o mesmo valor para o mesmo conjunto de valores de entrada.

  • return null on null input

    O return null on null input opcional especifica o comportamento da função quando um ou mais dos valores de entrada são nulos. Se o retorno de nulo na entrada nula for especificado, o sistema retornará null na entrada nula sem chamar a UDF. Se chamada de entrada nula for especificada, a UDF é invocada até mesmo para valores de entrada nulos.

Notas de uso para UDFs implementadas em PMML

As funções criadas de arquivos PMML usam uma única tabela chamada params como argumento e geram uma tabela. A implementação da função mapeia campos de entrada entre os esquemas de entrada e de saída declarados na instrução create function e o esquema especificado no arquivo PMML. Em outras palavras, a seção DataDictionary que descreve os nomes e os tipos de campos que podem aparecer nos registros de entrada e saída que o modelo produz e consome, a seção MiningSchema que informa quais arquivos denominados definidos na seção DataDictionary estão em cada tupla que representa um vetor de recurso e a seção Output que informa quais campos denominados na seção DataDictionary estão presentes em cada tupla da representação externa da saída do modelo. Essas funções devem ser funções de tabela; cada linha na tabela é transmitida para o modelo PMML e produz uma linha de saída.

Essas informações do esquema são necessárias porque os sistemas do tipo PMML e AQL não correspondem perfeitamente. Por exemplo, a PMML tem vários tipos para representar os registros de data e hora, enquanto a AQL requer atualmente que os usuários codifiquem os registros de data e hora como valores de sequência. As informações do esquema também permitem que os desenvolvedores que conhecem a AQL, mas não a PMML, entendam o conjunto de regras da AQL.

O compilador AQL verifica o esquema de entrada com relação ao esquema de entrada do arquivo PMML para assegurar que os dois esquemas sejam compatíveis. Se os dois esquemas contiverem campos com o mesmo nome, mas tipos incompatíveis, a compilação falhará com uma mensagem de erro apropriada. Se os esquemas de entrada ou de saída da função contiverem colunas adicionais ou ausentes, a função resulting ignorará essas colunas e não gerará um erro. A ordem de nomes de colunas pode ser diferente entre a definição de AQL e o arquivo de PMML. Se um nome de coluna aparecer nos esquemas de entrada e de saída, mas não no esquema PMML, os valores dessa coluna serão transmitidos para a saída da função.

Exemplos

Exemplo 1: declarando UDFs escalares com valores escalares como entrada usando Java

O exemplo a seguir mostra uma instrução create function que declara uma função denominada udfCombineSpans. A função definida pelo usuário usa dois spans como entrada e retorna um span mesclado semelhante ao primeiro span de entrada. A função real UDF Java™ é compactada em um arquivo JAR denominado udfs.jar, no diretório udfjars. O método que implementa a função é combineSpans na classe com.ibm.test.udfs.MiscScalarFunc. O método também declara uma função udfSpanGreaterThan que retornará true se o período for maior que o tamanho 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;

O próximo exemplo mostra como declarar uma função denominada udfCompareNames que recebe uma lista de nomes nameList e um único nome myName. A saída é uma lista semelhante à lista de entrada, que contém apenas as entradas de nameList semelhantes 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;

Exemplo 2: declarando UDFs escalares com tabelas como entrada usando Java

O exemplo a seguir ilustra o uso do tipo de entrada table as locator. Ele mostra uma instrução create function que declara uma função chamada MyScalarFunc. A implementação Java™ da UDF é empacotada dentro da classe com.ibm.test.udfs.TableConsumingScalarFunc.

Esta UDF toma como entrada duas listas de tuplas e gera um valor de sequência que concatena o conteúdo das duas listas de tuplas de entrada. A implementação Java™ da UDF está incluída em Implementando funções definidas pelo usuário.

-- 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;

Exemplo 3: Declarando UDFs de tabela usando Java

O exemplo a seguir ilustra o uso da cláusula return table. O exemplo mostra uma instrução create function que declara uma função de tabela chamada MyScalarFunc. A implementação Java™ da UDF é empacotada dentro da classe TEST.UDFS.TABLECONSUMINGTABLEFUNC. Essa UDF usa como entrada duas listas de tuplas e gera uma lista de tuplas que mesclam as listas de entrada. A implementação Java™ da UDF está incluída em Implementando funções definidas pelo usuário.

-- 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;

Exemplo 4: declarando uma UDF de tabela implementada em PMML

O exemplo a seguir mostra uma instrução create function que declara uma função de tabela denominada IrisDecisionTree usando a linguagem PMML. A implementação de PMML da UDF é especificada no arquivo IrisTree.xml, mostrado no exemplo a seguir. O modelo armazenado no IrisTree.xml é um modelo de árvore de decisão.

-- 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>

Documentando a instrução create function com comentários

O comentário do AQL Doc para uma instrução de função create contém as informações a seguir:

  • Uma descrição geral sobre a função.
  • A descrição @param que especifica cada nome de parâmetro que é usado na função. Indique o tipo do parâmetro, se é um tipo escalar ou uma tabela. Se o parâmetro for uma tabela, descreva o esquema da tabela, incluindo os nomes e os tipos de coluna na ordem em que aparecem no esquema da tabela esperada como entrada.
  • A descrição @return que especifica as informações que são retornadas pela função. Se a função retornar uma tabela, especifique o esquema de saída da tabela, incluindo nomes de colunas e tipos na ordem em que eles aparecem no esquema da tabela de saída.
/**
* 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;

Usando funções definidas pelo usuário

As funções definidas pelo usuário funcionam com as instruções e as cláusulas AQL.

As funções escalares definidas pelo usuário funcionam com as instruções e as cláusulas AQL, semelhantes a funções integradas. Especificamente, as UDFs escalares podem ser usadas nas cláusulas select, where, having, group by e order by da mesma maneira que as funções escalares integradas, como GetBegin e LeftContext. Funções escalares definidas pelo usuário que retornam um tipo booleano podem ser usadas como predicados em where e having cláusulas.

As funções de tabela definidas pelo usuário (UDFs de tabela) podem ser usadas na cláusula from de uma instrução select ou de uma instrução extract.

Exemplos

Exemplo 1: usando UDFs escalares implementadas em Java com valores escalares como entrada

Este exemplo demonstra como usar as funções udfCombineSpans e udfSpanGreaterThan que são declaradas em Declarando funções definidas pelo usuário.

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);

Exemplo 2: usando UDFs escalares implementadas em Java com tabelas como entrada

O exemplo a seguir mostra como usar uma função escalar que usa tabelas como entrada. Este exemplo ilustra o uso da função UDF da tabela MyScalarFunc, cuja implementação Java™ está incluída em Implementando funções definidas pelo usuário. Elas são os mesmos tipos de coluna, mas têm nomes de coluna diferentes.

-- 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;

Exemplo 3: usando UDFs de tabela implementadas em Java

Este exemplo ilustra o uso da função UDF da tabela MyTableFunc, cuja implementação Java™ está incluída em Implementando funções definidas pelo usuário.

-- 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;

Como no Exemplo 2, O exemplo define duas visualizações: FirstInputView com schema (match Span) e SecondInputView com schema (spanCol Span, textCol Text). A última visualização no exemplo, TabFuncOutput, chama a função table MyTableFunc na cláusula from, com as duas visualizações de entrada. Conforme explicado no Exemplo 2, uma visualização é compatível com um argumento de localizador de tabela de uma função, desde que o número de colunas e os tipos de colunas no esquema da visualização de entrada e do localizador de tabela correspondam. No entanto, não é necessário que os nomes da coluna correspondam.

Finalmente, a cláusula select descarta a coluna outStr na tabela de saída de MyTableFunc, mantendo somente as duas primeiras colunas outSpan1 e outSpan2.

Exemplo 4: usando uma UDF de tabela implementada em PMML

Este exemplo ilustra o uso da função UDF da tabela IrisDecisionTree que é declarada no exemplo 4 de Declarando funções definidas pelo usuário.

-- 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;