IBM Cloud Docs
Guide de référence pour Annotation Query Language (AQL)

Guide de référence pour Annotation Query Language (AQL)

Annotation Query Language (AQL) est le langage principal utilisé pour créer des extracteurs de règles avancées dans IBM Watson® Knowledge Studio.

  • Modèle de données : le modèle de données pour AQL est similaire au modèle relationnel standard utilisé par une base de données SQL telle que DB2®. Toutes les données dans AQL sont stockées dans des tuples, des enregistrements de données d'une ou plusieurs colonnes, ou des champs. Une collection de tuples constitue une vue. Tous les tuples d'une vue peuvent avoir le même schéma, c'est-à-dire les noms et les types de champs contenus dans tous les tuples.
  • Modèle d'exécution : le composant d'exécution possède un modèle d'exécution sur la base d'un document à la fois. Ce composant reçoit une série de documents et exécute l'extracteur sur chaque document pour en extraire des informations.
  • Instructions AQL : en utilisant des instructions AQL, vous pouvez créer, puis utiliser des modules, des vues, des tables, des dictionnaires et des fonctions.
  • Fonctions intégrées : AQL comporte toute une collection de fonctions intégrées à utiliser dans les règles d'extraction.
  • Instruction create function : pour réaliser des opérations sur des valeurs extraites qui ne sont pas prises en charge par AQL, vous pouvez définir des fonctions personnalisées à utiliser dans les règles d'extraction que l'on nomme fonctions définies par l'utilisateur (UDF, user-defined functions).

Syntaxe d'Annotation Query Language (AQL)

A l'instar de nombreux langages de programmation, AQL est basé sur une syntaxe et une grammaire communes.

La structure lexicale d'un langage de programmation est formée d'un ensemble de règles élémentaires qui définissent les unités lexicales et les composants de base de ce langage, comme par exemple les mots réservés, identificateurs, constantes, etc.

La syntaxe du langage AQL est similaire à celle de SQL, mais avec des différences notables :

  • AQL est sensible à la casse.

  • AQL ne prend pas en charge les fonctions SQL avancées telles que les sous-requêtes corrélées et les requêtes récursives.

  • AQL comporte un nouveau type d'instruction, extract, qui ne figure pas dans SQL.

  • AQL n'autorise pas l'utilisation de mots clés (mots réservés) pour les noms de vue, de colonne ou de fonction.

  • AQL autorise l'utilisation de la syntaxe Perl pour les expressions régulières mais vous n'êtes pas obligé de l'utiliser. Les expressions régulières commencent par une barre oblique (/) et se terminent par une barre oblique (/), comme dans la syntaxe Perl. AQL autorise également les expressions régulières qui commencent par un guillemet simple (') et se terminent par un guillemet simple ('). Par exemple, vous pouvez utiliser /regex/ au lieu de 'regex' comme expression régulière dans AQL.

  • Identificateurs : des identificateurs sont utilisés pour définir les noms des objets AQL, notamment les noms des modules, vues, tables, dictionnaires, fonctions, attributs et paramètres de fonction.

  • Mots réservés : les mots réservés correspondent à des mots qui ont une signification figée dans le contexte de la structure AQL et qui ne peuvent pas être redéfinis. Les mots clés sont des mots réservés qui ont une signification spéciale dans la syntaxe du langage.

  • Constantes : les constantes sont des valeurs fixes dont les données peuvent être de type : chaîne (String), entier (Integer), valeur en virgule flottante (Float) ou booléenne (Boolean).

  • Commentaires : utilisez des commentaires pour étendre le code AQL avec des descriptions de base permettant d'aider d'autres personnes à comprendre le code et de générer des modules compilés auto-descriptifs.

  • Expressions : une expression AQL est une combinaison d'une ou plusieurs valeurs scalaires et fonctions qui a pour résultat une seule valeur scalaire.

Identificateurs

Des identificateurs sont utilisés pour définir les noms des objets AQL, notamment les noms des modules, vues, tables, dictionnaires, fonctions, attributs et paramètres de fonction.

Il existe deux types d'identificateurs AQL sensibles à la casse :

  • Identificateur simple

    Un identificateur simple doit commencer par une lettre en minuscules (a-z) ou en majuscules (A-Z) ou le caractère de soulignement (_). Les caractères suivants peuvent être des lettres minuscules ou majuscules, le caractère de soulignement ou des chiffres (0-9). Un identificateur simple doit être différent de tout mot clé AQL.

  • Identificateur entre guillemets

    Un identificateur à guillemets doubles commence et se termine par un guillemet double ("). Vous pouvez utiliser n'importe quel caractère entre les guillemets doubles de début et de fin. Ces identificateurs ne peuvent pas contenir de point (.). Si un guillemet double est présent dans un nom, il doit être précédé de la barre oblique inversée (\), par exemple \”.

Mots réservés

Les mots réservés correspondent à des mots qui ont une signification figée dans le contexte de la structure AQL et qui ne peuvent pas être redéfinis. Les mots clés sont des mots réservés qui ont une signification spéciale dans la syntaxe du langage.

Les mots clés suivants réservés dans AQL ne peuvent pas être utilisés comme identificateurs car ils ont chacun un objectif bien défini au sein du langage :

  • 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

Les mots réservés suivants sont les noms de types scalaires intégrés :

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

Les autres noms réservés suivants ne peuvent pas être utilisés comme identificateurs :

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

Constantes

Les constantes sont des valeurs fixes dont les données peuvent être de type : chaîne (String), entier (Integer), valeur en virgule flottante (Float) ou booléenne (Boolean).

Les constantes sont utilisées dans une liste de sélection incorporée dans une clause select ou extract ou en tant qu'arguments dans les fonctions intégrées ou UDF et les prédicats. AQL prend en charge les types de constante suivants :

  • Constante de chaîne

    Une chaîne est incluse entre guillemets simples (‘), par exemple ‘une chaîne’.

  • Constante de type entier (Integer)

    Valeur entière signée 32 bits qui n'est pas placée entre guillemets, par exemple 10 ou -1.

  • Constante de type valeur en virgule flottante (Float)

    Valeur en virgule flottante simple précision 32 bits, qui n'est pas placée entre guillemets, par exemple 3.14 ou -1.2.

  • Constante booléenne (Boolean)

    Valeur true ou false qui n'est pas placée entre guillemets.

  • Constante de type Null

    La valeur null n'est pas placée entre guillemets.

Commentaires

Utilisez des commentaires pour étendre le code AQL avec des descriptions de base permettant d'aider d'autres personnes à comprendre le code et de générer des modules compilés auto-descriptifs.

Les commentaires permettent aux développeurs AQL d'étendre le code AQL avec des descriptions de base, pour en faciliter la compréhension et ils peuvent ainsi générer des modules AQL compilés auto-descriptifs. Trois sortes de commentaires sont pris en charge dans le langage AQL :

  • Commentaires sur une seule ligne

    Les commentaires sur une seule ligne commencent par deux traits d'union (--).

  • Commentaires sur plusieurs lignes

    Les commentaires à plusieurs lignes commencent par une barre oblique et un astérisque (/*) et se terminent par un astérisque et une barre oblique (*). Les commentaires de plusieurs lignes ne peuvent pas être imbriqués. Par exemple, le commentaire sur plusieurs lignes suivant n'est pas admis :

    /*
    A comment with a /*nested comment*/
    */
    
  • Commentaires AQL Doc

    Les commentaires AQL Doc permettent de décrire un module ou un objet AQL en langage simple et avec un aspect enrichi pour offrir une compréhension contextuelle à d'autres utilisateurs. Contrairement aux commentaires sur une seule ligne ou sur plusieurs lignes qui sont ignorés par le compilateur AQL, les commentaires AQL Doc sont sérialisés dans les métadonnées des modules compilés (fichiers .tam) et accessibles pour une utilisation en externe.

    Tous les commentaires AQL Doc pour les instructions et les modules sont au format suivant :

    • Le commentaire est en texte en clair (aucune balise HTML n'est prise en charge).

    • Le commentaire commence par une barre oblique suivie de deux astérisques (/**) et se termine par un astérisque suivi d'une barre oblique (*/). En option, chaque ligne peut également commencer par un astérisque (*).

    • Vous pouvez utiliser autant de blancs que vous voulez avant l'astérisque.

    • Les balises spéciales avec le symbole (@) en préfixe peuvent être utilisées au début de chaque ligne ou après l'astérisque en option.

    • Les commentaires AQL Doc ne peuvent pas être imbriqués. Deux niveaux de granularité sont pris en charge dans le système AQL Doc. Le format pour documenter chaque artefact fait l'objet d'une explication détaillée dans la rubrique qui décrit l'instruction et la syntaxe associées.

    • Commentaires au niveau du module

      Les commentaires au niveau du module sont incorporés dans un fichier spécial nommé module.info situé juste au-dessous du dossier du module. Les commentaires sont censés décrire la sémantique du module, ainsi que le schéma de la vue Document du module.

    • Commentaires au niveau de l'instruction

      Les commentaires au niveau de l'instruction sont incorporés dans le fichier AQL source, qui précède l'instruction qui crée un objet AQL. Les commentaires sur une seule ou plusieurs lignes sont autorisés entre le commentaire AQL Doc d'une instruction et l'instruction elle-même.

      Les instructions AQL de niveau supérieur suivantes peuvent être documentées à l'aide de commentaires AQL Doc :

      • L'instruction create external view
      • L'instruction create external table
      • L'instruction create external dictionary
      • La fonction create
      • L'instruction detag
      • L'instruction select... into. Les commentaires AQL Doc sont sérialisés dans la représentation compilée d'un module.

Expressions

Une expression AQL est une combinaison d'une ou plusieurs valeurs scalaires et fonctions qui a pour résultat une seule valeur scalaire.

Il existe quatre types de fonction possibles :

  • une constante
  • une référence de colonne
  • un appel de fonction scalaire
  • un appel de fonction d'agrégation

Constante

Une expression peut être une constante de type Integer, Float ou String, comme illustré dans l'exemple suivant :

select 'positive' as polarity

L'expression correspond à positive, une constante de type chaîne (String).

Référence de colonne

Une expression peut être une référence de colonne, comme illustré dans l'exemple suivant :

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

Cette vue identifie du texte pouvant être interprété comme le nom complet d'une personne (par exemple, “Samuel Davis”, “Vicky Rosenberg”). Les expressions F.name et L.name sont des expressions de référence de colonne qui renvoient la colonne correspondant respectivement au nom des vues F et L. L'instruction from définit les vues F et L en tant que noms locaux des vues FirstName et LastName (qui définissent le prénom et le nom valides et qui ne figurent pas dans cet exemple).

Appel de fonction scalaire

Une expression peut être composée d'un ou plusieurs appels de fonction scalaire, chacun pouvant contenir des arguments constituant également des expressions de type constante, référence de colonne ou appel de fonction scalaire. Un appel de fonction scalaire peut être une des fonctions scalaires intégrées ou une fonction scalaire définie par l'utilisateur. Prenons l'exemple suivant :

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

Cette vue identifie des membres potentiels de la famille en regroupant les personnes ayant le même nom de famille, en imprimant l'ensemble des noms avec les noms de famille en minuscules (par exemple, lastname keaton, firstnames (Elyse, Alex, Diane)). Les sorties des appels de fonction GetText est utilisée en tant qu'argument dans l'appel de fonction ToLowerCase pour afficher les noms en minuscules. Les expressions de l'appel de fonction scalar dans cet exemple sont : ToLowerCase, (GetText(P.lastname), ToLowerCase(GetText(P.firstname)) et GetText(P.lastname).

Appel de fonction d'agrégation

Une expression peut correspondre à un appel de fonction d'agrégation. Ce type d'expression peut avoir comme arguments une autre expression de type référence de colonne ou appel de fonction scalaire. L'exemple suivant illustre un appel de fonction d'agrégation avec une expression de type référence de colonne :

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

L'expression correspond tout simplement à Count(Person.lastname) et compte le nombre d'annotations Person.lastname dans le document. Un exemple d'appel de fonction d'agrégation avec une expression de type appel de fonction scalaire figurait dans l'exemple précédent sous la forme List(GetText(P.firstname)) avec la fonction d'agrégation List ayant une fonction scalaire GetText en tant qu'argument afin de générer une liste de prénoms. Les expressions d'appel de fonction d'agrégation ne sont autorisées qu'en tant qu'expressions dans la liste select d'une instruction select. Elles ne sont pas autorisées dans la liste select d'une instruction extract ou en tant qu'arguments dans un appel de fonction d'agrégation ou de fonction scalaire.

Modèle de données

Le modèle de données pour l'AQL est similaire au modèle relationnel standard utilisé par une base de données SQL telle que DB2®. Toutes les données dans AQL sont stockées dans des tuples, des enregistrements de données d'une ou plusieurs colonnes, ou des champs. Une collection de tuples constitue une vue. Tous les tuples d'une vue peuvent avoir le même schéma, c'est-à-dire les noms et les types de champs contenus dans tous les tuples.

Le contenu du document d'entrée est représenté sous la forme d'une vue spéciale appelée Document.

Les champs d'un tuple doivent appartenir à l'un des types de données intégrés d'AQL :

  • Boolean

    Type de données ayant la valeur true ou false.

  • Float

    Nombre à virgule flottante simple précision.

  • Integer

    Entier signé 32 bits.

  • ScalarList

    Collection de valeurs ayant le même type scalaire (Integer, Float, Text ou Span). Une valeur avec le type de données ScalarList peut être obtenue en résultat d'une fonction d'agrégation intégrée AQL List() ou en résultat d'une fonction définie par l'utilisateur (UDF).

  • Span

    Une étendue (Span) correspond à une région d'un objet Text, identifiée par les décalages de début et de fin dans l'objet Text. Supposons que votre texte d'entrée soit :

    Amelia Earhart is a pilot.
    

    Le texte dans l'étendue [0 à 6] est Amelia.

    Cette étendue est visualisée sous cette forme :

    0A1m2e3l4i5a6
    

    De même, le texte dans l'étendue [20 à 25] correspond à pilot.

    Une étendue [x à x] représente l'étendue entre la fin d'un caractère et le début du caractère suivant. Dans l'exemple précédent, [0-0] est une chaîne vide avant le caractère A. De même, une étendue de [3-3] est une chaîne vide entre les caractères e et l.

    Une valeur de type Span peut être obtenue en résultat d'une instruction extract ou en tant que fonction scalaire intégrée ou fonction définie par l'utilisateur (UDF).

  • Texte

    Type de données AQL utilisé pour représenter une séquence de caractères. Un objet Text contient une chaîne en Unicode désignée comme sa valeur de chaîne. Lorsqu'une chaîne est formée par une concaténation de sous-chaînes disjointes d'un autre objet Text, elle peut également contenir une référence à l'objet Text d'origine et aux informations de mappage de décalages correspondants. Deux objets Text sont considérés comme égaux si tous leurs composants sont rigoureusement égaux entre eux.

  • Valeurs de comparaison de type Span et Text Des facteurs de définition de priorité affectent les comparaisons entre les valeurs de type Span et de type Text.

Valeurs de comparaison de type Span et Text

Des facteurs de définition de priorité affectent les comparaisons entre les valeurs de type Span et de type Text.

Les valeurs de type Span et de type Text sont comparées comme suit :

  • Une valeur null de type Span est toujours considérée comme inférieure aux autres valeurs.
  • Une valeur de type Text est toujours considérée comme supérieure à une valeur de type Span.
  • Les valeurs de type Text sont triées d'abord par ordre lexical de leurs valeurs de chaîne, puis dans l'ordre de leurs valeurs d'origine de type Text et par informations de mappage de décalage, le cas échéant.
  • Les valeurs de type Span sont triées d'abord par leurs objets Text sous-jacents, puis par leur décalage de début, et ensuite par leur décalage de fin. L'étendue avec le plus petit décalage de début est considérée comme inférieure. Entre les deux étendues commençant au même décalage, celle qui a le décalage de fin le plus faible est considérée comme inférieure.

Modèle d'exécution

Le composant d'exécution possède un modèle d'exécution sur la base d'un document à la fois. Ce composant reçoit une série de documents et exécute l'extracteur sur chaque document pour en extraire des informations.

Un extracteur se compose d'un ou plusieurs modules AQL pour créer une collection de vues définissant chacune une relation. Certaines de ces vues sont désignées par vues de sortie (output views) tandis que d'autres ne sont pas des vues de sortie. Les vues qui ne sont pas des vues de sortie peuvent comprendre des vues importées ou exportées dans un module. Il est important de noter que les vues de sortie et les vues exportées sont orthogonales. Par exemple, une vue exportée n'entre pas dans la catégorie des vues de sortie. En plus de ces vues, la vue unique Document représente le document d'entrée annoté par cet extracteur.

Vue Document

Au niveau du module AQL, la vue Document est une vue spéciale qui représente le document actuel qui fait l'objet d'annotation par ce module. Lorsqu'au moins deux modules sont combinés pour former un extracteur, l'union sans doublon des schémas de Document de tous les modules est la vue Document requise. Utilisez l'instruction require document with columns pour spécifier le schéma de la vue Document. Si cette instruction ne figure pas dans un module, le schéma par défaut pris en compte pour la vue Document est (text Text, label Text) :

  • text

    Contenu sous forme de texte du document actuel.

  • label

    Label du document actuel en cours d'annotation.

Le mot clé Document est réservé comme identificateur de la vue Document, qui est remplie automatiquement lors de l'exécution. Par conséquent, vous ne pouvez pas définir une autre vue ou table du même nom. Cependant, vous pouvez utiliser le mot Document comme identificateur pour les alias et les noms d'attributs.

Instructions AQL

En utilisant des instructions AQL, vous pouvez créer, puis utiliser des modules, des vues, des tables, des dictionnaires et des fonctions.

Les instructions suivantes sont prises en charge dans le langage AQL :

  • Instructions pour créer des modules et déclarer leurs interactions

    L'instruction module

    L'instruction export

    L'instruction import

  • Instructions pour créer des objets AQL : vues (views), dictionnaires (dictionaries), tables (tables) ou fonctions (functions)

    Les instructions create dictionary et create external dictionary

    L'instruction create table

    L'instruction create view

    L'instruction create external view

    L'instruction detag

    L'instruction extract

    L'instruction select

    L'instruction require document with columns

    L'instruction set default dictionary language

    L'instruction create function

Les spécifications de syntaxe des instructions AQL contiennent des crochets ([ ]). Ces spécifications indiquent que les parenthèses et les constructions qu'elles contiennent sont facultatives lorsque la syntaxe correspondante est utilisée pour écrire une instruction. De plus, ils servent de marque de réservation permettant de définir comment spécifier d'autres instances de construction ou d'argument.

L'instruction module

Utilisez l'instruction module pour créer un module contenant des ressources requises autonomes. Vous pouvez exporter ou importer ces ressources sous forme d'objets AQL vers ou à partir d'autres modules.

Syntaxe

module <module-name\>;

Description

  • <module-name\>

    Déclare que le fichier en cours fait partie du module nommé <module-name\>. Cette valeur de nom de module (module-name) doit correspondre à un identificateur simple. Les identificateurs entre guillemets ne peuvent pas être utilisés comme noms de module.

    Chaque fichier AQL à l'intérieur du module doit avoir exactement une seule déclaration de module et cette déclaration doit constituer la première instruction dans chaque fichier. Cette déclaration établit un espace de nom identique à module-name. Toutes les vues (et les autres objets, tels que les dictionnaires, les tables et les fonctions) déclarés dans les fichiers AQL à l'intérieur de ce module se trouvent dans cet espace de nom unique. Ils sont accessibles à tous les fichiers AQL figurant dans cet espace de nom.

    Tous les fichiers qui sont déclarés comme faisant partie du module <module-name\> doivent se trouver dans un dossier appelé <module-name\> pour appliquer cet espace de nom. Il n'existe aucun ordre particulier des fichiers AQL au sein du dossier de ce module. Le compilateur AQL examine tous les fichiers AQL du module et détermine l'ordre adéquat pour compiler toutes les vues, les dictionnaires, les tables et les fonctions déclarés dans le module.

Notes sur l'utilisation

  • Lorsque le fichier AQL sous-jacent ne fait pas partie d'un module (AQL modulaire) et qu'il est compilé en mode compatibilité, cette instruction n'est pas prise en charge.
  • Les dépendances en boucle entre les vues ne sont pas autorisées.
  • Les modules AQL ne prennent pas en charge les sous-modules.
  • Les fichiers AQL à l'intérieur de sous-dossiers du dossier de module de niveau supérieur sont ignorés.

Exemples

Exemple 1 : module sample

Dans l'exemple suivant, la vue TheMentions appartient au module nommé sample.

module sample;

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

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

L'instruction export

L'instruction export dans AQL est utilisée pour exporter un objet AQL du module actuel de sorte à pouvoir l'importer et l'utiliser dans d'autres modules.

Syntaxe

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

Description

  • view|dictionary|table|function

    Définit le type d'objet à exporter. Il peut s'agir d'un objet view, dictionary, table ou function.

  • <object-name\>

    Définit le nom de l'objet à exporter. <object-name\> peut être un identificateur simple ou un identificateur à guillemets doubles.

Notes sur l'utilisation

  • Vous ne pouvez pas exporter un objet AQL ayant été importé. Vous pouvez créer l'effet de réexporter l'objet view ou table dans le module actuel en créant un nouvel objet view :

    select * from <imported_view_name_or_table_name>;
    
  • Les instructions export view et output view présentées dans les exemples sont orthogonales les unes par rapport aux autres. Autrement dit, une vue de sortie n'est pas automatiquement une vue exportée mais elle peut être explicitement exportée à l'aide d'une instruction export. Une vue exportée n'est pas automatiquement une vue de sortie mais elle peut l'être explicitement en utilisant l'instruction output view. Dans les exemples, l'instruction export tente d'exporter la vue PersonName.FirstName, qui est une vue importée. Cette tentative entraîne une erreur, ce qui signifie que le développeur doit copier la vue importée dans une nouvelle vue, puis exporter cette nouvelle vue à la place.

Exemples

Exemple 1 : création de vues et de dictionnaires, puis exportation de ces objets pour les utiliser dans d'autres modules

Cet exemple crée les vues FirstName et NotFirstName. La vue FirstName collecte des informations sur les prénoms qui sont représentés dans le dictionnaire FirstNamesDictionary. L'autre vue collecte les noms restants lorsque vous excluez les prénoms. Deux dictionnaires sont nécessaires pour faciliter l'extraction de texte. Un dictionnaire contient tous les prénoms que vous voulez rechercher. Le second dictionnaire, LastNamesDictionary, contient les noms de famille que vous pouvez rechercher. Le dictionnaire FirstNamesDictionary est exporté pour qu'il puisse être utilisé dans d'autres modules. Les vues FirstName et NotFirstName sont également exportées pour qu'elles puissent être importées et utilisées dans d'autres modules comme le module person dans l'exemple 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;

Exemple 2 : importation de vues à utiliser mais exportation inappropriée entraînant une erreur

Cet exemple illustre l'importation de deux vues. Ces vues ont été exportées du module personName dans l'exemple 1. Le module person peut désormais importer et faire référence à ces vues. Cependant, ce module tente d'exporter une vue ayant été importée, FirstName, ce qui entraîne une erreur.

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;

Cette erreur est due au fait qu'une vue qui a été importée d'un module ne peut pas être exportée dans le module actuel. En outre, les vues exportées ne sont pas automatiquement des vues de sortie sauf si vous avez défini une vue de sortie avec l'instruction output view.

L'instruction import

Vous pouvez utiliser l'instruction import pour référencer des objets exportés à partir d'autres modules dans le contexte du module actuel.

Syntaxe

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

Description

  • view\|dictionary\|table\|function

    Identifie le type d'objet AQL à importer. Le type de l'objet est obligatoire.

  • <object-name\>

    <object-name\> peut être un identificateur simple ou un identificateur à guillemets doubles.

  • <module-name\>

    <module-name\> doit être un identificateur simple.

  • <alias\>

    Cette forme de l'instruction import, également connue comme alias import, importe l'objet AQL spécifié sous le nom <alias\> (et non le nom d'origine) dans l'espace de nom du module actuel. Vous pouvez référencer l'élément importé en utilisant un alias non qualifié ou un alias qualifié avec le nom du module actuel (c'est-à-dire le module dans lequel a été importé l'objet AQL). Vous ne pouvez pas utiliser originalModule.elementName car l'instruction alias import importe l'élément sous le nom de l'alias uniquement et pas sous le nom d'origine qualifié.

Notes sur l'utilisation

  • Une instruction import sans spécification d'alias importe l'objet AQL indiqué dans le module actuel. Elle rend l'objet AQL accessible aux instructions AQL définies dans le module actuel sous son nom qualifié <original\_module\_name\>.<object-name\>.

  • L'instruction import n'est utilisée que pour importer des objets AQL à partir de modules différents du module actuel. Un objet qui est déclaré dans un fichier AQL du module est visible de tous les autres fichiers AQL figurant dans ce même module. Une instruction import place les objets dans le contexte du module actuel et non pas dans le contexte du fichier actuel. Par conséquent, une vue importée par le fichier 1.aql dans le module A est visible du fichier 2.aql à l'intérieur du même module sans avoir à ajouter d'autres instructions import.

  • Toutes les instructions import doivent figurer immédiatement après la déclaration du module et doivent précéder tout autre type d'instruction. Seuls les objets AQL exportés explicitement d'un module peuvent être importés dans un autre module. Si cette condition requise n'est pas respectée, une erreur de compilation se produit.

  • Une erreur de compilation se produit lorsqu'une instruction import view entraîne un conflit de nom avec une instruction create view ou d'autres instructions import au sein du même module (pas seulement au sein du fichier actuel). Cette restriction s'applique à l'import d'autres objets en plus des objets de type view.

  • Le compilateur AQL respecte les conventions de dénomination utilisées dans les versions précédentes d'AQL :

    • Un module ne peut pas contenir d'objet view ou table portant le même nom.
    • Par contre un objet dictionary peut avoir le même nom qu'un objet table ou view.
    • Un objet function avec le même nom qu'un objet table, view ou dictionary est autorisé.
  • Une erreur de compilation apparaît lorsque différentes instructions import au sein d'un ou de plusieurs fichiers AQL dans le module attribuent le même nom à différents objets AQL.

  • Une erreur de compilation se produit lorsqu'un fichier AQL à l'intérieur d'un module tente de référencer une autre vue exportée d'un module sans utiliser l'instruction import view. La même chose s'applique aux objets dictionary, table ou function.

  • Lorsque deux fichiers AQL à l'intérieur d'un module importent le même objet view X d'un autre module sous deux alias différents, par exemple A et B, les deux alias sont considérés comme des synonymes. Cette règle s'applique également aux objets table, dictionary et function.

Exemples

Exemple 1 : création de vues que vous exportez pour les importer dans d'autres modules

Cet exemple crée deux vues, FirstName et NotFirstName. La vue FirstName collecte des informations sur les prénoms qui sont représentés dans le dictionnaire FirstNamesDictionary. La seconde vue collecte les noms qui restent lorsque vous excluez les prénoms. Deux dictionnaires sont nécessaires pour faciliter l'extraction de texte. Un dictionnaire contient tous les prénoms que vous voulez rechercher. Le second dictionnaire, LastNamesDictionary, contient les noms de famille que vous pouvez rechercher. Les vues FirstName et NotFirstName sont exportées pour qu'elles puissent être importées et utilisées dans d'autres modules comme le module person dans les exemple 2 et 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;

Exemple 2 : importation de la vue FirstName en utilisant l'instruction alias import

Cet exemple importe l'une des vues qui ont été créées et exportées dans l'exemple 1. Ensuite, la vue PersonFirstName est générée afin que ses résultats puissent être visualisés.

L'instruction sample import est désignée par alias import. Elle importe la vue FirstName, sans qualificateur de module, dans l'espace de nom du module actuel, person. La vue importée est accessible uniquement avec le nom d'alias PersonFirstName et sous aucune autre forme. Par exemple, vous ne pouvez pas faire référence à la vue importée avec personName.FirstName car cette vue est importée uniquement via le nom d'alias.

module person;

`import view FirstName from module personName as PersonFirstName;`

output view PersonFirstName;

Exemple 3 : importation de la vue NotFirstname sans utiliser l'instruction alias import

Cet exemple d'instruction import importe la vue avec le nom qualifié personName.NotFirstName (et non pas le nom qui n'est pas qualifié de la vue) dans l'espace de nom du module actuel, person. Faites toujours référence à la vue importée en utilisant uniquement le nom qualifié. Tout autre mode de référence est marqué comme erreur de compilation.

module person;

`import view NotFirstName from module personName;`


output view personName.NotFirstName;

L'instruction import module

Vous pouvez utiliser l'instruction import module pour importer et réutiliser des modules AQL existants.

Syntaxe

 import module <module-name\>;

Description

  • <module-name\>

    Indique le module à importer. <module-name\> doit être un identificateur simple.

Notes sur l'utilisation

  • L'instruction import n'est utilisée que pour importer des objets AQL d'autres modules et non pas du module actuel.

  • Toutes les instructions import doivent figurer immédiatement après la déclaration du module et doivent précéder tout autre type d'instruction. Seuls les objets AQL exportés explicitement d'un module peuvent être importés dans un autre module. Si cette condition requise n'est pas respectée, une erreur de compilation se produit.

  • Une erreur de compilation se produit lorsqu'une instruction import view entraîne un conflit de nom avec une instruction create view ou une autre instruction import au sein du même module (pas seulement au sein du fichier actuel). Cette restriction s'applique à l'import d'autres objets AQL en plus des objets de type view.

  • Une erreur de compilation se produit lorsqu'un fichier AQL à l'intérieur d'un module tente de référencer une autre vue exportée d'un module sans utiliser l'instruction import view. La même chose s'applique aux objets dictionary, table ou function.

  • Si deux fichiers AQL à l'intérieur d'un module importent le même objet view X d'un autre module sous deux alias différents, par exemple A et B, les deux alias sont considérés comme des synonymes. Cette règle s'applique également aux objets table, dictionary et function.

Exemples

Dans cet exemple, l'instruction import importe le nom qualifié des deux vues exportées, personName.FirstName et personName.NotFirstName. Toute vue qui n'est pas exportée par le module personName n'est pas importée dans le cadre de l'instruction import.

  • Exemple 1 : importation des vues FirstName et NotFirstName

    Cet exemple illustre toutes les vues exportées du module personName. Les vues FirstName et NotFirstName ont été créées dans la section d'exemple de l'instruction export.

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

L'instruction set default dictionary language

L'instruction set default dictionary language permet au développeur d'un extracteur de personnaliser l'ensemble de langues par défaut correspondant au dictionnaire pour le module conteneur.

Syntaxe

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

Description

  • <language codes\>

    Spécifie la langue de compilation et de correspondance pour les dictionnaires du module déclarés sans spécification with language as. Le jeu <language codes\> doit être une liste séparée par des virgules, sans espaces blancs autour de chaque code de langue. Si cette condition requise n'est pas respectée, vous pourrez obtenir une erreur de compilation.

    Cette instruction affecte les dictionnaires suivants :

    • Les dictionnaires déclarés de manière explicite dans le module actuel à l'aide de l'instruction create dictionary ou create external dictionary mais sans la clause with language as.
    • Les dictionnaires provenant de fichiers externes.
    • Dans une spécification de modèle d'une instruction extract pattern, les atomes de type 'string' et les atomes de type <'string' [match parameters]> sans spécification with language as explicite. Lorsque cette instruction est absente de l'intérieur d'un module, le composant d'exécution est défini par défaut sur le jeu de langues allemand, espagnol, anglais, français, italien et la langue non spécifiée x. Le jeu est : [de,es,en,fr,it,x_unspecified]. Un module ne peut contenir qu'une seule instance de cette instruction.

Notes sur l'utilisation

  • L'instruction set default dictionary language peut être mise à jour pour développer l'étendue des langues couvertes par l'extracteur. La possibilité d'ajouter des langues contribue à faciliter la personnalisation et la réutilisation d'extracteurs existants.

Exemples

Exemple 1 : spécification de langues à utiliser pour la correspondance avec les entrées du dictionnaire

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;

L'instruction require document with columns

En utilisant l'instruction require document with columns, vous pouvez définir le schéma de la vue spéciale Document au moment de la compilation. Cette définition de schéma spécifie la liste des champs requis et les types à rechercher dans chaque tuple de la vue Document.

Syntaxe

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

Description

  • <columnName\>

    Spécifie le nom de la colonne à utiliser dans le schéma. <columnName\> est un identificateur d'attribut, qui est un identificateur simple ou un identificateur à guillemets doubles.

  • <columnType\>

    Spécifie le type de colonne à utiliser dans le schéma de la vue Document. <columnType\> peut être l'un des types de données suivants : Integer, Float, Boolean ou Text.

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

    Spécifie les noms de colonne et les types supplémentaires dans le schéma de la vue Document. Ils suivent les mêmes règles que <columnName\> et <columnType\>.

Dans les versions antérieures d'AQL, le schéma de la vue spéciale Document était prédéfini pour un seul champ (text Text) ou deux champs (text text, label Text). Le choix entre ces schémas était déterminé lors de l'exécution. En utilisant l'instruction require document with columns, vous pouvez remplacer le schéma du document d'entrée par défaut lors de la compilation.

Notes sur l'utilisation

  • Pour le code AQL modulaire, la portée d'une instruction require document with columns correspond au module dans lequel elle est définie.
  • Une seule instruction require document with columns est autorisé par fichier AQL. Au sein d'un module unique ou d'un module générique, zéro, un ou plusieurs fichiers AQL peuvent comporter une instruction require document with columns. Tous les fichiers AQL à l'intérieur d'un module fusionnent leurs instructions require document with columns au niveau de l'ensemble du module pour former une instruction require document with columns à l'échelle du module. Cette instruction définit le schéma de la vue Document pour ce module. Si aucun des fichiers AQL d'un module ou d'un module générique ne contient d'instruction require, le module adopte un schéma par défaut pour la vue Document. Ce schéma est constitué de deux colonnes : (text Text, label Text). Aucune colonne par défaut n'est appliquée pour la vue spéciale Document si au moins un fichier AQL du module comporte une instruction require document with columns.
  • Lorsque plusieurs modules sont combinés pour former un extracteur, le schéma de la vue Document de l'extracteur complet est défini par l'union sans doublon des schémas de la vue Document pour chaque module. Une exception est émise lorsqu'il s'avère qu'une colonne identifiée parmi les différentes instructions require document with columns entre en conflit au niveau des exigences en termes de type entre plusieurs modules. Par exemple, un module nécessite une colonne X avec le type Y alors qu'un autre module chargé avec nécessite une colonne X avec le type Z.
  • Une exception est émise lorsque vous exécutez un extracteur si le tuple du document d'entrée fourni ne contient pas la totalité des colonnes requises. Vous obtenez également une exception si une colonne n'est pas conforme au type requis correspondant associé.
  • Lorsque l'instruction require document with columns figure dans un module, toutes les colonnes de la vue spéciale Document référencée doivent être déclarées dans au moins une instruction require document with columns. L'instruction peut se trouver dans différents fichiers AQL au sein du même module. Cependant, toutes les instructions de type require document with columns seront fusionnées au niveau du module pour former une instruction require document with columns à l'échelle du module.

Exemples

Exemple 1 : instruction require document avec des colonnes de types similaires

L'exemple suivant définit un schéma de document contenant quatre champs du même type. Cet exemple de code AQL s'attend à ce que chaque tuple de document de la collection de données contienne quatre colonnes comme indiqué dans le schéma du document.

Consultez les formats de document JSON pour obtenir des détails sur la création d'un document qui soit conforme à un schéma.

module person;

-- Require document statement with similar field types

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

Exemple 2 : instruction require document avec différents types de colonne

L'exemple suivant définit un schéma de document contenant des colonnes avec des types de champ différents.

module sample;

-- Require document statement with varying field types

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

Exemple 3 : fusion de schémas de document

L'exemple suivant montre comment fusionner des schémas de document qui utilisent les fichiers first.aql, last.aql et 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;

Le schéma fusionné est (firstName Text, lastName Text, socialSecurityNo Integer).

L'instruction create view

Les composants de niveau supérieur d'un extracteur AQL sont ses vues. Les vues sont des instructions logiques qui définissent (sans forcément calculer) un ensemble de tuples.

Syntaxe

L'instruction create view peut prendre trois formes différentes. La forme la plus simple définit une vue logique constituée des tuples d'une seule instruction select ou extract. La seconde forme est une forme à plusieurs jointures qui définit une vue comprenant les tuples qui proviennent de l'union de plusieurs ensembles d'instructions select ou extract. La troisième forme définit une nouvelle vue contenant les différences entre les tuples à partir de deux instructions 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\>);

Description

  • <viewname\>

    <viewname\> peut être un identificateur simple ou un identificateur à guillemets doubles. Il ne peut pas contenir le point (.).

  • <select or extract statement\>

    L'instruction select ou extract crée une sortie utilisée pour calculer les tuples de la vue qui les contient.

Notes sur l'utilisation

  • Les noms de vue sont sensibles à la casse. Par exemple, Person, PERSON et person sont des noms de vue différents.
  • Deux vues au sein du même module AQL ne peuvent pas partager le même nom, ce qui en ferait des doublons. Cependant, il peut exister deux vues avec le même nom dans deux modules différents, car leurs noms qualifiés complets sont uniques.
  • Par défaut, une vue qui est définie par l'instruction create view n'est pas une vue de sortie tant qu'elle n'est pas spécifiée en tant que telle.
  • Les instructions select ou extract des formes union all et minus, doivent avoir un schéma de sortie compatible. Deux schémas sont considérés comme compatibles pour une opération union ou minus s'ils comportent le même nombre de colonnes, que leurs noms de colonne sont dans le même ordre et qu'ils ont des types de données compatibles :
    • Les champs avec des données du même type sont compatibles avec les opérations union ou minus.
    • Les types de données Span et Text sont compatibles avec les opérations union ou minus. Dans le cas d'une union entre un type Span ou Text, le type de sortie est Span. Toutefois, les objets de type Text ne sont pas convertis automatiquement en type Span (la conversion automatique se produit uniquement lorsqu'elle est demandée par des appels de fonction).
    • Deux types ScalarLists sont compatibles avec les opérations union ou minus indépendamment du type scalaire sous-jacent.

Exemples

Exemple 1 : création d'une vue avec une instruction select ou extract

Dans l'exemple ci-dessous, la vue Phone utilise une instruction extract pour préparer ses tuples. La vue PhoneNumber utilise une instruction select pour extraire des champs spécifiques de la vue 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;

Exemple 2 : création d'une vue avec l'instruction Union All

La vue AllPhoneNums prépare un ensemble constitué de l'union des tuples des vues Phone et Extension. Les deux vues ainsi réunies ont le même schéma.

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

Exemple 3 : création d'une vue avec l'instruction Minus

L'exemple suivant montre comment utiliser minus pour filtrer les tuples indésirables d'un ensemble de tuples.

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

Exemple 4 : compatibilité de schéma pour l'instruction minus

Il est important de noter que les étendues dans les différents textes cible ne sont pas du même type. Examinez l'exemple de code AQL suivant qui explique cette différence en utilisant un littéral de type chaîne (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);

Au lieu d'obtenir la sortie attendue avec une liste de tuples vide, la sortie est un ensemble d'enregistrements avec la valeur de champ 'a string'.

Bien que le contenu des vues OneString et TheSameString semble identique, les valeurs de texte réelles ont des objets AQL sous-jacents différents. Le type de OneString.match est 'Span over OneString.match'. Le type de TheSameString.match est 'Span over TheSameString.match'. Comme les types de champ sont différents, ils ne sont pas compatibles à des fins de comparaison.

Pour obtenir la sortie souhaitée à savoir la liste de tuples vide, vous devez comparer des valeurs de type identique. Dans l'exemple suivant, la fonction GetString() convertit des objets de type Span en objets de type String pour transmettre des types compatibles à l'opération minus.

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

Documentation de l'instruction create view avec AQL Doc

Le commentaire AQL Doc pour une instruction create view contient les informations suivantes :

  • Description générale de la vue.
  • @field pour chaque nom de colonne dans la vue.

Exemple

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

L'instruction output view

L'instruction output view définit une vue comme vue de sortie. Le composant d'exécution ne renvoie que les tuples de vues marquées comme étant des vues de sortie (output views). Le compilateur AQL compile uniquement les vues marquées avec output ou export ou les vues accessibles à partir de vues marquées avec output ou export.

Syntaxe

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

Description

  • <view-name\>

    Nom de la vue qui doit être une vue de sortie, connue dans l'espace de nom du module actuel. <view-name\> est un identificateur simple ou un identificateur à guillemets doubles. La vue intégrée Document ne peut pas être une vue de sortie.

  • [as '<alias\>']*

    Définit un nom <alias\> pour la vue de sortie. Lorsque l'alias facultatif n'est pas spécifié, la vue est générée sous les noms suivants :

    • Dans la version modulaire d'AQL, la vue est produite sous le nom <module-name\>.<view-name\>, où <module-name\> est le nom du module dans lequel la vue est définie à l'origine (qui peut être différente du module dans lequel la vue est produite).
    • Dans AQL 1.4 ou une version antérieure, la vue est produite sous le nom de <view-name\> L'instruction output ... as <alias\> est utile lorsque vous personnalisez un extracteur pour différents domaines. L'utilisation du nom <alias\> lorsque vous définissez une vue de sortie garantit que les noms de sortie sont identiques entre les différentes implémentations de la personnalisation.

    Le nom <alias\> ne peut pas être utilisé dans une autre instruction select ou export. Vous devez entourer <alias\> de guillemets simples et le nom <alias\> peut contenir des points.

Notes sur l'utilisation

  • Lorsqu'un extracteur AQL s'exécute, il calcule les tuples obtenus pour chaque vue définie comme une vue de sortie. Les tuples d'une vue qui ne serait pas une vue de sortie sont également calculés mais uniquement lorsqu'ils sont nécessaires pour calculer les tuples qui résultent d'une vue de sortie.
  • En langage AQL modulaire, l'instruction output view génère les tuples de la vue sous le nom complet de la vue qui est qualifié par son nom de module. Examinez l'exemple suivant dans lequel l'instruction output view Person; produit la sortie de la vue personModule.Person :
module personModule;

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

output view Person;

Ce comportement s'applique à toute vue de sortie sans alias, que la vue soit générée dans le module dans lequel elle est définie ou dans un module dans lequel elle est importée, même lorsque l'importation est effectuée à l'aide d'une instruction alias import. Par exemple, dans la vue de sortie MyPerson, cet exemple obtient la vue générée sous son nom qualifié d'origine personModule.Person et non pas sous son alias local MyPerson.

module employeeModule;

import view Person from module personModule as MyPerson;

output view MyPerson;
  • L'instruction output alias est utile lorsque vous générez des bibliothèques d'extracteurs dans lesquelles le même type d'entité peut avoir de nombreuses implémentations différentes, selon le domaine d'application ou la langue des documents d'entrée. Le principal avantage de l'utilisation d'un alias lorsque vous définissez une vue de sortie est d'assurer une nomenclature cohérente des vues de sortie. Une nomenclature cohérente est attendue par la logique du programme d'un utilisateur lorsque vous traitez plusieurs modules qui génèrent chacun une vue similaire d'un point de vue sémantique. En langage AQL modulaire, lorsqu'un nom d'alias est utilisé dans une instruction output view, les tuples d'une vue sont générés sous le nom d'alias indiqué. Par exemple, le code suivant génère les résultats sous le nom d'alias PersonAlias et le nom d'alias n'est pas qualifié avec le préfixe du module.
module personModule;

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

output view Person as 'PersonAlias';

Exemples

Les exemples suivants contiennent deux modules, personModuleFrench et personModuleEnglish. Chaque module génère une vue, nommée PersonNameFrench et PersonNameEnglish. Supposons des modules similaires dont les vues de sortie respectives sont des variantes sémantiques d'un extracteur de noms de personne. Ces modules sont personnalisés pour les différentes langues avec la variance de personnalisation de cette vue pour une langue d'entrée indiquée. En définitive, un utilisateur peut envisager un programme pour utiliser des modules dans lesquels la vue de sortie recherchée est nommée PersonName, quels que soient les modules traités. Cette attente est normale car chaque module qui est personnalisé pour une langue, un domaine ou à d'autres fins doit nécessairement produire différents résultats. Le consommateur de ces modules n'a pas besoin de modifier l'algorithme de son programme pour s'adapter aux différents noms de vue de sortie lorsque la sémantique sous-jacente est similaire.

Dans cet exemple, comme l'alias PersonName est utilisé, le consommateur n'a pas besoin de modifier le nom de la vue recherchée. Les résultats peuvent néanmoins varier en fonction des modules qui sont traités. Dans l'exemple, les correspondances obtenues sont en français (Exemple 1) et en anglais (Exemple 2).

Exemple 1 : correspondances obtenues pour le français

L'exemple suivant définit une vue PersonNameFrench et la génère sous un nom d'alias neutre en termes d'implémentation, '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';

Exemple 2 : correspondances obtenues pour l'anglais

L'exemple suivant définit une vue PersonNameEnglish et la génère sous un nom d'alias neutre en termes d'implémentation, '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';

Le consommateur de ces exemples de module peut accéder aux tuples générés via le nom d'alias 'PersonName'. Il n'a pas besoin de connaître le module effectif à partir duquel sont extraits les résultats.

L'instruction extract

L'instruction extract est utilisée pour extraire des fonctions de base directement à partir de texte.

Syntaxe

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

Description

  • <select list\>

    Liste séparée par des virgules d'expressions de sortie. Les résultats de ces expressions sont renvoyés en sortie de l'instruction extract, avec les tuples générés par l'évaluation de la spécification d'extraction. Le format de la liste <select list\> est le même que celui de la liste <select list\> d'une instruction select.

  • <extraction specification\>

    Applique la spécification d'extraction sur tous les tuples des vues qui sont définies dans la liste <from list\>. Renomme les colonnes des tuples en fonction de leurs alias correspondants qui sont spécifiés dans l'instruction extract. Vous pouvez utiliser l'une des spécifications d'extraction suivantes :

    • Expressions régulières
    • Dictionnaires
    • Scissions
    • Blocs
    • Partie du discours
    • Modèles de séquence
  • <from list\>

    Liste séparée par des virgules qui constitue la source des tuples à partir desquels sélectionner les fonctions. Le format de la liste <from list\> est similaire au format de la liste <from list\> de l'instruction select. Toutefois, si l'instruction extract n'a pas de spécification de modèle, <from list\> peut contenir un élément unique.

  • [having <having clause\>]

    Spécifie un prédicat de filtrage (dans la clause <having clause\>) qui est appliqué à chaque tuple de sortie extrait. Les noms de zone spécifiés dans la clause <having clause\> font référence à tous les alias qui sont spécifiés dans la liste <select list\>. Cette clause est facultative.

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

    Définit la façon de gérer les étendues qui se chevauchent, comme défini dans la consolidation <policy\>. Dans cette spécification, <column\> doit être le nom d'un champ de sortie, qui fait partie de l'instruction extract. Cette clause est facultative.

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

    Limite le nombre de tuples de sortie de chaque document à la valeur maximale spécifiée. Cette clause est facultative.

Notes sur l'utilisation

La sémantique de l'instruction extract se décline comme suit :

  • Evaluation de la spécification d'extraction sur chaque tuple de la relation d'entrée. Pour chaque résultat généré par l'extraction, un tuple de sortie contenant les valeurs extraites, ainsi que toutes les colonnes du tuple d'origine qui ont été spécifiées dans la liste <select list\>, est produit.
  • Renommez les colonnes du tuple de sortie en fonction des alias spécifiés dans le cadre de la liste <select list\> et de la spécification <extraction specification\>.
  • Application des prédicats éventuels dans la clause facultative having au tuple de sortie obtenu.
  • Consolidation des tuples qui transmettent les prédicats en fonction de la clause facultative consolidation et ajout des tuples obtenus dans la sortie.
  • Si la clause facultative limit est présente, limitation de la sortie au nombre spécifié de tuples pour chaque document.

La sémantique de la clause from d'une instruction extract pattern est différente de celle des autres formes d'instructions extract qui n'ont pas de spécification de modèle. Si au moins l'une des vues de la liste <from list\> ne contient pas de tuples sur un document particulier, la sortie de l'instruction extract est vide. La sortie est vide car l'ensemble de toutes les combinaisons de tuples des vues d'entrée est vide.

Dans le cas de figure particulier des instructions extract pattern, la clause from est une marque de réservation qui déclare les noms des relations impliquées dans la spécification de modèle. La sémantique de l'instruction est gérée uniquement par la spécification de modèle. La sortie de l'instruction peut notamment ne pas être vide même si certaines vues d'entrée sont vides.

Exemples

Exemple 1 : extraction de numéros de téléphone à partir d'une vue prédéfinie

Cet exemple d'instruction extract évalue une expression régulière pour les numéros de téléphone des Etats-Unis sur le texte d'entrée représenté par la vue prédéfinie Document. La sortie est ensuite limitée aux trois premiers numéros de téléphone identifiés par chaque document. Les noms de champ dans la clause having font référence aux alias indiqués au début de l'instruction 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;

Exemple 2 : extraction de blocs de mots avec une majuscule

Dans cet exemple, l'instruction extract identifie des blocs de deux à trois mots avec une majuscule. Dans AQL, un bloc fait référence à une étendue contiguë d'unités lexicales, dans ce cas deux à trois unités lexicales. Cet exemple utilise également une règle de consolidation pour exclure les blocs contenus dans des blocs plus volumineux de l'ensemble de tuples en sortie.

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

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

La clause consolidate est appliquée au champ capswords par la spécification extract blocks. La différence réside dans le fait que le champ cible référencé par la clause consolidation est un champ de sortie de l'instruction extract. Le champ cible de l'instruction select est un champ d'entrée. Ce comportement est similaire à celui de la clause having.

Exemple 3 : instruction extract ou select imbriquée en tant que nom de vue

La vue d'entrée d'une instruction extract peut être un nom de vue comme dans l'exemple 2 ou une instruction extract ou select comme dans l'exemple ci-après :

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;

Exemple 4 : extraction d'une instruction avec une liste de sélection (select list)

Dans cet exemple, nous procédons à l'extraction d'un modèle et nous sélectionnons en même temps plusieurs attributs dans les vues d'entrée.

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;
  • Expressions régulières Utilisez une spécification d'extraction d'expression régulière pour identifier les modèles contenus dans l'expression régulière dans le texte d'entrée.
  • Dictionnaires Utilisez la spécification d'extraction de dictionnaire pour extraire des chaînes du texte d'entrée figurant dans un dictionnaire de chaînes.
  • Scissions Utilisez la spécification d'extraction de scission (split) pour répartir une large étendue en plusieurs étendues de plus petite taille.
  • Blocs Utilisez la spécification d'extraction de blocs (blocks) pour identifier les blocs d'étendues contiguës dans le texte d'entrée.
  • Partie du discours Utilisez la spécification d'extraction de partie du discours (part-of-speech) pour identifier les emplacements des différentes parties du discours dans le texte d'entrée.
  • Modèles de séquence Utilisez la spécification d'extraction de modèle pour réaliser des correspondances de modèles sur un document d'entrée et d'autres étendues extraites du document d'entrée.

Expressions régulières

Utilisez une spécification d'extraction d'expression régulière pour identifier les modèles contenus dans l'expression régulière dans le texte d'entrée.

Syntaxe

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

Description

  • regex[es] /<regex1\>/

    Indique les expressions régulières à utiliser dans l'extraction. Par défaut, AQL utilise la syntaxe Perl pour les expressions régulières, ce qui signifie que les littéraux d'expression régulière sont placés entre deux barres obliques (//). Les séquences d'échappement d'expressions régulières sont prioritaires par rapport à d'autres caractères d'échappement. AQL autorise l'utilisation d'expressions régulières dans la syntaxe de chaîne SQL, de sorte qu'une expression régulière pour les numéros de téléphone aux Etats-Unis puissent être exprimée selon l'un des exemples suivants :

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

    Répertorie d'autres expressions régulières à utiliser dans l'extraction.

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

    Indique une combinaison d'indicateurs pour contrôler les correspondances d'expressions régulières. Ce paramètre est facultatif. Ces indicateurs correspondent à un sous-ensemble d'indicateurs définis dans l'implémentation Java™. Si la chaîne d'indicateurs n'est pas fournie, AQL utilise uniquement l'indicateur DOTALL par défaut.

    Pour spécifier plusieurs indicateurs, séparez-les par le caractère |. Par exemple, pour spécifier une correspondance multi-lignes, une correspondance qui n'est pas sensible à la casse et le pli de casse Unicode, utilisez la chaîne d'indicateurs 'MULTILINE|CASE_INSENSITIVE|UNICODE'.

  • [<token spec\>]

    Indique d'établir une correspondance d'expression régulière qu'aux limites d'unités lexicales.

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

    Les contraintes liées aux unités lexicales sont une partie facultative de la spécification. Si ces contraintes sont omises, AQL renvoie la correspondance la plus longue sans chevauchement à chaque position de caractère dans le texte d'entrée. S'il existe des contraintes d'unité lexicale, l'instruction extract renvoie la correspondance la plus longue en fonction des limites d'unité lexicale incluses dans la plage de longueur des unités lexicales. Chaque correspondance renvoyée doit commencer au début d'une unité lexicale et se terminer à la fin d'une unité lexicale. Si plusieurs correspondances qui se chevauchent, l'instruction extract les renvoie toutes.

    L'emplacement des limites d'unités lexicales dépend du marqueur sémantique utilisé par le composant d'exécution pour segmenter le document. Si le moteur utilise le marqueur sémantique standard, l'unité lexicale est définie sous forme de séquence de caractères de mot ou d'un seul signe de ponctuation.

    Examinez par exemple la chaîne suivante :

    "The fish are pretty," said the boy.
    

    Les limites des unités lexicales sont identifiées à ces emplacements :

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

    Nom de la vue et nom de la colonne à laquelle est appliquée l'expression régulière.

  • <grouping spec\>

    Détermine comment traiter la capture de groupes dans l'expression régulière. Les groupes de capture sont des régions de la correspondance de l'expression régulière identifiées par des parenthèses dans l'expression d'origine. Par exemple, l'expression (fish)(cakes) a trois groupes de capture :

    • Group 0 correspond à la correspondance totale avec fishcakes.
    • Group 1 correspond à fish.
    • Group 2 correspond à cakes. Lorsque vous spécifiez des ID de groupe dans la clause return de la syntaxe, chacun de ces ID doit correspondre à un groupe valide au sein de chaque expression régulière spécifiée dans la clause extract regex dans la syntaxe.

    Voici le format de la spécification de groupe :

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

    Pour renvoyer uniquement le groupe 0 (la correspondance entière), vous pouvez utiliser un format alternatif plus court que dans l'exemple 1. Ce format est équivalent à return group 0 as <name>. <name> peut être un identificateur simple ou un identificateur à guillemets doubles.

Notes sur l'utilisation

  • En général, AQL prend en charge les mêmes fonctions que l'implémentation d'expression régulière Java 5 comme indiqué dans [Class Pattern: java.util.regex. Le composant d'exécution contient plusieurs implémentations de moteur d'expressions régulières, notamment l'implémentation intégrée de Java. Lors de la compilation, l'optimiseur examine chaque expression régulière et choisit le moteur le plus rapide pouvant exécuter l'expression.

  • D'autres moteurs d'exécution peuvent avoir une sémantique légèrement différente pour certains cas particuliers. Par exemple, AQL ne garantit pas l'ordre dans lequel ces autres solutions sont évaluées.

    Par exemple, supposons qu'une instruction extract corresponde à l'expression régulière /fish|fisherman/, sur le texte 'fisherman'. L'instruction peut correspondre soit à 'fish' ou à 'fisherman', en fonction du moteur d'expressions régulières utilisé en interne.

Chaîne d'indicateurs AQL Indicateur Java Description
CANON_EQ CANON_EQ Equivalences canoniques : les différents codages Unicode d'un même caractère sont considérés comme équivalents.
CASE_INSENSITIVE CASE_INSENSITIVE La recherche de correspondance n'est pas sensible à la casse. Par défaut, la recherche de correspondance qui n'est pas sensible à la casse considère que la correspondance est établie uniquement avec les caractères figurant dans le jeu de caractères US-ASCII. Une recherche de correspondance qui n'est pas sensible à la casse et tient compte des caractères Unicode peut être activée en spécifiant l'indicateur UNICODE avec cet indicateur.
UNICODE UNICODE_CASE Si la recherche de correspondance n'est pas sensible à la casse, utiliser le pli de casse Unicode pour déterminer si deux caractères sont équivalents dans le cadre d'une comparaison insensible à la casse de sorte que l'opération soit conforme à la norme Unicode. Par défaut, la recherche de correspondance insensible à la casse suppose que seuls les caractères du jeu de caractères US-ASCII sont pris en compte. Remarque : le comportement de cet indicateur n'est pas défini lorsqu'il est utilisé sans l'indicateur CASE_INSENSITIVE.
DOTALL DOTALL Faire en sorte que le signe point (.) corresponde à tous les caractères, y compris les retours à la ligne.
LITERAL LITERAL Traiter l'expression comme une séquence de caractères littéraux, en ignorant les séquences d'échappement d'expressions régulières normales.
MULTILINE MULTILINE Faire en sorte que les caractères ^ et $ correspondent au début et à la fin d'une ligne, contrairement au début et à la fin du texte d'entrée intégral.
UNIX_LINES UNIX_LINES Traiter uniquement le caractère de retour à la ligne UNIX™ comme un retour à la ligne en ignorant le caractère de retour chariot \r.
  • Suivez ces directives pour rendre vos extracteurs plus rapides en termes d'exécution et plus faciles à gérer :
    • Evitez les expressions régulières longues et complexes et utilisez des expressions régulières plus réduites combinées à des instructions AQL.
    • Evitez d'utiliser inutilement lookahead et lookbehind dans les expressions régulières. Vous pouvez obtenir le même effet en ajoutant des prédicats dans la clause having de l'instruction extract.
    • Utilisez des contraintes d'unités lexicales dans vos spécifications d'extraction d'expressions régulières dans la mesure du possible.

Exemples

Exemple 1 : utilisation d'équivalence canonique Unicode pour déterminer les correspondances

Cet exemple vous montre comment rechercher des mots avec une majuscule qui n'ont pas de nom donné. L'équivalence canonique de caractères Unicode est utilisée pour déterminer les correspondances. Notez l'utilisation de l'indicateur ‘CANON_EQ’ et que regex s'applique aux unités lexicales :

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

Exemple 2 : utilisation des groupes de capture

L'exemple suivant illustre l'utilisation des groupes de capture dans une instruction extract regex. Le code extrait les champs correspondant à un numéro de téléphone aux Etats-Unis en utilisant des groupes de capture :

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;

Exemple 3 : application de plusieurs expressions régulières sur le texte d'entrée

Vous pouvez spécifier plusieurs expressions régulières dans la même instruction extract regex en utilisant la syntaxe 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;

Exemple 4 : utilisation inadéquate de la spécification de groupes

L'expression régulière figurant dans cet exemple de code ne contient pas group -1 ni group 3000. Il s'agit d'une erreur de compilation.

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

Dictionnaires

Utilisez la spécification d'extraction de dictionnaire pour extraire des chaînes du texte d'entrée figurant dans un dictionnaire de chaînes.

Syntaxe

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

Description

  • '<dictionary\>'

    Se rapporte à un dictionnaire créé en utilisant l'instruction create dictionary ou create external dictionary ou un fichier de dictionnaire dans le système de fichiers.

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

    Fait référence à d'autres dictionnaires à utiliser pour l'extraction.

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

    Contrôle la correspondance par rapport au dictionnaire. Actuellement, deux options sont prises en charge :

    • Exacte

      Fournit une correspondance exacte, sensible à la casse.

    • IgnoreCase

      Fournit une correspondance qui n'est pas sensible à la casse.

Si aucun indicateur n'est spécifié, le dictionnaire établit les correspondances en fonction d'un indicateur qui a été spécifié lorsqu'il a été créé. Si aucun indicateur n'est spécifié lors de sa création, les correspondances sont établies en utilisant l'indicateur IgnoreCase.

Notes sur l'utilisation

  • Les dictionnaires sont toujours évalués en fonction des limites d'unités lexicales. Plus précisément, une entrée de dictionnaire correspond à une région du texte si la première unité lexicale de l'entrée correspond à la première unité lexicale de la région du texte, la seconde unité lexicale de l'entrée correspond à la seconde unité lexicale de la région du texte, et ainsi de suite. Les caractères compris entre deux unités lexicales successives sont ignorés.

    Par exemple, supposons que votre modèle de segmentation utilise des blancs, ce qui convient à une langue comme l'anglais. Supposons également que le texte d'entrée soit "Let’s go fishing!" Si un dictionnaire est constitué du terme go fish, il n'existe aucune correspondance dans le texte Let's go fishing!. Cependant, si le dictionnaire comprend l'entrée go fishing (notez qu'il y a deux blancs entre go et fishing), il existe une correspondance dans le texte Let's go fishing!. Le caractère blanc indique que go et fishing constituent deux unités lexicales distinctes. S'il y a un ou plusieurs blancs entre les deux unités lexicales go et fishing dans le texte d'entrée, il y a bien une correspondance.

    Pour chaque correspondance d'une entrée de dictionnaire dans le texte d'entrée, l'instruction extract dictionary génère un tuple de sortie.

Exemples

Exemple 1 : extraction de termes à partir de fichiers de dictionnaire

Rechercher des noms de personne en utilisant des fichiers de dictionnaire de prénoms et de noms de famille avec une correspondance sensible à la casse.

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

Voici un exemple de contenu du dictionnaire last.dict :

#Dictionary for surnames
Anthony
Aparicio
Cate
Lehmann
Radcliff

Voici un exemple de contenu du dictionnaire first.dict :

#Dictionary for given names
Aaron
Candra
Freeman
Mathew
Matthew
Zoraida

Remarque :

  • Un système de fichiers de dictionnaire directement référencé dans une instruction extract dictionary ne peut pas être configuré de manière explicite avec un ensemble de langues pour que les dictionnaires puissent être compilés et appliqués en phase d'exécution. A la place, l'ensemble de langues est indiqué avec l'instruction set default dictionary language si le module contient cette instruction.

    Par conséquent, la référence directe des fichiers de dictionnaire dans une instruction extract dictionary n'est pas recommandée et pourrait cesser à l'avenir. La pratique privilégiée consiste à définir un objet de dictionnaire de manière explicite en utilisant l'instruction create dictionary from file, puis d'utiliser ce dictionnaire dans l'instruction extract.

  • Le compilateur et le composant d'exécution tentent de localiser les fichiers de dictionnaire référencés dans les instructions AQL sous le chemin de recherche configuré.

Exemple 2 : extraction de termes à partir d'un dictionnaire en ligne

Recherchez des conjonctions en utilisant un dictionnaire en ligne et la correspondance par défaut n'est pas sensible à la casse.

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

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

Scissions

Utilisez la spécification d'extraction de scission (split) pour répartir une large étendue en plusieurs étendues de plus petite taille.

Syntaxe

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

Description

La spécification d'extraction de scission admet deux arguments :

  • Une colonne contenant des étendues de texte cible plus longues.
  • Une colonne contenant les points de scission.

L'algorithme de scission fonctionne en deux phases sur la vue d'entrée. La première phase regroupe tous les tuples d'entrée par colonne cible. La seconde phase passe en revue les tuples dans chaque groupe en divisant la colonne cible par chaque valeur de la colonne de scission.

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

    Indique les points de scission pour l'extraction.

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

    Indique comment traiter les points à l'extrémité gauche et droite de chaque résultat. Cet argument est facultatif

    • Si retain left split point est indiqué, chaque étendue de sortie contient également le point de scission à sa gauche, le cas échéant.
    • Si retain right split point est indiqué, le système fait en sorte que chaque étendue de sortie contienne le point de scission à sa droite.
    • L'extraction avec scission accepte également les valeurs null comme points de scission. Pour chaque valeur de ce type, l'extraction renvoie un tuple contenant l'étendue d'entrée complète.
  • <name\>.<column to split\>

    Indique la colonne cible pour l'extraction.

  • <output name\>

    Définit le nom de la sortie de l'extraction.

Exemples

Exemple 1 : points de scission et clause retain

Si les points de scission sont tous des instances du mot fish dans l'expression fish are swimming in the fish pond, les différentes versions de la clause retain ont les effets suivants :

  • Omission de la clause retain

    " are swimming in the " et " pond"

  • Conservation du point de scission à droite

    " are swimming in the fish" et " pond"

  • Conservation du point de scission à gauche

    "fish are swimming in the " et "fish pond"

  • Conservation des deux points de scission

    "fish are swimming in the fish" et "fish pond"

Exemple 2 : extraction avec scission

Cet exemple scinde le document en deux phrases. Il utilise d'abord une expression régulière pour identifier les limites de la phrase, puis utilise la spécification d'extraction avec scission pour diviser le texte du document aux limites de la phrase.

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;

Blocs

Utilisez la spécification d'extraction de blocs (blocks) pour identifier les blocs d'étendues contiguës dans le texte d'entrée.

Syntaxe

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

Description

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

    Indique le nombre d'étendues pouvant constituer un bloc. Les valeurs <min\> et <max\> indiquent le nombre minimal et maximal d'étendues qui peuvent constituer un bloc.

  • [between 0 and] <max\>

    Indique la distance de séparation autorisée entre les étendues avant de ne plus pouvoir les considérer comme contiguës.

  • (tokens| characters)

    Indique si la distance de séparation de l'étendue représente le nombre d'unités lexicales ou le nombre de caractères.

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

    Nom de la vue et de la colonne sur lesquelles l'opérateur de bloc doit être appliqué.

  • <output name\>

    Indique le nom de la sortie de l'opérateur de bloc.

Notes sur l'utilisation

  • Si les étendues d'entrée contiennent plusieurs blocs qui se chevauchent, une instruction d'extraction de bloc renvoie tous les blocs possibles. Utilisez la clause de consolidation pour exclure les blocs redondants.
  • Une instruction extract avec une spécification d'extraction de bloc renvoie des blocs consistant chacun en une agrégation de valeurs d'un champ particulier provenant de plusieurs tuples d'entrée. Par conséquent, sa liste de sélection ne peut pas inclure de champs provenant de sa vue d'entrée.

Exemples

Exemple 1 : extraction de blocs de mots dans une plage de caractères

Dans le code suivant, la vue TwoToThreeCapitalizedWords identifie des blocs de deux à trois mots avec une majuscule séparés les uns des autres par 100 caractères.

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;

Exemple 2 : extraction de blocs de mots dans une plage d'unités lexicales

Le code suivant identifie les blocs comportant exactement deux mots avec une majuscule, séparés les uns des autres par cinq unités lexicales.

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

Partie du discours

Utilisez la spécification d'extraction de partie du discours (part-of-speech) pour identifier les emplacements des différentes parties du discours dans le texte d'entrée.

Syntaxe

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>

Description

  • '<part of speech spec\>'

    Identifie les parties du discours à extraire du texte d'entrée. La spécification '<part of speech spec\>' est l'une des chaînes suivantes :

    • Une chaîne contenant une liste délimitée par des virgules de balises part-of-speech générées par le marqueur sémantique multilingue
    • Une combinaison constituée d'un nom part-of-speech interne et d'indicateurs, suivant la définition d'une table de mappage
  • [and '<part of speech spec\>']*

    Identifie les balises de partie du discours supplémentaires pour l'extraction.

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

    Spécifie la langue à utiliser dans l'extraction. Le <language code\> est un code de langue à deux lettres, en minuscules, tel que 'en' ou 'ja'. Si l'argument est omis, la langue de l'extraction de la partie du discours considérée est l'anglais.

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

    Spécifie le nom d'une table AQL qui mappe des balises brutes part-of-speech sous la forme "NOUN" à des combinaisons de parties de discours et d'indicateurs de niveau supérieur. Alors que la table de mappage facultative peut avoir des noms variables, une table de mappage part-of-speech doit obligatoirement avoir ces noms de colonne :

    • tag

      Colonne qui comprend une balise part-of-speech du marqueur sémantique multilingue.

    • basetag

      Colonne qui comprend la balise interne correspondante.

    • flagstr

      Colonne qui comprend une liste délimitée par des virgules d'indicateurs associés à la partie du discours indiquée.

    La table de mappage doit être définie en utilisant l'instruction create table dans le même module que l'instruction extract part_of_speech qui l'utilise. Il ne peut s'agir ni d'une table importée ni d'une table externe.

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

    Spécifie la colonne de la vue d'entrée à partir de laquelle extraire des informations de partie du discours.

  • <output column\>

    Spécifie le nom de la colonne dans laquelle sont envoyées les étendues d'unités lexicales avec les parties de discours indiquées.

  • <input view\>

    Spécifie la vue d'entrée à partir de laquelle extraire des informations de partie du discours.

Notes sur l'utilisation

  • L'extraction de partie du discours fonctionne uniquement avec l'utilisation du marqueur sémantique multilingue. Si le système utilise le marqueur sémantique standard, une extraction part_of_speech génère une erreur.

Balises de partie du discours correspondant aux différentes langues

Pour toutes les langues prises en charge, le marqueur sémantique multilingue utilise les balises de partie de discours qui sont énumérées dans le tableau suivant.

Balise Descriptions
ADJ adjectif
ADP apposition
ADV adverbe
AUX auxiliaire
CCONJ conjonction de coordination
DET déterminant
INTJ interjection
NOUN nom
NUM chiffre
PART particule
PRON pronom
PROPN nom propre
PUNCT ponctuation
SCONJ conjonction de subordination
SYM symbole
VERB verbe
X autre

Exemples

Exemple 1 : utilisation d'une balise part-of-speech dans une instruction d'extraction

La vue EnglishNoun extrait des noms anglais (au singulier ou massiques) ou des noms propres (au singulier).

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

Modèles de séquence

Utilisez la spécification d'extraction de modèle pour réaliser des correspondances de modèles sur un document d'entrée et d'autres étendues extraites du document d'entrée.

Syntaxe

La syntaxe générale d'un modèle de séquence consiste à indiquer d'abord le modèle à rechercher dans le texte, puis à spécifier ce qui doit être renvoyé par l'extracteur. La partie finale du modèle de séquence indique l'entrée du modèle, il peut s'agir d'une colonne d'une vue définie précédemment ou du texte intégral du document.

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

Description

  • <pattern specification\>

    Une spécification <pattern specification\> est composée de plusieurs atomes. Un Atome individuel peut être une colonne ou une vue déjà définie, une chaîne fixe ou une expression régulière. Vous pouvez spécifier vos atomes pour qu'ils soient facultatifs et répétitifs et indiquer les écarts d'unité lexicale (token gaps) entre les Atomes.

    La spécification de modèle fait partie d'une instruction AQL plus vaste, incluant une clause extract.

    Voici un exemple simple de création de vue contenant trois correspondances adjacentes provenant de vues définies auparavant. Dans cet exemple, la combinaison complète est renvoyée, ce à quoi group 0 fait référence :

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

    Si vos Atomes n'ont pas besoin d'être rigoureusement adjacents les uns des autres, vous pouvez utiliser des écarts d'unités lexicales entre les Atomes pour pouvoir obtenir davantage de correspondances. Cet exemple recherche les mentions de personnes suivies dans une plage de 0 à 2 unités lexicales par un numéro de téléphone. Notez la construction <Token>{0,2}, qui indique qu'un écart de 0 à 2 unités lexicales (token) est autorisé entre les annotations de personne et de téléphone.

    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;
    

    Les constructions avec écart d'unité lexicale (token gap) sont limitées dans les expressions comportant une séquence. Par ailleurs, chaque écart d'unité lexicale dans une séquence doit être précédé et suivi de l'expression "non-token gap". Par conséquent, les instructions extract pattern génèrent des exceptions :

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

    Utilisez la syntaxe (min,max) pour indiquer le nombre de répétition de chaque Atome. Vous pouvez également utiliser la syntaxe avec un point d'interrogation (?) pour indiquer qu'un Atome ou un Atome répétitif est facultatif. Les Atomes, ainsi que les indications associées indiquant qu'ils sont répétitifs ou facultatifs, sont combinés pour créer des séquences.

    Voici un exemple plus complexe indiquant comment répéter des éléments. Recherchez les noms d'hôtel potentiels (CandidateHotel) en identifiant les occurrences d'un à trois mots avec une majuscule, suivis de l'unité lexicale '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;
    

    Vous pouvez également utiliser l'opérateur | pour indiquer un choix entre les atomes, comme dans extract pattern <A.match>| <B.match> <C.match> as match from Apple A, Bacon B, Chocolate C;. Ce modèle peut être interprété ainsi : “faire correspondre une occurrence A.match OU une séquence B.match suivie d'une occurrence C.match. Vous pouvez obtenir l'exemple complet utilisant l'opérateur | dans l'exemple 1.

    Une fois que vous avez créé votre modèle, chaque correspondance avec votre spécification <pattern specification> génère un résultat de sortie en fonction de la clause de retour de la spécification de modèle, ainsi que de la liste <select list> facultative au début de l'instruction extract. Les résultats sont filtrés et consolidés en fonction des clauses having, consolidate et limit de l'instruction extract. Par exemple, s'il existe plusieurs correspondances qui se chevauchent pour la spécification de modèle, toutes les occurrences possibles sont renvoyées et vous pouvez utiliser une clause consolidation pour exclure les sorties redondantes.

    Reprenons l'exemple précédent, mais cette fois avec l'objectif de supprimer les correspondances contenant le mot 'Sheraton' et de consolider les occurrences obtenues en supprimant celles qui sont incluses dans une occurrence plus longue. Par exemple, nous ne voulons pas trouver "Best Garden Hotel" et également "Garden Hotel" dans la même étendue de texte.

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

Maintenant que vous vous êtes familiarisé avec la syntaxe et quelques exemples, ce diagramme présente la syntaxe complète de la spécification de modèle. Consultez cette syntaxe complète lorsque vous commencez à générer des modèles pour voir comment structure le modèle que vous souhaitez construire.

Si vous connaissez les expressions régulière POSIX, vous constatez que cette syntaxe est similaire. Dans ce cas, la syntaxe permet l'utilisation de blancs entre les éléments et définit également ce que peut être un élément pour répondre aux objectifs d'AQL. Notez que le terme Alternation dans ce cas indique une option possible. L'utilisation d'une barre verticale entre les éléments indique qu'un choix est possible, ce que vous pouvez regrouper en utilisant des parenthèses ( ).

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 )

Plus particulièrement, un Atome peut avoir six formats :

  • <view_name.column_name\>

    Indique une colonne d'une des références de vue, table ou fonction de table nommées dans la section from list de l'instruction extract pattern.

  • 'string'

    Indique une correspondance avec la chaîne spécifiée obtenue en utilisant la sémantique de correspondance avec le dictionnaire par défaut d'AQL.

  • <'string' [match parameters]\>

    Indique une correspondance avec la chaîne spécifiée obtenue en utilisant la sémantique de correspondance avec le dictionnaire spécifiée par l'élément [match parameters]. Le format des paramètres de correspondance ([match parameters]) par rapport à la casse à utiliser est ((exact | insensitive)). Ce format indique le type de pli de casse utilisé pour déterminer les correspondances de chaînes. Pour spécifier une correspondance exacte sensible à la casse, sélectionnez exact. Pour indiquer une correspondance qui ne tient pas compte des majuscules et des minuscules, sélectionnez la valeur par défaut insensitive.

  • /regex/

    Indique une correspondance avec une expression régulière basée sur les caractères, qui soit limitée à une seule unité lexicale dans le texte du document. De plus, la syntaxe permet de spécifier une construction spéciale d'écart d'unité lexicale (token gap) dans une expression de séquence pour indiquer une correspondance entre un nombre min et max d'unités lexicales.

  • <token\>

    Correspondance avec n'importe quelle unité lexicale.

  • [return clause]

    Génère les valeurs extraites pour chaque correspondance de l'expression modèle en fonction de la clause return. La sémantique de la clause return est la même que celle de la clause return dans une instruction extract regex.

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

    Pour les Atomes de type chaîne (string) ou expression régulière (regex), la clause with inline_match détermine l'objet de texte utilisé par le système pour l'extraction de chaîne ou d'expression régulière. Par exemple, si la clause est with inline_match on Email.subject, tous les dictionnaires et les expressions régulières définis en ligne dans la spécification du modèle sont appliquées au champ subject de la vue Email. S'il n'y a pas de clause with inline_match, l'extraction de chaîne et d'expression régulière s'exécute par défaut sur tout le texte du document. Dans ce cas, la valeur du paramètre viewname doit être le nom d'une vue ou d'une table définie dans le module actuel ou importée d'un autre module. Les références aux fonctions de table ne sont pas admises dans la clause with inline_match.

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

    Indique une liste délimitée par des virgules de codes de langue à deux lettres, par exemple en (English) ou zh (Chinese) pour les langues d'évaluation de la chaîne. Il n'y a aucune correspondance dans les documents dont le code de langue ne figure pas dans cette chaîne. Si le paramètre de langue est omis, la langue d'évaluation par défaut sera l'une des langues suivantes :

    • S'ils sont déclarés, les ensembles de langues sont indiqués via l'instruction set default language dans le module conteneur.
    • Les ensembles de langues contenant l'allemand (de), l'espagnol Spanish (es), l'anglais (en), le français (fr), l'italien (it) et la langue non spécifiée (x_unspecified)

Notes sur l'utilisation

  • La sémantique d'une instruction extract pattern est gérée par la spécification de modèle. Chaque correspondance produit un résultat en fonction de la clause return de la spécification de modèle (pattern specification) et de la liste de sélection (select list) au début de l'instruction extract. Les résultats sont filtrés et consolidés en fonction des clauses having, consolidate et limit de l'instruction extract. S'il existe plusieurs correspondances qui se chevauchent pour la spécification de modèle, une extraction de modèle renvoie toutes les occurrences possibles. Utilisez la clause consolidation pour filtrer les résultats redondants.

  • La sémantique de la clause from d'une instruction extract pattern est différente de celle des autres formes d'instructions extract qui n'ont pas de spécification de modèle. La sémantique générale d'une instruction extract requiert que la spécification d'extraction soit évaluée sur chaque combinaison des vues définies dans la liste <from list\>. Si au moins l'une des vues de <from list\> ne contient aucun résultat sur un document particulier, la sortie de l'instruction d'extraction est vide car l'ensemble de toutes les combinaisons de résultats dans les vues d'entrée est vide. Dans le cas de figure particulier des instructions extract pattern, la clause from est une marque de réservation qui déclare les noms des relations impliquées dans la spécification de modèle. La sémantique de l'instruction est gérée uniquement par la spécification de modèle. La sortie de l'instruction peut notamment ne pas être vide même si certaines vues d'entrée sont vides.

  • Une instruction extract qui utilise une extraction de modèle de séquence peut reporter les colonnes de n'importe quelle vue dans la liste from, mais seulement si le nom de la vue n'apparaît pas dans un élément de répétition dans la spécification de modèle. Par exemple, l'instruction CapsWordOneToThree génère une erreur de compilation. L'erreur se produit car la colonne reportée CW.type en haut de l'instruction extract appartient au nom de vue CW, qui se trouve dans l'élément de répétition <CW.word>{1,3} de la spécification de modèle.

    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;
    

    Pour les colonnes reportées à partir de noms de vue qui apparaissent sous la forme d'éléments alternatifs ou facultatifs de la spécification de modèle, la valeur de la colonne de sortie est null lorsque l'élément alternatif ou facultatif correspondant ne figure pas dans le texte. Un exemple pour illustrer ce cas de figure se trouve dans la vue Person de l'exemple 1.

  • Les groupes qui se trouvent dans un élément de répétition ne peuvent pas être renvoyés dans la clause return de l'instruction. Par exemple, l'instruction suivante peut provoquer une exception :

    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;
    

Exemples

Exemple 1 : modèle de séquence avec des groupes de capture

Cet exemple a pour but de rechercher des noms de personne en identifiant les occurrences d'un prénom accompagné éventuellement d'un deuxième prénom, suivi d'un nom et la correspondance totale qui est éventuellement précédée d'une salutation courante. Par ailleurs, l'extracteur renvoie la correspondance totale en tant que référence, le premier groupe en tant que salutation et le second groupe en tant que nom, et retourner les valeurs de prénom, deuxième prénom et nom à partir des vues d'entrée respectives.

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;

Comme la sous-expression de modèle ('Mr.'|'Ms.'|'Miss')? est facultative, la valeur de la colonne de sortie salutation est null si aucune salutation n'est présente dans le texte. De même, comme la sous-expression de modèle <M.initial>? est facultative, la valeur de la colonne de sortie middle est null si aucune initiale de milieu n'est présente.

Exemple 2 : modèle de séquence avec correspondance de chaîne et paramètres de correspondance

Cet exemple a pour but de rechercher les occurrences de notes de réunion concernant des projets connus en examinant les annotations de titre du document. Notez la clause with inline_match, qui indique que la correspondance de chaîne est réalisée sur le champ match de la vue Title, et non pas sur le texte intégral du document.

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;

Exemple 3 : modèle de séquence renvoyant des résultats non vides même lorsqu'une vue d'entrée est vide

L'instruction suivante génère des résultats même si la vue d'entrée LastName est vide. La seconde partie de la spécification de modèle, <L.name\>?, contient un élément facultatif. La sémantique de la spécification de modèle est conçue pour renvoyer toutes les étendues composées d'une étendue FirstName.name ou d'une étendue FirstName.name immédiatement suivie d'une étendue LastName.name. Par conséquent, sur les documents pour lesquels la vue LastName est vide, le résultat de l'instruction comprend toutes les étendues incluant une seule étendue FirstName.name identifiée dans ce document.

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;

L'instruction select

L'instruction select dans AQL fournit un mécanisme puissant permettant l'utilisation de différentes spécifications pour construire et combiner des ensembles de tuples.

Syntaxe

La structure de l'instruction select est semblable à celle d'une instruction 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>`];

Description

  • <select list\>

    Liste séparée par des virgules d'expressions de sortie.

  • <from list\>

    Liste délimitée par des virgules constituant la source des tuples à sélectionner.

  • [where <where clause\>]

    Définit un prédicat à appliquer à chaque tuple généré à partir du produit cartésien de tous les tuples dans les relations figurant dans la clause from. Cette clause est facultative.

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

    Définit une règle de consolidation pour gérer les étendues qui se chevauchent. Cette clause est facultative.

  • [group by<group by list\>]

    Regroupe les tuples produits à partir du même document par valeurs communes d'un champ spécifié. Cette clause est facultative.

  • [order by<order by list\>]

    Classe les tuples de sortie produits par l'instruction select à partir de chaque document. L'ordre adopté est basé sur les valeurs de la liste order-by, une liste d'expression délimitées par des virgules. Cette clause est facultative.

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

    Limite le nombre de tuples de sortie pour chaque document conformément à la valeur maximale indiquée. Cette clause est facultative.

Remarques relatives à l'utilisation

La sémantique de l'instruction select se décline comme suit :

  • Détermination des données d'entrée (sous forme de tuples) en prenant le produit cartésien des relations dans la liste from.
  • Pour chaque tuple d'entrée généré, filtrage du tuple en appliquant les prédicats dans la clause where (facultative).
  • Si la clause facultative group by est présente, regroupement des tuples produits dans le même document par les valeurs spécifiées dans la liste group-by et calcul du résultat des fonctions aggregate à l'intérieur de la liste de sélection (select list).
  • Consolidation de tous les tuples qui se chevauchent en fonction de la règle définie dans la clause consolidation (facultative). Si la clause facultative order by est présente, classez ces tuples par les valeurs indiquées dans la liste order-by.
  • Calcul de toutes les expressions figurant dans la liste select sur chaque tuple et attribution d'un nouveau nom aux colonnes suivant les indications fournies par les clauses as.
  • Si la clause facultative limit est présente, limitation du nombre de tuples de sortie au nombre de tuples indiqué pour chaque document.

Exemples

Un exemple d'utilisation de l'instruction select consiste à extraire des numéros de téléphone correspondant à un modèle. Supposons que la vue PhoneNumbers qui extrait les numéros de téléphone suivant le modèle XXX-XXX-XXXX pour les Etats-Unis est déjà définie. Cette instruction select évalue l'expression régulière correspondant au modèle 444-888-XXXX dans le texte d'entrée. La vue comporte les colonnes de sortie documentText et phoneNumber. De plus, la sortie est limitée à la première occurrence de ce modèle de numéro de téléphone identifiée par document.

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

Un autre exemple d'utilisation de l'instruction select consiste à rechercher des mappages approximatifs de personnes et leurs numéros de téléphone correspondants. Supposons que la vue Person soit déjà définie et qu'elle comporte les colonnes person et la vue PhoneNumbers. Cette instruction select évalue la clause where pour rechercher des étendues de texte contenant une mention de personne suivie d'un numéro de téléphone séparés par 1 à 3 mots ou unités lexicales. L'entrée de cette instruction est représentée par une jointure des vues Person et PhoneNumbers dans la liste from.

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

La colonne personPhoneSpan contient les étendues correspondantes qui indiquent un mappage approximatif personne-numéro de téléphone.

personPhoneSpan
John : 433-999-1000
Martha Mob 433-999-1001
  • Liste select La liste select dans une instruction AQL select ou extract est constituée d'une liste délimitée par des virgules d'expressions de sortie.
  • Liste from La deuxième partie d'une instruction select ou extract dans AQL est la liste from. La liste from est une liste séparée par des virgules qui constitue la source des tuples à sélectionner ou à extraire.
  • Clause where La clause facultative where définit un prédicat à appliquer sur chaque tuple généré à partir du produit cartésien de tous les tuples dans les relations figurant dans la clause from.
  • Clause consolidate on La clause facultative consolidate on indique comment les étendues qui se chevauchent sont résolues sur les tuples générés par une instruction select ou extract. Les tuples qui ne contiennent pas d'étendues qui se chevauchent ne sont pas affectés lorsque cette clause est utilisée.
  • Clause group by La clause facultative group by d'une instruction select demande au composant d'exécution de regrouper les tuples produits à partir du même document par des valeurs communes d'un champ spécifié.
  • Clause order by La clause facultative order by demande au composant d'exécution d'ordonner les tuples produits par l'instruction select à partir de chaque document en fonction des valeurs indiquées dans la liste order by, qui est un ensemble d'expressions délimitées par des virgules.
  • Clause limit La clause facultative limit spécifie le nombre limite de tuples de sortie générés par l'instruction select pour un document.
  • Instruction select... into L'instruction select ... into est utile pour définir une vue et spécifier qu'il s'agit d'une vue de sortie dans une seule instruction.

La liste select

La liste select dans une instruction AQL select ou extract est constituée d'une liste délimitée par des virgules d'expressions de sortie.

Syntaxe

Chaque expression select doit être au format suivant :

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>

Description

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

    • <viewname\>

      Indique la vue à partir de laquelle sélectionner des colonnes.

    • <colname\>

      Indique la colonne figurant dans cette vue.

    • <alias\>

      Indique le nom sous lequel le champ sélectionné est connu. Ce champ est facultatif. Il est sélectionné pour faire partie de chaque tuple de sortie. Si <alias\> n'est pas spécifié, le nom de la colonne est par défaut le <colname\>. Il peut s'agir d'un identificateur simple ou d'un identificateur entre guillemets.

  • <viewname\>.*

    Spécifie le nom d'une vue. Cette syntaxe indique que toute les colonnes de la vue spécifiée doivent être reportées dans l'instruction select ou extract.

    A l'instar de SQL, AQL autorise l'instruction abrégée select *. L'effet de cette instruction est de sélectionner toutes les colonnes de toutes les entrées spécifiées dans la clause from de l'instruction select. Toutefois, l'instruction abrégée extract * n'est pas prise en charge.

  • <expr\> as <alias\>

    Représente l'affectation d'une expression à un attribut de la vue globale.

    • <expr\>

      Indique une expression composée d'appels de fonction scalaire, d'appels de fonction d'agrégation ou d'une constante.

    • <name\>

      Représente le nom de la colonne qui contient le résultat de l'expression spécifiée par <expr\> comme <alias\>. Si <alias\> n'est pas spécifié, le nom de la colonne est par défaut le <name\>. Il peut s'agir d'un identificateur simple ou d'un identificateur entre guillemets.

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

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

      Spécifiez les fonctions scalaires qui renvoient un type booléen (Boolean).

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

      Spécifiez les expressions composées d'appels de fonction scalaire qui doivent renvoyer le même type.

    Si le résultat de <function1()\> est true, le résultat de l'expression case est le résultat de <expr1\>, et aucune des clauses when suivantes n'est évaluée. Sinon, les clauses when suivantes (le cas échéant) sont évaluées de la même manière.

    Si aucune des conditions des clauses when n'est satisfaite, le résultat de cette expression de cas est le résultat de l'expression par défaut <expr\_default\>. Cette expression est spécifiée dans la clause facultative else. Si la clause [else] est absente, le résultat de cette expression case est null.

Notes sur l'utilisation

  • L'instruction suivante n'est pas prise en charge :

    select * from Document;
    

    Le contenu de la vue Document peut ne pas être entièrement connu dans le contexte ou la portée en cours du fichier .aql dans lequel est émise cette instruction select. L'absence d'informations sur le contenu est due au fait que plusieurs instructions require document with columns indiquées hors du fichier .aql actuel peuvent modifier la définition de schéma finale de cette vue Document spéciale lorsqu'elle est utilisée au niveau d'un module. L'instruction abrégée Document.* n'est pas une construction AQL valide.

  • Vous pouvez sélectionner des champs de manière explicite à partir de la vue Document. L'exemple suivant présente une sélection explicite de champs valide d'une vue Document :

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

Exemples

Les exemples suivants illustrent plusieurs formes de la liste select.

Exemple 1 : affectation de valeur explicite utilisant une constante

Cet exemple illustre l'affectation d'une valeur de constante à un attribut de vue au sein de la liste select. Le champ nommé polarity indique si la polarité de PS.match est positive ou négative (notez l'affectation explicite d'une valeur de constante à cet attribut).

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;

Exemple 2 : affectation de valeur explicite utilisant un appel de fonction

L'exemple suivant montre comment le résultat d'un appel de fonction est affecté de manière explicite à un attribut de vue dans la liste select.

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

Exemple 3 : expression de la liste select à partir d'une extraction de dictionnaire

L'exemple suivant montre comment l'expression select list peut sélectionner des valeurs de type Span (étendue) à partir d'un résultat issu d'une extraction de dictionnaire.

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

Exemple 4 : exemple d'expressions case

Ce premier exemple montre comment spécifier le traitement de valeur null dans des champs spécifiques :

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

Cet exemple explique comment classifier les données :

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

La liste from

La deuxième partie d'une instruction select ou extract dans AQL est la liste from. La liste from est une liste séparée par des virgules qui constitue la source des tuples à sélectionner ou à extraire.

Syntaxe

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

Description

  • <from list item\>

    Référence à une vue, table ou fonction de table ou instruction AQL imbriquée. Toutes les instructions imbriquées dans AQL doivent être mises entre parenthèses.

  • <name\>

    Nom local de l'élément <from list item\>, qui est compris dans l'instruction select ou l'instruction extract. Un nom local peut être un identificateur simple ou entre guillemets. Les noms locaux qui contiennent des espaces, des signes de ponctuation ou des mots clés AQL doivent être mis entre guillemets (").

Exemples

Exemple 1 : liste from avec une vue et une instruction imbriquée

Cet exemple montre une liste from qui fait référence à une vue et une instruction extract imbriquée. Le résultat de l'instruction est affecté au nom local FN. Cet exemple affecte également les sorties de la vue LastName au nom 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);

Les noms suivants sont inclus dans le dictionnaire externe de prénoms first.dict :

#Dictionary for given names
Aaron
Candra
Freeman
Mathew
Matthew
Zoraida

La clause where

La clause facultative where définit un prédicat à appliquer sur chaque tuple généré à partir du produit cartésien de tous les tuples dans les relations figurant dans la clause from.

Syntaxe

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

Description

  • <where clause\>

    Indique un ou plusieurs prédicats. Une jointure se produit lorsqu'un prédicat figurant dans une clause where se rapporte à des champs de plusieurs vues qui appartiennent à la liste from. Ce prédicat doit être une conjonction d'un ensemble de fonctions de prédicat intégrées ou d'autres fonctions définies par l'utilisateur qui renvoient le type booléen (Boolean) :

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

    La clause where est facultative et peut être omise dans une instruction select s'il n'y a aucun prédicat à appliquer.

Exemples

Exemple 1 : filtrage des tuples de jointure en utilisant un prédicat dans la clause WHERE

Cet exemple présente une clause where qui recherche uniquement les expressions constituées de prénoms valides suivis dans une plage de 0 à 1 caractère par des noms de famille valides.

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

Les noms suivants sont inclus dans le dictionnaire externe de prénoms first.dict :

#Dictionary for given names
Aaron
Candra
Freeman
Mathew
Matthew
Zoraida

Les noms suivants sont inclus dans le dictionnaire externe de noms last.dict :

#Dictionary for surnames
Anthony
Lehman
Radcliff

La clause consolidate on

La clause facultative consolidate on indique comment les étendues qui se chevauchent sont résolues sur les tuples générés par une instruction select ou extract. Les tuples qui ne contiennent pas d'étendues qui se chevauchent ne sont pas affectés lorsque cette clause est utilisée.

Syntaxe

Le code suivant est un exemple de structure générale de cette clause :

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

Description

  • <target\>

    Indique une colonne d'une vue dans la clause from ou une expression composée d'appels de fonction scalaire impliquant des colonnes de vues qui sont spécifiées dans la clause from sous forme d'arguments.

  • '<policy\>'

    Indique l'une des règles de consolidation suivantes prises en charge par l'analyse de texte :

    • ContainedWithin

      Règle par défaut. Si les étendues A et B se chevauchent, A englobe complètement B, cette règle supprime ensuite le tuple contenant l'étendue B dans la sortie. Si les étendues A et B sont identiques, l'une d'entre elles est supprimée. La suppression de l'un ou l'autre de ces tuples est arbitraire.

    • NotContainedWithin

      Si les étendues A et B se chevauchent, A englobe complètement B. Cette règle supprime ensuite l'étendue A dans la sortie. Si les étendues A et B sont identiques, l'une d'entre elles est supprimée. La suppression de l'un ou l'autre de ces tuples est arbitraire.

    • ContainsButNotEqual

      Cette règle est identique à ContainedWithin, mais cette fois les étendues qui sont rigoureusement identiques sont conservées.

    • ExactMatch

      Si un ensemble d'étendues couvre la même région de texte, cette règle renvoie une seule de ces étendues. Toutes les autres étendues ne sont pas touchées.

    • LeftToRight

      Cette règle traite les étendues de gauche à droite. En cas de chevauchement, elle conserve l'étendue sans chevauchement la plus longue située le plus à gauche (leftmost). Cette règle émule la règle de traitement de chevauchement de la plupart des moteurs d'expressions régulières.

  • <priority\_column\>

    Indique une colonne de type Text, String, Integer ou Float. Cet élément ne peut être spécifié qu'avec la règle de consolidation LeftToRight.

  • <priority\_order\>

    Indique l'ordre croissant (ascending) ou décroissant (descending). Cet élément ne peut être spécifié qu'avec la règle de consolidation LeftToRight. L'ordre croissant garantit que si le tuple T1 a une priorité égale à 1 et que le tuple T2 a une priorité égale à 2, T1 a une priorité supérieure par rapport à T2. En revanche, si l'ordre de priorité est décroissant, T2 a une priorité plus élevée. La valeur par défaut est l'ordre croissant.

Notes sur l'utilisation

  • Lorsque la clause priority est présente, la sémantique de la clause de consolidation respecte cet ordre :
    • Traitement des étendues de gauche à droite et en cas de chevauchement, conservation des étendues situées le plus à gauche.
    • Si vous avez plusieurs étendues qui se chevauchent commençant au même décalage, conservation des étendues de priorité supérieure en fonction de l'ordre de priorité.
    • Rupture des liens restants en conservant les étendues les plus longues parmi celles qui ont la même priorité.
  • La consolidation traite les valeurs null comme des valeurs identiques. Toutes les entrées avec un <consolidate target\> nul résultent en un tuple de sortie unique, qui est choisi au hasard parmi ces entrées. Ce comportement s'apparente à la consolidation des tuples avec une étendue identique dans la colonne cible. La sortie est un tuple de sortie unique sauf si la règle appliquée est ContainsButNotEqual. Dans ce cas, le <consolidate target\> nul génère toutes les entrées avec une cible de consolidation nulle.

Exemples

Exemple 1 : expression consolidate on impliquant une seule colonne

Cet exemple demande au système d'examiner le champ Person.name de tous les tuples de sortie et d'utiliser la règle de consolidation ContainedWithin pour résoudre les chevauchements.

consolidate on Person.name
  using 'ContainedWithin'

Exemple 2 : expression consolidate on impliquant plusieurs colonnes

Cet exemple demande au système d'examiner le résultat de l'application de la fonction scalaire CombineSpans dans les champs Person.firstname et Person.lastname dans chaque tuple de sortie. Les chevauchements sont résolus à l'aide de la règle de consolidation ContainedWithin.

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

Exemple 3 : consolidation en utilisant la règle LeftToRight et l'ordre de priorité

Supposons que les tuples de termes suivants sont extraits du texte d'entrée John Doe :

match: `John`,
priority: `1`

and

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

Ces deux étendues ont le même décalage de début. Lorsque vous consolidez en utilisant la règle LeftToRight pour l'ordre de priorité croissant (ascending), le tuple (match: John, priority: 1) est conservé car sa priorité est plus élevée. Lorsque vous consolidez en utilisant l'ordre de priorité descendant (descending) le tuple (match: John Doe, priority: 2) est conservé, comme dans l'exemple suivant :

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

La clause group by

La clause facultative group by d'une instruction select demande au composant d'exécution de regrouper les tuples produits à partir du même document par des valeurs communes d'un champ spécifié.

Syntaxe

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

Description

  • <group by list\>

    Indique une liste délimitée par des virgules d'expressions concernant les colonnes des vues dans la clause from et les appels de fonction scalaire. Lorsque vous appliquez la clause group by, chaque groupe de tuples partageant des valeurs communes pour toutes les expressions group by génère un seul tuple de sortie représentatif de tout le groupe.

    Un champ ou une expression qui n'apparaît pas dans la clause group by ne peut pas apparaître dans la liste select, sauf s'ils sont utilisés dans un appel de fonction d'agrégation. L'ordre des expressions dans la liste n'a aucune importance.

    La clause group by traite toutes les valeurs nulles comme identiques. Group by sur une colonne avec des valeurs nulles donne un groupe unique.

Exemples

Exemple 1 : calcul de valeurs d'agrégat

Utilisez la clause group by pour calculer des valeurs d'agrégat. Cet exemple comptabilise le nombre d'occurrences de chaque prénom dans le document. Dans cet exemple, Count est une fonction d'agrégation.

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

Dans ce cas, first.dict est un dictionnaire externe de prénoms contenant les entrées suivantes :

#Dictionary for given names
Aaron
Candra
Freeman
Matthew
Zoraida

La sémantique de cette instruction est décrite dans les étapes suivantes :

  1. Groupement des tuples générés par la sous-requête dans la clause from par le contenu du texte correspondant à leur champ firstname.
  2. Pour chaque groupe, comptabilisation du nombre de tuples avec une valeur firstname différente de null. Génération d'un seul tuple de sortie pour chaque groupe de ce type, avec deux valeurs, le nom et le nombre de tuples figurant dans ce groupe.

Exemple 2 : erreurs lors du regroupement de champs différents

Cet exemple illustre une instruction qui n'est pas valide.

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

L'inclusion de GetText(P.lastname) dans la liste select n'est pas acceptée, car les tuples avec les mêmes valeurs de prénom (firstname) peuvent avoir des valeurs de nom (lastname) différentes, ce qui risque d'entraîner une certaine ambiguïté.

La clause order by

La clause facultative order by demande au composant d'exécution d'ordonner les tuples produits par l'instruction select à partir de chaque document en fonction des valeurs indiquées dans la liste order by, qui est un ensemble d'expressions délimitées par des virgules.

Syntaxe

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

Description

  • <order by list\>

    Indique une liste d'expressions délimitée par des virgules.

    L'ordre s'applique aux valeurs d'une liste d'expressions délimitée par des virgules. La clause order by prend en charge les expressions qui renvoient des types de données numériques (Integer ou Float), Text ou Span. Si une expression figurant dans la clause order by renvoie un type Span, la comparaison des tuples du résultat s'effectue en comparant les valeurs d'étendue (span) pertinentes. Dans l'exemple suivant, la comparaison s'effectue sur les valeurs d'étendue du champ person.

    order by P.person
    
    

    La clause order by traite les valeurs null comme étant non ordonnées (les unes par rapport aux autres). L'ordre des valeurs null est considéré comme inférieur à celui des autres objets.

Exemples

Exemple 1 : classement par expressions multiples

Supposons que person soit un champ de type Span. La clause order by suivante indique que l'instruction renvoie des tuples au sein de chaque document. Ils sont classés de manière lexicographique par texte contenu dans le champ person, puis par le début du champ person.

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

La clause limit

La clause facultative limit spécifie le nombre limite de tuples de sortie générés par l'instruction select pour un document.

Syntaxe

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

Description

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

    Indique le nombre maximal de tuples de sortie pour chaque document. Si cette valeur limite est supérieure ou égale au nombre total de tuples pouvant être renvoyés, tous les tuples sont renvoyés.

Exemples

Exemple 1 : limitation du nombre de renvois

Cet exemple renvoie les trois premiers noms de personne dans chaque document :

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

L'instruction select... into

L'instruction select ... into est utile pour définir une vue et spécifier qu'il s'agit d'une vue de sortie dans une seule instruction.

Syntaxe

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

Description

  • <output view name\>

    Indique le nom de la vue définie par l'instruction. L'instruction select ... into est identique à l'instruction select, à l'exception de la clause into <output view name\> supplémentaire.

Exemples

Exemple 1 : définition d'une vue

Cet exemple définit une vue nommée PersonPhone et spécifie également qu'il s'agit d'une vue de sortie.

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

Cet exemple est équivalent aux deux instructions suivantes :

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

output view PersonPhone;

L'instruction detag

L'instruction detag dans AQL fournit la fonction permettant de retirer des balises ou de supprimer tout le balisage de documents HTML ou XML avant d'exécuter les extracteurs AQL.

L'instruction detag peut également conserver les emplacements d'origine de ces balises, ainsi que toutes les valeurs qui y sont stockées. Lorsqu'une instruction detag supprime les balises d'un document, le composant d'exécution se souvient du mappage entre les décalages du texte dont les balises ont été supprimées et la source du balisage d'origine. La fonction Remap, une fonction intégrée spéciale qui remappe les étendues du texte dont les balises ont été retirées à leurs étendues équivalentes dans la source d'origine.

Syntaxe

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

Description

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

    • <input view name\>

      Indique le nom de la vue de sortie sur laquelle effectuer le processus de retrait des balises. <input view name\> peut être un identificateur simple ou un identificateur à guillemets doubles.

    • <text column\>

      Indique le champ de texte de la vue d'entrée sur lequel effectuer le processus de retrait des balises. <text column\> peut être un identificateur simple ou un identificateur à guillemets doubles.

  • <output view name\>

    Indique le nom de la vue de sortie contenant le texte dont les balises ont été retirées. La vue de sortie contient une seule colonne nommée text qui renferme le texte sans les balises. <output view name\> peut être un identificateur simple ou un identificateur à guillemets doubles.

  • always|never

    Indique s'il faut vérifier qu'il s'agit d'un contenu HTML ou XML avant de lancer l'instruction detag. Lorsque vous exécutez du texte non HTML et non XML par le biais d'un détagueur, des problèmes peuvent se produire si le texte contient des caractères spéciaux XML tels que <, > ou &. Si la clause detect content_type est manquante, la valeur par défaut est always et le système effectue systématiquement une détection du contenu.

    • always

      Indique que la vérification a lieu systématiquement avant de tenter l'opération afin d'éviter tout problème lors de l'analyse syntaxique des documents qui ne sont pas au format HTML ou XML. Si la valeur de <text column\> ne semble pas contenir de balisage, le système saute le détagage pour le document en cours.

    • never

      Indique qu'il n'y a jamais de vérification avant l'opération de retrait des balises. Le système tente de retirer les balises du texte cible, même si le texte ne renferme aucun contenu HTML ou XML.

  • <element name\>

    Indique le nom de l'élément HTML ou XML à annoter. La clause facultative annotate peut demander au composant d'exécution de se souvenir des informations sur les balises retirées en créant une ou plusieurs vues.

  • <auxiliary view name\>

    Indique le nom de la vue créée pour héberger les balises d'origine et leurs attributs. Il peut s'agir d'un identificateur simple ou d'un identificateur entre guillemets.

  • <attribute name\>

    Nom d'un attribut de l'élément HTML ou XML.

  • <column name\>

    Nom de la colonne dans le <auxiliary view name\> qui est utilisé pour stocker les valeurs de <attribute name\>. Il peut s'agir d'un identificateur simple ou d'un identificateur entre guillemets.

Exemples

Exemple 1 : spécification de la vue de sortie de l'instruction detag et d'une vue auxiliaire

Dans cet exemple, la vue DetaggedDoc est créée pour héberger la version sans balises du texte d'origine figurant dans l'attribut text de la vue Document. En plus de créer une vue DetaggedDoc, la clause annotate crée une vue auxiliaire nommée Anchor. Cette vue auxiliaire est constituée de deux colonnes. Une colonne nommée match contenant le texte anchor. Une autre colonne appelée linkTarget, contient la cible réelle du lien sous forme de texte. Les étendues dans la colonne match figurent sur la valeur de texte de la vue DetaggedDoc.

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

Exemple 2 : utilisation de la fonction Remap

L'exemple suivant montre comment la fonction Remap est utilisée pour remapper les étendues du texte dont les balises ont été retirées à leurs équivalents dans la source d'origine.

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

Documentation de l'instruction detag avec AQL Doc

Le commentaire AQL Doc pour une instruction detag contient les informations suivantes :

  • Description générale concernant la fonction de l'instruction.
  • @field pour chaque champ de texte de la vue d'entrée sur lequel appliquer le processus de retrait des balises.
  • @auxView indique le nom de la vue.
  • @auxViewField indique le nom de colonne qualifié complet de la vue.
/**
* 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;

Les instructions create dictionary et create external dictionary

Les instructions create dictionary et create external dictionary sont utilisées pour définir les dictionnaires de mots ou d'expressions pour identifier les termes correspondants dans le texte d'entrée via des instructions extract ou d'autres fonctions de prédicat. L'instruction create dictionary permet de spécifier le contenu du dictionnaire dans le code AQL source, et le contenu du dictionnaire est sérialisé dans la représentation compilée du module (fichier .tam). L'instruction create external dictionary vous permet de spécifier le contenu du dictionnaire lors de l'instanciation de l'extracteur, plutôt que dans le code AQL source et vous n'avez pas à recompiler le module. Par conséquent, les dictionnaires externes sont des constructions efficaces qui permettent au développeur AQL d'exposer des points de personnalisation dans un module compilé.

Les dictionnaires peuvent être créés à partir de trois sources :

  • Fichiers de dictionnaire
  • Déclarations de dictionnaire en ligne
  • Tables créées avec l'instruction create table et l'instruction create external table.

Syntaxe

L'instruction interne create dictionary a trois formes syntaxiques, from file, from table et un format en ligne.

  • Dictionnaire interne

    A partir d'un fichier (from file) :

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

    A partir d'une table (from table) :

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

    Format en ligne

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

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

Description

  • <dictionary name\>

    Indique un nom pour le nouveau dictionnaire interne ou externe. Il peut s'agir d'un identificateur simple ou d'un identificateur entre guillemets.

  • '<file name\>'

    Indique le nom du fichier contenant les entrées du dictionnaire. Les fichiers de dictionnaire sont des fichiers texte délimités par des retours chariot avec une entrée de dictionnaire par ligne. Les entrées d'un fichier de dictionnaire peuvent comporter plusieurs unités lexicales.

  • <table name\>

    Indique le nom de la table à partir de laquelle ajouter des entrées de dictionnaire. Les dictionnaires ne peuvent pas être créés à partir d'une table importée d'un autre module.

  • <column name\>

    Indique le nom de la colonne figurant dans table à partir de laquelle ajouter les entrées de dictionnaire.

  • required [true|false]

    Indique si du contenu externe pour le dictionnaire externe est nécessaire à l'exécution du module.

    • true

      Si la clause est required true, vous devez fournir un identificateur URI pour l'emplacement du fichier contenant le contenu externe. Le fichier spécifié doit inclure un contenu. Si l'identificateur URI n'est pas fourni ou si le fichier ne contient pas de contenu, le composant d'exécution émet une exception.

    • false

      Si la clause est required false, le module peut être exécuté correctement même si un identificateur URI vers le contenu externe n'est pas fourni pour ce dictionnaire. Si aucun identificateur URI n'est fourni, le composant d'exécution le traite comme s'il s'agissait d'un dictionnaire vide.

    L'utilisation de create external dictionary <dictionary-name\> allow_empty est désormais obsolète et génère un avertissement de compilation.

  • '<language code(s)\>'

    Indique une liste séparée par des virgules de codes de langue à deux lettres, par exemple en (anglais) ou zh (chinois) pour les langues, ou pour les langues des documents de dictionnaires externes, utilisées pour évaluer le dictionnaire. Le dictionnaire ne donne aucun résultat sur les documents dont le code de langue n'est pas inclus dans cette chaîne.

    Si le paramètre de langue est omis, la langue du dictionnaire prend l'un des ensembles de langue suivants par défaut :

    • Les ensembles de langues qui sont indiqués via l'instruction set default language, si elle est déclarée, dans le module conteneur.
    • Les ensembles de langues contenant l'allemand (de), l'espagnol (es), l'anglais (en), le français (fr), l'italien (it) et la langue non spécifiée (x_unspecified).
  • lemma_match

    Utilisez la lemmatisation pour rechercher les correspondances de mots similaires à un terme du dictionnaire dans vos documents.

    La lemmatisation est le processus permettant de déterminer le lemme d'un mot donné. Un lemme est un mot pouvant être utilisé comme correspondance d'un seul terme donné. Par exemple, le terme "go" peut correspondre aux termes "goes", "going", "gone" ou "went". Ce processus implique des tâches complexes, telles que la compréhension du contexte et la détermination de la partie du discours d'un mot dans une phrase. La lemmatisation est disponible pour toutes les langues pour lesquelles le marqueur sémantique multilingue fournit un support de type part-of-speech.

    La correspondance des lemmes est réalisée uniquement pour les dictionnaires déclarés avec la clause lemma match.

    La sémantique de l'extraction de dictionnaire avec la clause lemma_match se décline comme suit :

    • Calcul de la forme lemmatisée de chaque unité lexicale du document d'entrée.
    • Le dictionnaire est évalué par rapport au document lemmatisé. Vous ne pouvez pas utiliser l'option lemma_match avec l'option case exact. Si les deux options sont utilisées, une erreur du compilateur est renvoyée.
  • case (exact | insensitive)

    Indique le type de pli de casse effectué par le dictionnaire lorsqu'il détermine si une correspondance avec une région spécifique du document est établie.

    • exact

      Indique une correspondance exacte sensible à la casse.

    • insensitive

      Indique une correspondance qui n'est pas sensible à la casse. Il s'agit de l'option par défaut.

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

    Indique les chaînes que vous souhaitez inclure dans le dictionnaire en ligne. Les entrées d'un dictionnaire en ligne peuvent être constituées d'une ou de plusieurs unités lexicales.

Notes sur l'utilisation

  • Les formats from file et from table sont recommandés, notamment lorsque vous envisagez de modifier les entrées ou lorsque vous disposez de nombreuses entrées. En utilisant ces formats, vous pouvez modifier le contenu du dictionnaire sans modifier le code.

  • Lorsque l'instruction create dictionary est traitée par le compilateur AQL modulaire, les références aux emplacements du fichier de dictionnaire spécifiées dans la syntaxe create dictionary ... from file doivent être relatives à la racine du module dans lequel cette instruction create dictionary est émise.

  • Vous pouvez spécifier des commentaires dans un fichier de dictionnaire en faisant précéder le commentaire du caractère #. Les commentaires peuvent commencer n'importe où sur une ligne.

  • Si vous souhaitez spécifier des commentaires sur plusieurs lignes, vous devez faire précéder chaque ligne du caractère signalant un commentaire. Si le caractère de commentaire fait partie d'une entrée de dictionnaire, vous devez l'indiquer avec un caractère d'échappement correspondant à la barre oblique inversée (\), par exemple \#. Si le caractère de barre oblique inversée fait partie d'une entrée du dictionnaire, il doit être indiqué par un caractère d'échappement représenté par lui-même, par exemple \\.

  • Pour les dictionnaires externes, lors du chargement des modules, vous devez indiquer une liste d'identificateurs URI vers les dictionnaires externes, conformément aux conditions requises par les modules qui sont chargés.

  • Lemmatisation des dictionnaires : la principale différence entre la sémantique de correspondance du dictionnaire existant et la sémantique lemmatisée réside dans le fait que la correspondance s'effectue par rapport à la forme lemmatisée du document, et non pas la forme d'origine du document.

    Les exigences suivantes sont applicables aux entrées de dictionnaire appartenant à un dictionnaire avec correspondance de lemme activée :

    • Une entrée de dictionnaire peut contenir une ou plusieurs unités lexicales, chaque unité lexicale d'une entrée constituant un lemme. Pour créer un dictionnaire de lemmes, vous pouvez utiliser la fonction scalaire [GetLemma.
    • Les unités lexicales d'une entrée de dictionnaire doivent être séparées par un blanc. Si l'unité lexicale est constituée de blancs, ces blancs doivent être indiqués avec un caractère d'échappement correspondant à une barre oblique inversée ( \).
  • Le tableau suivant présente les différences entre l'instruction create external dictionary et l'instruction create dictionary :

create external dictionary create dictionary
  • Définit une marque de réservation pour un dictionnaire dont le contenu est fourni au moment de l'initialisation.
  • Nécessite que le contenu du dictionnaire soit disponible au moment de la compilation.
  • Contenu sérialisé dans la représentation compilée (.tam) d'un module.

Exemples

Exemple 1 : création d'un dictionnaire externe

Le dictionnaire externe, PersonPositiveClues, s'attend à recevoir des valeurs d'un fichier externe au moment du chargement. Il s'attend également à être utilisé pour trouver des correspondances dans les langues occidentales comme indiqué par ses indicateurs.

module PersonModuleEnglish;

create external dictionary PersonPositiveClues
  allow_empty false
  with case exact;

export dictionary PersonPositiveClues;

Exemple 2 : lemmatisation

Prenez par exemple un dictionnaire avec la correspondance de lemme activée contenant deux entrées : go shop et went shopping. Le document contient le texte Anna went shopping. La forme lemmatisée du document d'entrée est Anna go shop. La correspondance renvoie went shopping comme correspondance de l'entrée go shop. Le texte du document d'origine n'est pas comparé aux entrées du dictionnaire, mais uniquement au texte du document lemmatisé. Par conséquent, il n'existe aucune correspondance dans le document pour l'entrée went shopping.

Documentation des instructions create dictionary et create external dictionary avec AQL Doc

Le commentaire AQL Doc pour une instruction create dictionary contient les informations suivantes :

Description générale du dictionnaire.

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

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

Le commentaire AQL Doc pour une instruction create external dictionary contient la description générale concernant le dictionnaire qui est créé. La chaîne suivante illustre le format :

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

L'instruction create table

L'instruction create table crée une table AQL.

L'instruction create table dans AQL est utilisée pour définir des tables de recherche statique afin d'ajouter des informations supplémentaires aux annotations.

Syntaxe

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

Description

  • <table name\>

    Indique le nom de la table à créer. <table name\> peut être un identificateur simple ou un identificateur à guillemets doubles.

  • <colname\>

    Indique le nom de la colonne à créer.

  • <type\>

    Indique le type de données AQL correspondant à la colonne associée. Toutes les colonnes doivent être de type Text, Integer, Float ou Boolean.

  • <value\>

    Indique les tuples à remplir dans la table qui a été créée.

Exemples

Exemple 1 : création d'une table composée de noms de société

Dans cet exemple, l'instruction create table ajoute des métadonnées d'emplacement supplémentaires dans les annotations de nom de société (company names) :

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

Documentation de l'instruction create table avec AQL Doc

Le commentaire AQL Doc pour une instruction create table contient les informations suivantes :

  • Description générale de la table.
  • @field for every column name in the schema of this table.
/** 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');

L'instruction create external table

Vous pouvez utiliser l'instruction create external table pour spécifier une table avec un contenu établi lorsqu'un module compilé est exécuté sur tous les documents d'entrée. Vous fournissez le contenu de la table au moment du chargement au lieu de le fournir dans le code AQL source et vous n'avez pas à recompiler le module.

Les tables externes sont des constructions efficaces qui permettent au développeur AQL d'exposer des points de personnalisation dans un module compilé.

Syntaxe

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

Description

  • <table-name\>

    Indique le nom de la table externe à créer. <table-name\> peut être un identificateur simple ou un identificateur à guillemets doubles.

  • <colname\>

    Indique le nom de la colonne à créer.

  • <type\>

    Indique le type de données AQL correspondant à la colonne associée. Toutes les colonnes doivent être de type Text, Integer, Float ou Boolean.

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

    Indique les colonnes supplémentaires et les objets AQL à utiliser dans la table externe.

  • allow_empty [true|false]

    Indique la valeur de la clause allow_empty.

    • true

      Si la clause est allow_empty true, le module peut être exécuté correctement même si un identificateur URI vers le contenu externe n'est pas fourni pour cette table. Si l'identificateur URI n'est pas fourni, le composant d'exécution la traite comme une table vide.

    • false

      Si la clause est allow_empty false, vous devez fournir un identificateur URI pour l'emplacement du fichier contenant le contenu externe. Le fichier spécifié doit inclure un contenu. Si l'identificateur URI n'est pas fourni ou si le fichier ne contient pas de contenu, le composant d'exécution émet une exception.

Notes sur l'utilisation

  • La représentation compilée du module contient des métadonnées sur les objets externes (vues, dictionnaires et tables) définis par le module.
  • Au moment du chargement des modules, vous devez spécifier une liste d'identificateurs URI vers les tables externes, conformément aux conditions requises par les modules qui sont chargés.
  • Le format pris en charge pour le contenu d'une table externe est un fichier CSV (.csv) avec en-tête.

Le tableau suivant présente les différences entre l'instruction create external table et l'instruction create table :

create external table create table
  • Définit une marque de réservation pour une table dont le contenu est fourni au moment de l'initialisation.
  • Nécessite que le contenu de la table soit disponible au moment de la compilation.
  • Contenu sérialisé dans la représentation compilée (.tam) d'un module.

Exemples

Exemple 1 : création d'une table externe dont le remplissage s'effectue au moment du chargement

La table externe, PersonNegativeClues, s'attend à être remplie au moment du chargement en raison de l'indicateur, allow_empty false.

module PersonModuleFrench;

create external table PersonNegativeClues (name Text)
  allow_empty false;

export table PersonNegativeClues;

Exemple 2 : création d'un dictionnaire avec une table externe

Les dictionnaires peuvent également être créés à partir de tables externes, comme lorsqu'ils sont créés à partir de tables en ligne déclarées avec l'instruction 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;

Documentation de l'instruction create external table avec AQL Doc

Le commentaire AQL Doc pour une instruction create external table contient les informations suivantes :

  • Description générale de la table.
  • @field for every column name in the schema of this table.
/** 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;

L'instruction create external view

L'instruction create external view dans AQL permet la spécification de métadonnées supplémentaires sur un document, par exemple une nouvelle vue, en plus de la vue Document prédéfinie qui détient le contenu textuel et le label.

Syntaxe

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

Description

  • <view_name\>

    Indique le nom interne de la vue externe. La vue externe est référencée sous ce nom dans les règles AQL. Un <view_name\> peut être un identificateur simple ou un identificateur à guillemets doubles. Un <view_name\> ne peut pas contenir de point.

  • <colname\>

    Indique le nom de la colonne à définir dans la vue externe.

  • <type\>

    Indique le type de données correspondant à la colonne associée. Les types de données pris en charge pour les colonnes d'une vue externe sont : Text, Span, Integer et Float.

  • '<view_external_name\>'

    Indique le nom externe de la vue externe. Les systèmes externes qui remplissent les tuples dans la vue externe font référence à la vue externe en utilisant le nom externe. Le '<view_external_name\>' doit être une constante de type String placée entre guillemets simples ('ExternalName').

Exemples

Pour illustrer les vues externes, considérons un exemple d'application qui nécessite que vous identifiez les noms des personnes dans les courriers électroniques.

Exemple 1 : identification des noms de personnes dans les courriers électroniques

Supposons que le texte d'un courrier électronique soit "Ena, please send me the document ASAP". Alors qu'un être humain est en mesure de comprendre qu'Ena est le nom d'une personne en fonction du texte du courrier électronique, les règles AQL écrites pour identifier des noms de personnes avec une grande précision à partir d'un texte général peuvent être trop conservatrices et s'avérer incapables de tirer la même conclusion avec un niveau de fiabilité élevé, en s'appuyant sur le fait qu'Ena est un mot avec une majuscule.

Une façon d'améliorer la couverture des règles consiste à utiliser les mots figurant dans les champs De, A et CC du courrier électronique comme preuves supplémentaires.

Si le courrier électronique est adressé à "Ena Smith," et que l'application rend ces informations accessibles à l'extracteur, le développeur de l'extracteur peut écrire d'autres règles AQL pour améliorer la couverture de l'extracteur qui s'appuie sur la connaissance du domaine selon laquelle les courriers électroniques sont habituellement adressés à des personnes.

Par exemple, vous pouvez écrire des règles SQL pour identifier des unités lexicales correspondant à des personnes dans les champs de métadonnées des courriers électroniques. Vous pouvez ensuite utiliser ces informations comme des éléments probants lorsque vous déterminez si une unité lexicale avec une majuscule dans le texte du courrier électronique est un nom de personne. En général, les métadonnées des courriers électroniques ne font pas partie du courrier électronique proprement dit, mais l'application les rend accessibles à l'extracteur en utilisant une vue externe.

Pour chaque courrier électronique qui doit être traité, l'application peut transmettre le texte du courrier sous forme de texte de document (pour remplir la vue Document) lors de l'exécution. Elle peut également transmettre d'autres métadonnées en utilisant une vue externe définie de manière appropriée.

L'instruction suivante définit une vue externe nommée EmailMetadata. La vue externe a un schéma contenant trois champs de type Text. Lors de l'exécution, la vue EmailMetadata est automatiquement remplie à partir d'un type externe nommé EmailMetadataSrc. Vous pouvez référencer la vue EmailMetadata dans vos règles AQL, comme pour référencer n'importe quelle autre vue.

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

Documentation de l'instruction create external view avec AQL Doc

Le commentaire AQL Doc pour une instruction create external view contient les informations suivantes :

  • Description générale de la vue.
  • @field pour chaque nom de colonne dans la vue.
/**
* 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';

Formats de fichier pour les artefacts externes

Trois types d'artefacts externes sont pris en charge : les vues externes, les dictionnaires externes et les tables externes.

Dictionnaire externe

Le format du fichier contenant les entrées d'un dictionnaire externe est défini comme suit :

  • Fichier texte délimité par des retours chariot.
  • Une entrée de dictionnaire par ligne.
  • L'extension de fichier recommandée est .dict, mais d'autres extensions de fichier sont également prises en charge.
  • Les entrées du dictionnaire peuvent être constituées de plusieurs unités lexicales.
  • Il est possible d'indiquer des commentaires en faisant précéder le contenu du commentaire du caractère #.
  • Les commentaires peuvent commencer n'importe où sur une ligne.
  • Les commentaires sur plusieurs lignes doivent contenir le caractère # au début de chaque ligne.
  • Les entrées du dictionnaire peuvent contenir des caractères de commentaire, si chacun de ces caractères est indiqué avec un caractère d'échappement correspondant à une barre oblique inversée. Par exemple, \#.

Table externe

Le format de fichier pris en charge pour le contenu d'une table externe est un fichier .csv avec en-tête.

L'exemple suivant illustre une instruction create external table et le fichier .csv qui spécifie le contenu de cette table externe.

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

La première ligne du fichier .csv contient l'en-tête. Les lignes restantes contiennent les données.

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

Vue externe

Le contenu des vues externes peut être spécifié ainsi :

  • Lorsque vous exécutez un extracteur, vous pouvez spécifier le contenu de la vue externe d'une collection de données uniquement si vous utilisez le format d'entrée JSON.

Fonctions intégrées

AQL comporte toute une collection de fonctions intégrées à utiliser dans les règles d'extraction.

  • Fonctions d'agrégation Les fonctions d'agrégation sont utilisées pour appliquer des opérations (par exemple, comptage, opérations mathématiques et autres opérations) sur un ensemble de valeurs d'entrée. Ces fonctions ne renvoient qu'un seul résultat.
  • Fonctions de prédicat Les fonctions de prédicat testent un prédicat particulier sur ses arguments d'entrée et renvoient la valeur booléenne correspondante.
  • Fonctions scalaires Les fonctions scalaires effectuent une opération sur les valeurs d'un champ dans un ensemble de tuples d'entrée et renvoient une valeur non booléenne, par exemple une étendue, un texte ou un nombre entier. Ces fonctions peuvent être utilisées dans la liste select d'une instruction select ou extract. Elles peuvent également être utilisées comme entrées dans les fonctions de prédicat.

Fonctions d'agrégation

Les fonctions d'agrégation sont utilisées pour appliquer des opérations (par exemple, comptage, opérations mathématiques et autres opérations) sur un ensemble de valeurs d'entrée. Ces fonctions ne renvoient qu'un seul résultat.

Ces fonctions peuvent être utilisées dans la liste select d'une instruction select, mais pas dans une instruction extract.

Exemple de forme générale d'un appel de fonction d'agrégation :

Aggregate_Function_Name(argument)

L'argument peut être :

  • Une expression constituée d'une colonne de vue dans la clause from ou d'une combinaison de fonctions scalaires impliquant des colonnes des vues figurant dans la clause from.

    Dans la plupart des cas, sauf indication, les valeurs d'argument null sont ignorées.

  • Le caractère * dans le cas de figure particulier de la fonction d'agrégation Count(*).

    Dans ce cas, toutes les lignes de la sortie sont comptabilisées, y compris les valeurs null.

Fonction d'agrégation Type d'argument Type de retour Valeur renvoyée
Avg(expression) Integer, Float Flottant Moyenne de toutes les valeurs d'entrée ou valeur null si aucune ligne n'est sélectionnée
Count(*) Integer Nombre total de lignes d'entrée
Count(expression) Tous Integer Nombre total de valeurs d'entrée non null
List(expression) Integer, Float, Text, Span Liste de valeurs scalaires du même type comme argument d'entrée Liste non ordonnée de valeurs d'entrée non null : par conséquent, un sac, et non pas un ensemble, pourra contenir des doublons. Liste vide si seules les valeurs null sont sélectionnées
Max(expression) Integer, Float, Text, Span Identique au type d'argument Nombre maximal d'éléments dans les valeurs d'entrée ou null si aucune ligne n'est sélectionnée
Min(expression) Integer, Float, Text, Span Identique au type d'argument Nombre minimal d'éléments dans les valeurs d'entrée ou null si aucune ligne n'est sélectionnée
Sum(expression) Integer, Float Identique au type d'argument Somme de toutes les valeurs d'entrée ou valeur null si aucune ligne n'est sélectionnée

Limitations de la version actuelle :

La version actuelle de AQL prend en charge la création de valeurs scalaires via la liste de fonctions d'agrégation (aggregate).

Exemples

L'exemple suivant montre comment les fonctions d'agrégation peuvent compter le nombre d'annotations de nom de personne ou les ensembles de calcul de prénoms associés à chaque nom distinct identifié dans un document :

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

L'exemple suivant illustre l'utilisation des fonctions Min et 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;

Fonctions de prédicat

Les fonctions de prédicat testent un prédicat particulier sur ses arguments d'entrée et renvoient la valeur booléenne correspondante.

Les arguments d'entrée des fonctions de prédicat comprennent les valeurs renvoyées par d'autres fonctions scalaires ou d'autres fonctions d'agrégation en plus des dictionnaires, des expressions régulières, etc. Ces fonctions peuvent être employées dans la clause where d'une instruction select et dans la clause having d'une instruction extract.

Et

La fonction And accepte un nombre variable d'arguments booléens et renvoie les résultats d'une opération logique AND sur tous les arguments d'entrée.

L'optimiseur AQL ne tente pas d'optimiser l'ordre d'évaluation des arguments dans cette fonction dans le cadre de l'opération logique AND. Si une entrée est null, le résultat est null.

Considérez ce format de requête :

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

Par conséquent, un format de requête qui utilise l'opération AND s'exécute beaucoup plus lentement que la même requête au format :

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

Dans la mesure du possible, utilisez le style SQL et un mot clé à la place de cette fonction.

Contient

La fonction Contains admet deux étendues span1 et span2 en tant qu'arguments :

Contains(<span1>, <span2>)

Cette fonction renvoie TRUE si l'étendue span1 englobe complètement l'étendue span2. Si span2 commence au niveau de span1 ou après le début de cette étendue et se termine au niveau de span1 ou avant la fin de cette étendue, span2 est une étendue entièrement englobée. Si l'un ou l'autre de ces arguments est null, la fonction renvoie null.

ContainsDict

La fonction ContainsDict vérifie si le texte d'une étendue contient une entrée provenant d'un dictionnaire donné. Cette fonction admet en arguments d'entrée un dictionnaire, une spécification d'indicateurs facultatifs et une étendue à évaluer.

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

La fonction ContainsDict renvoie TRUE si l'étendue contient une ou plusieurs correspondances du dictionnaire. Les indicateurs peuvent être Exact ou IgnoreCase.

  • Si l'indicateur Exact est utilisé, une correspondance sensible à la casse est établie pour chaque terme figurant dans le dictionnaire.
  • Si l'indicateur IgnoreCase est utilisé, la correspondance est établie pour chaque terme du dictionnaire sans tenir compte de la casse.
  • Si aucun indicateur n'est spécifié, le dictionnaire établit les correspondances en fonction d'un indicateur qui a été spécifié lorsqu'il a été créé. Si aucun indicateur n'a été spécifié lors de sa création, les correspondances sont établies en utilisant l'indicateur IgnoreCase.

Si l'étendue est null, la fonction renvoie null.

L'exemple suivant illustre l'utilisation de la fonction 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);

Les dictionnaires sont toujours évalués en fonction des limites d'unités lexicales. Par exemple, si un dictionnaire est constitué du terme fish, il n'existe aucune correspondance dans le texte Let's go fishing!.

ContainsDicts

La fonction ContainsDicts vérifie si le texte d'une étendue (span) contient une entrée d'un dictionnaire donné. Cette fonction admet en arguments d'entrée deux dictionnaires ou plus, une spécification d'indicateurs facultatifs et une étendue à évaluer.

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

La fonction ContainsDicts renvoie TRUE si l'étendue contient une ou plusieurs correspondances avec au moins un des dictionnaires spécifiés. Les indicateurs peuvent être Exact ou IgnoreCase.

  • Si l'indicateur Exact est utilisé, une correspondance sensible à la casse est établie pour chacun des termes figurant dans les dictionnaires.
  • Si l'indicateur IgnoreCase est utilisé, la correspondance est établie pour chacun des termes figurant dans les dictionnaires sans tenir compte de la casse.
  • Si aucun indicateur n'est spécifié, le dictionnaire établit les correspondances en fonction d'un indicateur qui a été spécifié lorsqu'il a été créé. Si aucun indicateur n'a été spécifié lors de sa création, les correspondances sont établies en utilisant l'indicateur IgnoreCase.

Si l'un ou l'ensemble de ces arguments est null, la fonction renvoie null.

L'exemple suivant illustre l'utilisation de la fonction ContainsDicts avec l'indicateur Exact :

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

ContainsRegex

La fonction ContainsRegex vérifie si le texte d'une étendue correspond à une expression régulière donnée. Cette fonction accepte une expression régulière avec laquelle effectuer la correspondance, une spécification d'indicateurs facultatifs et l'étendue d'entrée à prendre en compte pour établir la correspondance.

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

La fonction renvoie TRUE si le texte de l'étendue, qui est considéré comme une chaîne Java™ distincte, contient une ou plusieurs correspondances de l'expression régulière. La fonction renvoie null si l'étendue est null. Les indicateurs facultatifs affectent le comportement de la correspondance, de la même façon que les indicateurs utilisés dans les expressions régulières Java.

La chaîne d'indicateurs est formée en combinant un ou plusieurs indicateurs suivants en utilisant | comme séparateur :

  • CANON_EQ
  • CASE_INSENSITIVE
  • DOTALL
  • LITERAL
  • MULTILINE
  • UNICODE (n'a pas de sens sans l'indicateur CASE_INSENSITIVE)
  • UNIX_LINES

Exemple de chaîne d'indicateurs :

'UNICODE | CASE_INSENSITIVE'

Examinez cet exemple dans lequel ContainsRegex identifie des noms de produit ainsi que les mentions de leur numéro de version de chaque côté. Contrairement à l'exemple indiqué pour MatchesRegex, un numéro de version n'est pas strictement identifié à l'aide de l'expression régulière (regex), mais par le contexte autour d'une mention de nom de produit contenant une unité lexicale dont la correspondance est établie avec l'expression régulière (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)
);

Egal

La fonction Equals admet deux arguments de type arbitraire :

Equals(<arg1>, <arg2>)

Deux étendues sont considérées comme identiques (equal) si elles commencent et se terminent toutes les deux aux mêmes valeurs de décalage et contiennent le même texte. Si l'un des arguments est null, la fonction renvoie null.

L'exemple suivant illustre l'utilisation de la fonction 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));

Suit

La fonction de prédicat Follows admet deux arguments d'étendue (span1 et span2) et deux arguments d'entier :

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

La fonction renvoie TRUE si le nombre de caractères entre la fin de l'étendue span1 et le début de l'étendue span2 est compris entre minchar et maxchar inclus. Si l'un des arguments est null, la fonction renvoie null.

FollowsTok

La fonction de prédicat FollowsTok est une version de la fonction Follows. Cependant, les arguments de distance de FollowsTok sont exprimés en termes d'unités lexicales et non pas de caractères :

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

La fonction FollowsTok renvoie TRUE si le nombre d'unités lexicales entre la fin de l'étendue span1 et le début de l'étendue span2 est compris entre mintok et maxtok inclus. Si l'un des arguments est null, la fonction renvoie null.

GreaterThan

La fonction GreaterThan admet deux arguments de type arbitraire :

GreaterThan(<arg1>, <arg2>)

La fonction renvoie TRUE si <arg1> est supérieur à <arg2>. La fonction renvoie FALSE si l'un des arguments est null.

IsNull

La fonction IsNull teste si les données sont ou non de type null. Elle admet un seul argument de n'importe quel type et renvoie TRUE si cet argument est null, et FALSE dans le cas contraire. Le comportement de ce prédicat et du prédicat NotNull déjà défini est différent de tous les autres prédicats qui renvoient null lorsque l'entrée a la valeur null.

MatchesDict

La fonction MatchesDict admet en arguments un dictionnaire (comme dans une extraction de dictionnaire), une spécification d'indicateurs facultatifs et une étendue :

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

La fonction MatchesDict renvoie TRUE si l'étendue correspond exactement à un ou plusieurs termes figurant dans le dictionnaire. Les indicateurs peuvent être Exact ou IgnoreCase.

  • Si l'indicateur Exact est utilisé, une correspondance sensible à la casse est établie pour chaque terme figurant dans le dictionnaire.
  • Si l'indicateur IgnoreCase est utilisé, la correspondance est établie pour chaque terme du dictionnaire sans tenir compte de la casse.
  • Si aucun indicateur n'est spécifié, le dictionnaire établit les correspondances en fonction d'un indicateur qui a été spécifié lorsqu'il a été créé. Si aucun indicateur n'a été spécifié lors de sa création, les correspondances sont établies en utilisant l'indicateur IgnoreCase.

Si l'un des arguments est null, la fonction renvoie null.

Les dictionnaires sont toujours évalués en fonction des limites d'unités lexicales. Par exemple, si un dictionnaire est constitué du terme fish, il n'existe aucune correspondance dans le texte Let's go fishing!.

MatchesRegex

La fonction MatchesRegex comporte une syntaxe similaire à ContainsRegex. Contrairement à la fonction ContainsRegex, la fonction MatchesRegex renvoie TRUE si le texte complet de l'étendue, pris sous la forme d'une chaîne Java distincte, correspond à l'expression régulière. Si l'un des arguments est null, la fonction renvoie null. Les indicateurs facultatifs affectent le comportement de la correspondance, de la même façon que les indicateurs utilisés dans les expressions régulières Java.

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

La chaîne d'indicateurs est formée en combinant un sous-ensemble de ces indicateurs en utilisant | comme séparateur :

  • CANON_EQ
  • CASE_INSENSITIVE
  • DOTALL
  • LITERAL
  • MULTILINE
  • UNICODE (n'a pas de sens sans l'indicateur CASE_INSENSITIVE)
  • UNIX_LINES

Exemple de chaîne d'indicateurs :

'UNICODE | CASE_INSENSITIVE'

Examinez cet exemple dans lequel la fonction MatchesRegex est utilisée pour identifier des noms de produit ainsi que les mentions de leur numéro de version à droite. Contrairement à l'exemple de la section ContainsRegex, le numéro de version exact est identifié par l'unité lexicale qui suit immédiatement la mention de nom de produit.

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

Non

La fonction Not admet un seul argument booléen (Boolean) et renvoie son complément. Si l'argument est null, la fonction renvoie null.

NotNull

La fonction NotNull admet un argument de n'importe quel type.

Comme son nom l'indique, la fonction NotNull renvoie TRUE si la valeur de l'argument n'est pas null et FALSE si la valeur de l'argument est null.

Ou

La fonction Or admet un nombre variable d'arguments booléens non null. Si l'un des arguments est null, la fonction renvoie null.

La fonction Or renvoie TRUE si l'un d'entre eux est évalué avec la valeur TRUE.

Chevauchements

La fonction Overlaps admet deux arguments d'étendue (span1 et span2) :

Overlaps(<span1>, <span2>)

La fonction renvoie TRUE si deux étendues d'entrée se chevauchent dans le texte du document. La fonction renvoie null si l'un des arguments est null.

Fonctions scalaires

Les fonctions scalaires effectuent une opération sur les valeurs d'un champ dans un ensemble de tuples d'entrée et renvoient une valeur non booléenne, par exemple une étendue, un texte ou un nombre entier. Ces fonctions peuvent être utilisées dans la liste select d'une instruction select ou extract. Elles peuvent également être utilisées comme entrées dans les fonctions de prédicat.

Si un objet de texte (Text) est fourni alors qu'un objet d'étendue (Span) est requis, un objet Span converti est automatiquement généré en fonction de cet objet Text avec des décalages de début et de fin couvrant la totalité de l'objet Text.

Si un objet d'étendue (Span) est fourni alors qu'un objet de texte (Text) est requis, un objet Text est automatiquement généré à partir de la valeur de texte de l'objet Span.

Chomp

La fonction Chomp est semblable à l'opérateur Chomp dans Perl, à ceci près que Chomp opère sur des étendues et non pas des chaînes :

Chomp(<span1>)

L'exemple suivant illustre l'utilisation de la fonction Chomp.

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

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

Si l'étendue d'entrée contient un blanc à la fin ou au début, la fonction Chomp réduit l'étendue de sorte à éliminer le blanc. La fonction renvoie ensuite une nouvelle étendue sans aucun blanc au début ou à la fin. Si l'étendue d'entrée ne comporte aucun blanc au début ou à la fin, la fonction Chomp renvoie la même étendue. Si l'étendue d'entrée est null, la fonction Chomp renvoie null.

CombineSpans

La fonction CombineSpans admet deux étendues (span1 et span2) en entrée et renvoie l'étendue la plus courte qui couvre les deux étendues d'entrée si les étendues sont basées sur le même objet de texte.

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

La fonction CombineSpans respecte l'ordre des étendues d'entrée, sauf si vous utilisez le paramètre IgnoreOrder. Lorsque le paramètre facultatif IgnoreOrder est utilisé, l'ordre des deux étendues est ignoré.

L'exemple suivant illustre l'utilisation de la fonction CombineSpans.

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

La sémantique de la fonction se décline comme suit :

  • Si l'une des étendues span1 ou span2 a la valeur null ou si les deux étendues portent sur des objets de texte différents, la fonction renvoie null.
  • Sinon, si l'étendue span1 est inférieure à l'étendue span2 ou si le paramètre IgnoreOrder est utilisé, la fonction renvoie l'étendue la plus courte couvrant à la fois les étendues span1 et span2.
  • Sinon (l'étendue span1 est supérieure à l'étendue span2 et le paramètre IgnoreOrder n'est pas utilisé), la fonction renvoie une erreur d'exécution.

En fonction de la définition de l'étendue (Span), les différents scénarios d'arguments pour la fonction CombineSpans sont les suivants :

  • L'étendue span2 est toujours après span1. En d'autres termes, l'ordre de gauche à droite est maintenu :

    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]
    
  • L'étendue span2 n'est pas après span1. En d'autres termes, l'ordre de gauche à droite n'est pas maintenu :

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

La fonction GetBegin admet un seul argument d'étendue (span) et renvoie le décalage de début de l'étendue d'entrée.

Exemple :

GetBegin([5, 10])

renvoie la valeur 5.

De même, la fonction GetEnd renvoie le décalage de fin de son étendue d'entrée.

L'exemple suivant illustre l'utilisation des fonctions GetBegin et GetEnd.

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

Pour ces deux fonctions, si l'argument est null, la fonction renvoie null.

GetLanguage

La fonction GetLanguage admet un seul argument d'étendue et renvoie le code de langue à deux lettres correspondant au texte source de l'étendue. Si l'argument est null, la fonction renvoie null.

Cette instruction produit des résultats pertinents uniquement si la source des données balise les champs de texte avec les codes de langue appropriés.

GetLemma

La fonction GetLemma admet en argument un seul objet de type étendue (Span) ou texte (Text) et renvoie une chaîne contenant la forme lemmatisée de l'étendue d'entrée. Si l'argument est null, la fonction renvoie null. Avec des entrées de dictionnaire pour la correspondance de lemme, cette fonction peut déterminer la forme lemmatisée de différentes unités lexicales, telles qu'elles sont renvoyées par le marqueur sémantique. Par exemple, pour l'étendue went shopping, la fonction GetLemma renvoie la chaîne de lemmes go shop.

Les résultats de cette fonction respectent les règles suivantes :

  • Si l'étendue d'entrée commence au début d'une unité lexicale et se termine à la fin d'une unité lexicale, le résultat contient la séquence de lemmes qui commence par le lemme de la première unité lexicale, suivi d'un blanc, puis du lemme de la deuxième unité lexicale, suivi d'un blanc, et ainsi de suite (par exemple, chien chat poisson oiseau ...). Si le lemme d'une unité lexicale est constitué de blancs, indiquez-les avec le caractère d'échappement correspondant à la barre oblique inversée ( \ ).
  • Si l'étendue d'entrée commence ou se termine par un blanc, (par exemple, elle commence ou se termine entre deux unités lexicales), la fonction ignore les blancs au début et à la fin.
  • Si l'étendue d'entrée commence ou se termine au milieu d'une unité lexicale, la sortie est formée du contenu suivant, dans cet ordre, séparé par un blanc :
    • La forme de surface de la première unité lexicale partielle, si elle existe.
    • La séquence de lemmes qui correspond aux unités lexicales complètes (de la première à la dernière). Si le lemme d'une des unités lexicales complètes est constitué de blancs, indiquez les blancs en utilisant devant le caractère d'échappement correspondant à la barre oblique inversée ( \ ).
    • La forme de surface de la dernière unité lexicale partielle si elle existe.

Cette fonction renvoie une erreur si le marqueur sémantique utilisé n'est pas en mesure de produire des lemmes.

Vous pouvez utiliser la fonction GetLemma() pour créer des dictionnaires de formes lemmatisées. Appelez la fonction GetLemma() sur une entrée contenant les termes dont vous voulez inclure la forme lemmatisée dans le dictionnaire.

GetLength

La fonction GetLength admet un seul argument d'étendue et renvoie la longueur de l'étendue d'entrée. Si l'argument est null, la fonction renvoie null.

Exemple :

GetLength([5, 12])

Renvoie la valeur 7.

GetLengthTok

La fonction GetLengthTok admet un seul argument d'étendue et renvoie la longueur de l'étendue d'entrée en unités lexicales. Si l'argument d'entrée est null, la fonction renvoie null.

GetString

La fonction GetString admet en argument un seul objet AQL et renvoie un objet de texte (Text) formé à partir de la représentation de chaîne de l'objet.

Pour les arguments d'étendue et de texte, les valeurs renvoyées sont différentes de celles renvoyées par la fonction GetText(). Pour les objets Text, la valeur renvoyée comprend la chaîne de texte entre guillemets simples. Pour les objets Span, la valeur renvoyée comprend en plus les décalages entre crochets.

Pour les listes scalaires, cette fonction renvoie les valeurs GetString() des éléments de la liste, concaténés avec des points-virgules. Pour les arguments de type entier (Integer), nombre à virgule flottante (Float), booléen (Boolean) et chaîne (String), la fonction renvoie la valeur de l'argument sous forme de chaîne. Pour les arguments null, cette fonction renvoie null.

GetText

La fonction GetText admet un argument unique d'étendue ou de texte. Pour l'entrée correspondant à une étendue, elle renvoie l'objet de texte en fonction de la chaîne de texte réelle marquée par l'étendue. Pour l'entrée de texte, elle renvoie l'objet de texte d'entrée. Si l'entrée est null, cette fonction renvoie null. Par exemple :

GetText([5, 12])

L'étendue renvoie la sous-chaîne du document de la position des caractères 5 à 12.

La fonction GetText a deux utilisations principales.

Test d'une équivalence de chaîne entre le texte marqué par deux étendues.

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

Fractionnement d'un document en sous-documents plus petits.

Par exemple, si le document principal est un blogue contenant plusieurs entrées, vous pouvez utiliser la fonction GetText pour créer un sous-document pour chaque entrée de blogue.

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 et RightContext

La fonction LeftContext admet en entrée une étendue et un entier :

LeftContext(<input span>, <nchars>)

La fonction LeftContext(<input span\>, <nchars\>) renvoie une nouvelle portée qui contient les caractères nchars du document immédiatement à gauche de <input span\>. Si l'étendue d'entrée commence à moins de <nchars\> caractères du début du document, LeftContext() renvoie une étendue qui commence au début du document et continue jusqu'au début de l'étendue d'entrée.

Par exemple, LeftContext([20, 30], 10) renvoie l'étendue [10, 20]. L'étendue LeftContext([5, 10], 10) renvoie [0, 5].

Si l'entrée commence au premier caractère du document, la fonction LeftContext() renvoie une étendue égale à zéro. De même, la fonction RightContext renvoie le texte situé à droite de son étendue d'entrée. Pour ces deux fonctions, si l'un des arguments est null, la fonction renvoie null.

LeftContextTok et RightContextTok

Les fonctions LeftContextTok et RightContextTok sont des versions des fonctions LeftContext et RightContext qui considèrent les distances en termes d'unités lexicales :

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

L'exemple suivant illustre l'utilisation de la fonction 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;

Pour ces deux fonctions, si l'un des arguments est null, la fonction renvoie null.

Remap

La fonction Remap admet un seul argument d'étendue :

Remap(<span>)

Si l'étendue d'entrée couvre un objet de texte obtenu par la transformation d'un autre objet de texte, la fonction Remap convertit l'étendue en étendue sur le texte "source" d'origine.

Par exemple, si l'étendue N.name couvre un document dont les balises ont été retirées et qui a été obtenu en exécutant l'instruction detag en HTML,

Remap(<N.name>)

renvoie une étendue équivalente dans le HTML d'origine.

Si l'argument d'étendue a été obtenu en exécutant l'instruction detag sur un document vide, la fonction procède à un nouveau mappage des étendues jusqu'au début du document (c'est-à-dire, Document.text[0-0]). De plus, si l'instruction detag a renvoyé une chaîne vide, la fonction procède également au nouveau mappage des étendues jusqu'au début du document. La seule partie d'AQL qui obtient un objet de texte dérivé de ce type est l'instruction detag.

L'exemple suivant illustre l'utilisation de la fonction Remap :

-- Detag the HTML document and annotate the anchor tags
detag Document.text as DetagedDoc
    annotate
    element 'a' as Anchor;

-- Remap the Anchor Tags
create view AnchorTag as
select Remap(A.match) as anchor
from Anchor A;

Si l'argument de Remap n'est pas un objet de texte dérivé ou une étendue couvrant un objet de texte dérivé, la fonction génère une erreur. Si l'argument est null, la fonction renvoie null.

SpanBetween

La fonction SpanBetween admet une entrée formée de deux étendues (span1 et span2) et renvoie l'étendue qui couvre exactement le texte compris entre les deux étendues si les étendues sont basées sur le même objet de texte, et renvoie null si elles sont basées sur des objets de texte différents :

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

Lorsque le paramètre facultatif IgnoreOrder est utilisé, l'ordre des deux étendues est ignoré par le compilateur AQL.

Si aucun texte n'existe entre les deux étendues, SpanBetween renvoie une étendue vide qui commence à la fin de <span1>.

Comme CombineSpans, SpanBetween est sensible à l'ordre de ses entrées, sauf si vous utilisez le paramètre IgnoreOrder. Par conséquent,

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

renvoie l'étendue [10, 50], alors que

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

renvoie l'étendue [60, 60].

Si l'argument de SpanBetween est null, la fonction renvoie null.

SpanIntersection

La fonction SpanIntersection admet deux étendues en entrée et envoie une étendue qui couvre le texte traité par ces deux étendues si les étendues sont basées sur le même objet de texte, et renvoie null si elles sont basées sur des objets de texte différents :

SpanIntersection(<span1>, <span2>)

Exemple :

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

renvoie l'étendue [10, 20], alors que

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

renvoie l'étendue [7, 10].

Si les deux étendues ne se chevauchent pas, la fonction SpanIntersection renvoie null. Si l'entrée d'une des étendues est null, la fonction renvoie null.

SubSpanTok

La fonction SubSpanTok admet une étendue en entrée et une paire de décalages dans cette étendue :

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

Comme le nom de la fonction le suggère, les arguments <first_tok> et <last_tok> sont des distances en unités lexicales, selon le marqueur sémantique que le système est configuré pour utiliser.

La fonction SubSpanTok renvoie une nouvelle étendue qui couvre la plage d'unités lexicales indiquée, incluse, au sein de l'étendue d'entrée. Si l'étendue indiquée commence à l'intérieur de l'étendue et dépasse la fin de l'étendue, la portion de la plage incluse est renvoyée. Si <first_tok> représente une distance au-delà de l'étendue cible, SubSpanTok renvoie une étendue de longueur zéro qui commence au début de l'étendue d'entrée.

Si une entrée est null, la fonction renvoie null.

ToLowerCase

La fonction ToLowerCase admet un seul objet en argument et renvoie une représentation de l'objet sous forme de chaîne en minuscules. La conversion en chaîne est traitée de la même manière que la conversion effectuée par la fonction GetString().

L'utilisation principale de cette fonction est la réalisation de jointures d'égalité qui ne tiennent pas compte des majuscules et des minuscules :

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

Si l'objet d'entrée est null, la fonction renvoie null.

L'instruction create function

Pour réaliser des opérations sur des valeurs extraites qui ne sont pas prises en charge par AQL, vous pouvez définir des fonctions personnalisées à utiliser dans les règles d'extraction que l'on désigne par fonctions définies par l'utilisateur (UDF).

AQL prend en charge les fonctions scalaires définies par l'utilisateur et les fonctions de table définies par l'utilisateur. Java™ et PMML sont les seuls langages applicables pris en charge pour les fonctions UDF. Une fonction scalaire renvoie une seule valeur scalaire et une fonction de table renvoie un ou plusieurs tuples, autrement dit, une table.

Pour implémenter des fonctions définies par l'utilisateur, procédez comme suit :

  1. Implémentation de la fonction

    AQL prend en charge les fonctions définies par l'utilisateur (UDF) implémentées en langage Java ou PMML.

  2. Déclaration de la fonction dans AQL.

    Vous pouvez rendre accessibles à AQL les fonctions scalaires définies par l'utilisateur et les modèles d'apprentissage automatique de fichiers PMML en utilisant l'instruction create function.

  3. Utilisation de la fonction dans AQL.

    Les fonctions définies par l'utilisateur fonctionnent avec des instructions et clauses AQL.

  4. Débogage de la fonction UDF.

    Etant donné que les fonctions définies par l'utilisateur (UDF) en langage Java sont implémentées sous forme de méthodes publiques dans des classes Java, le débogage de vos fonctions UDF est identique à celui de vos programmes Java.

Implémentation des fonctions définies par l'utilisateur

AQL prend en charge les fonctions définies par l'utilisateur (UDF) implémentées en langage Java™ ou PMML.

Cette section étudie particulièrement les fonctions UDF implémentées en Java. Pour les fonctions UDF implémentées en PMML, le modèle d'apprentissage automatique est stocké dans le fichier XML PMML. Reportez-vous à la documentation de PMML pour savoir comment créer ces modèles : [http://dmg.org/pmml/v4-1/GeneralStructure.html]

Vous pouvez implémenter une fonction scalaire UDF sous forme de méthode publique dans une classe Java. Vous pouvez implémenter une fonction de table UDF sous forme de méthode publique dans une classe Java qui étend l'API com.ibm.avatar.api.udf.TableUDFBase. De plus, une fonction de table UDF peut éventuellement remplacer la méthode initState() de la superclasse com.ibm.avatar.api.udf.TableUDFBase.

Si la fonction UDF comporte un paramètre de type Span, Text ou ScalarList, ou que le type de valeur renvoyé est Span, Text ou ScalarList, la classe Java doit importer les classes com.ibm.avatar.algebra.datamodel.Span, com.ibm.avatar.algebra.datamodel.Text ou com.ibm.avatar.algebra.datamodel.ScalarList à compiler.

Les fonctions de table nécessitent des API supplémentaires pour fournir les informations du schéma de sortie. Ces API appartiennent à la même classe de base com.ibm.systemt.api.udf.TableUDFbase. Si une sous-classe contient plusieurs fonctions de table, un objet Java distinct est créé pour chaque instance.

Pour que le code de la fonction UDF puisse extraire des ressources qui ne sont pas des classes de son fichier JAR, la seule méthode prise en charge est getResourceAsStream(). Les autres méthodes d'accès aux ressources (telles que getResource(), getResources(), getSystemResource()) ne sont pas prises en charge. Par exemple, un fichier JAR de fonction UDF contenant le fichier de propriétés my.properties dans le package com.ibm.myproject.udfs, peut accéder aux ressources avec l'instruction Java suivante :

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

Cycle de vie des fonctions UDF implémentées en Java

Les opérations suivantes sont effectuées lorsque l'extracteur est compilé (API CompileAQL.compile()), instancié (API OperatorGraph.createOG()) et validé (API OperatorGraph.validateOG()), une seule fois pour chaque instruction create function dans AQL :

  1. Chargement de la classe Java contenant la méthode UDF à l'aide d'un tout nouveau chargeur de classe. La classe est recherchée dans le fichier JAR de la fonction UDF indiqué dans l'instruction create function correspondante. Toutes les autres classes requises lors du chargement de cette classe font également l'objet d'une recherche dans le même fichier JAR de l'UDF et, si elles sont introuvables, la recherche est déléguée au chargeur de classe qui a instancié l'exécution.
  2. Création de cette classe.
  3. Pour les fonctions de table UDF, appel de la méthode initState().

Etant donné que ces étapes sont suivies pour chaque instruction create function, si une classe Java contient plusieurs méthodes UDF (et que toutes ces méthodes sont utilisées dans AQL dans des instructions create function différentes), la classe est chargée plusieurs fois, et dans un chargeur de classe distinct (étape 1) à chaque fois. De plus, plusieurs instances de la classe sont créées (étape 2) et la méthode initState() est appelée une fois pour chaque instance (étape 3). La raison pour laquelle toutes les fonctions UDF aboutissent à un chargeur de classe distinct est de permettre à différentes fonctions UDF d'utiliser des versions différentes de la même classe (ou bibliothèque).

Lors de l'exécution (API OperatorGraph.execute()), la classe UDF n'est pas chargée à nouveau, car elle a été chargée lors de l'instanciation de l'extracteur. La méthode Java qui implémente la fonction UDF est appelée si nécessaire pour calculer les différentes parties de la sortie. Lorsque l'extracteur est utilisé dans une seule unité d'exécution, cela signifie qu'il existe de zéro à plusieurs appels possibles pour chaque document d'entrée (et plus probablement plusieurs appels sur la durée de vie de l'objet OperatorGraph). Lorsque l'extracteur est partagé entre plusieurs unités d'exécution, les différentes unités d'exécution peuvent accéder à la méthode à peu près au même moment (avec différentes entrées).

Si vous avez besoin d'une partie spécifique de code UDF qui doit être évaluée une seule fois, par exemple pour initialiser des structures de données nécessaires à la méthode UDF pour les différents appels, ce code ne doit pas être inséré dans la méthode d'évaluation de la fonction UDF, car cette méthode est probablement exécutée plusieurs fois sur la durée de vie de l'extracteur (comme l'objet OperatorGraph), et accessible presque simultanément lorsque l'extracteur est partagé entre plusieurs unités d'exécution. Solutions alternatives :

  1. Pour les fonctions scalaires UDF, suivez les principes de programmation Java standard. Par exemple, mettre le code dans un bloc statique.
  2. Pour les fonctions de table UDF, insérez le code dans la méthode initState() ou suivez les principes de programmation Java standard. Par exemple, mettre le code dans un bloc statique.

Lorsque vous procédez ainsi, n'oubliez pas que la classe doit être chargée plusieurs fois lors de la compilation, l'instanciation et la validation de l'extracteur, comme indiqué dans les étapes 1 à 3 ci-dessus. Si le code qui initialise la fonction UDF est placé dans un bloc statique, ce code est exécuté chaque fois que la classe est chargée (probablement plusieurs fois), générant ainsi une surcharge lors de la compilation et de l'instanciation du graphique de l'opérateur (OperatorGraph). Si cette surcharge est importante, adoptez ces pratiques recommandées :

  • Pour réduire la surcharge lors de la compilation, la meilleure pratique consiste à placer les ressources volumineuses de compilation, telles que les gros dictionnaires ou les fonctions UDF avec des délais d'initialisation importants dans des modules AQL distincts et de les exporter. Essayez de compiler uniquement les modules qui ont changé et les autres modules qui en dépendent.
  • Pour réduire la surcharge lors de l'instanciation et de la validation du graphique de l'opérateur :
    1. Si le code d'initialisation est requis par une seule méthode UDF, placez cette méthode UDF dans une classe Java à part (et mettez le code volumineux de l'instanciation dans un initialiseur statique comme précédemment, ou utilisez un autre mécanisme qui garantit que le code n'est exécuté qu'une seule fois).
    2. Si le code d'initialisation est partagé par plusieurs méthodes UDF, l'environnement d'exécution et AQL ne fournissent pas de mécanisme explicite pour garantir que le code d'initialisation n'est exécuté qu'une seule fois. Dans ce type de situation, si la durée d'initialisation est rédhibitoire, la seule solution possible est de mettre les ressources partagées et le code d'initialisation dans le chemin d'accès aux classes du système. En d'autres termes, placez le code d'initialisation dans une nouvelle classe MySeparateClass.java et stockez le résultat de l'initialisation dans une variable statique de cette classe, par exemple MySeparateClass.myVar. Conditionnez la classe MySeparateClass.java ainsi que toutes les ressources nécessaires lors de l'initialisation dans un fichier JAR et placez ce fichier dans le chemin d'accès aux classes du système. Les méthodes UDF peuvent faire référence au modèle initialisé en utilisant la variable statique MySeparateClass.myVar. Le code d'initialisation n'est désormais exécuté qu'une seule fois, lorsque la classe MySeparateClass.java est chargée par le chargeur de classe du système.

Astuce :

La représentation compilée d'un module (fichier .tam) contient le code binaire sérialisé de la fonction UDF. Par conséquent, si le même code de fonction UDF est référencé par des instructions create function dans deux modules distincts, le code de fonction UDF est sérialisé dans la représentation compilée des deux modules. En d'autres termes, le code de fonction UDF est sérialisé deux fois. Dans ce cas, vous pouvez éviter la redondance en créant un module distinct qui fait office de bibliothèque de fonctions UDF et réutilise cette bibliothèque dans d'autres modules. Pour créer une bibliothèque de fonctions UDF, procédez comme suit :

  1. Créez un module.
  2. Placez tous les fichiers JAR de fonction UDF dans ce module.
  3. Définissez toutes les fonctions nécessaires avec les instructions create function.
  4. Exportez-les toutes avec des instructions export function pour pouvoir les importer et les utiliser dans d'autres modules.

Exemples

Exemple 1 : implémentation d'une fonction scalaire UDF

Cet exemple illustre l'implémentation d'une fonction scalaire UDF nommée toUpperCase. Cette fonction admet en entrée une valeur de type Span et génère en sortie une valeur de chaîne constituée du contenu du texte de l'étendue d'entrée, converti en majuscules.

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

Exemple 2 : implémentation d'une fonction scalaire UDF utilisant une table comme entrée

Cet exemple illustre l'implémentation d'une fonction scalaire UDF nommée TableConsumingScalarFunc. Cette fonction admet deux listes de tuples en entrée et génère une valeur de chaîne qui concatène le contenu des deux listes de tuples en entrée.

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

Exemple 3 : implémentation d'une fonction de table UDF qui utilise une table comme entrée

Cet exemple illustre l'implémentation d'une fonction de table UDF nommée TableConsumingTableFunc. Cette fonction admet deux listes de tuples en entrée et génère en sortie une liste de tuples contenant les tuples de la première entrée entrecoupés de tuples de la deuxième entrée. Notez que l'implémentation est développée à partir de la classe de base com.ibm.avatar.api.udf.TableUDFBase, qui fournit les API permettant d'obtenir les schémas d'entrée et de sortie.

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

}

Déclaration des fonctions définies par l'utilisateur

Vous pouvez rendre accessibles à AQL les fonctions scalaires définies par l'utilisateur et les modèles d'apprentissage automatique de fichiers PMML en utilisant l'instruction create function.

Syntaxe

La syntaxe générale de l'instruction create function est la suivante :

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

Description

  • <function-name\>

    Le <function-name\> déclare le nom AQL de la fonction définie par l'utilisateur. La fonction UDF est référencée avec ce nom dans le code AQL.

  • <input-schema-definition\>

    Indique les paramètres d'entrée de la fonction UDF. Un paramètre d'entrée a un nom, qui est spécifié comme <column-name\> et peut être un type scalaire ou un pointeur de table. En langage PMML, la fonction doit comporter une seule table nommée params comme argument.

  • <column-name\>

    Indique le nom d'une colonne dans l'entrée ou la sortie de la fonction UDF.

  • <data-type\>

    Type d'un paramètre scalaire d'entrée dans la fonction UDF, type de colonne dans le schéma d'une table d'entrée dans la fonction UDF ou dans le schéma de la table de sortie de la fonction UDF. Les valeurs possibles pour <data-type\> sont Integer, Float, String, Text, Span, Boolean ou ScalarList.

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

    Ce type d'entrée permet à une fonction d'admettre en entrée le contenu intégral d'une vue AQL donnée, telle qu'elle est calculée dans le document en cours. Le paramètre locator référence des vues ou des tables en tant qu'arguments.

  • <return-type\>

    Pour les fonctions scalaires définies par l'utilisateur, <return-type\> indique le type de la valeur scalaire qui est renvoyée par la fonction définie par l'utilisateur. Les valeurs possibles de type de retour sont : Integer, Float, String, Text, Span, Boolean ou ScalarList. Si le type de retour est Integer, la fonction Java™ qui implémente la fonction UDF renvoie des objets de type Integer (entier). L'implémentation de la fonction UDF ne peut pas renvoyer la valeur primitive int. Si le type de retour est Text ou Span, spécifiez le paramètre d'entrée à partir duquel est dérivé le type de retour. Vous pouvez spécifier le paramètre d'entrée en utilisant la spécification facultative like, car les étendues proviennent toujours d'une colonne sous-jacente. Si le type de retour est ScalarList, spécifiez le paramètre d'entrée à partir duquel le type scalaire figurant dans la liste ScalarList doit être induit. En langage PMML, la fonction doit renvoyer une table.

  • <output-schema-definition\>

    Pour les fonctions de tables définies par l'utilisateur, <output-schema-definition\> indique le schéma de sortie de la table qui est renvoyée par la fonction définie par l'utilisateur, y compris les noms de colonne et leurs types.

  • <ext-name\>

    Le paramètre <external_name> indique où trouver l'implémentation de la fonction UDF. Lorsque le langage est Java, il s'agit d'une chaîne au format '<jar-file-name\>:<fully-qualified-class-name\>!<method-name\>', qui se compose de trois parties :

    • Nom du fichier JAR (jar-file-name) : lorsque vous compilez en AQL modulaire, les références aux emplacements des fichiers JAR des fonctions UDF doivent être relatifs à la racine du module dans lequel la référence est indiquée.
    • Nom de classe (fully-qualified-class-name) : nom de classe qualifié complet contenant l'implémentation de la fonction UDF
    • Nom de la méthode (method-name) : la méthode doit être une méthode publique de la classe. La signature de la méthode doit correspondre aux types de paramètre indiqués dans l'instruction create function. La conversion automatique des types n'est pas effectuée par le composant d'exécution. En langage PMML, la clause <external_name> indique une chaîne correspondant à l'emplacement du fichier PMML relatif au répertoire racine du module. L'implémentation actuelle prend en charge les modèles exprimés avec la version standard 4.1 de PMML et les évalue en utilisant la version 1.0.22 org.jpmml de la bibliothèque.
  • language

    La spécification du langage pointe vers le langage d'implémentation de la fonction UDF. Le composant d'exécution ne prend en charge que les fonctions UDF implémentées en Java™.

  • deterministic/not deterministic

    Le paramètre facultatif deterministic/not deterministic indique si la fonction est sans état. Une fonction déterministe renvoie toujours la même valeur pour le même ensemble de valeurs d'entrée.

  • return null on null input

    Le paramètre facultatif return null on null input indique le comportement de la fonction lorsqu'une ou plusieurs valeurs d'entrée sont null. Si le paramètre return null on null input est spécifié, le système renvoie null pour une valeur d'entrée null sans appeler la fonction UDF. Si le paramètre called on null input est indiqué, la fonction UDF est appelée même pour les valeurs d'entrée null.

Remarques relatives à l'utilisation des fonctions définies par l'utilisateur implémentées en PMML

Les fonctions créées à partir de fichiers PMML admettent une table unique nommée params comme argument et génèrent une table en sortie. L'implémentation de la fonction mappe les champs d'entrée entre les schémas d'entrée et de sortie déclarés dans l'instruction create function et le schéma spécifié dans le fichier PMML. En d'autres termes, la section DataDictionary qui décrit les noms et les types de champs pouvant apparaître dans les enregistrements d'entrée et de sortie produits et consommés par le modèle, la section MiningSchema indiquant les fichiers nommés définis dans la section DataDictionary qui figurent dans chaque tuple représentant un vecteur de caractéristique et la section Output indiquant les champs nommés définis dans la section DataDictionary qui figurent dans chaque tuple de la représentation externe de la sortie du modèle. Ces fonctions doivent être des fonctions de table. Chaque ligne de la table est transmise au modèle PMML et produit une ligne en sortie.

Ces informations de schéma sont nécessaires car les systèmes de type PMML et AQL ne correspondent pas parfaitement. Par exemple, PMML comporte plusieurs types pour représenter les horodatages, alors qu'AQL nécessite actuellement que les utilisateurs codent les horodatages sous forme de valeurs de chaîne. Les informations de schéma permettent également aux développeurs de savoir qui connaît AQL et pas PMML pour comprendre l'ensemble de règles AQL.

Le compilateur AQL vérifie le schéma d'entrée par rapport au schéma d'entrée du fichier PMML pour s'assurer que les deux schémas sont compatibles. Si les deux schémas contiennent des champs du même nom mais des types incompatibles, la compilation échoue en renvoyant le message d'erreur approprié. Si les schémas d'entrée ou de sortie de la fonction contiennent des colonnes en plus ou des colonnes manquantes, la fonction resulting ignore ces colonnes et ne génère pas d'erreur. L'ordre des noms de colonne peut être différent entre la définition AQL et le fichier PMML. Si un nom de colonne apparaît à la fois dans les schémas d'entrée et de sortie mais pas dans le schéma PMML, les valeurs de cette colonne sont transmises à la sortie de la fonction.

Exemples

Exemple 1 : déclaration de fonctions scalaires UDF avec des valeurs scalaires en entrée à l'aide de Java

L'exemple suivant présente une instruction create function qui déclare une fonction nommée udfCombineSpans. La fonction définie par l'utilisateur admet deux étendues en entrée et renvoie une étendue fusionnée semblable à la première étendue d'entrée. La fonction UDF Java™ est conditionnée dans un fichier JAR nommé udfs.jar, sous le répertoire udfjars. La méthode utilisée pour implémenter la fonction est combineSpans dans la classe com.ibm.test.udfs.MiscScalarFunc. La méthode déclare également une fonction udfSpanGreaterThan qui renvoie la valeur true si l'étendue est supérieure à la taille spécifiée.

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

L'exemple suivant montre comment déclarer une fonction nommée udfCompareNames à laquelle est attribuée une liste de noms (nameList) et un seul nom (myName). La sortie est une liste semblable à la liste d'entrée, qui contient uniquement les entrées de la liste nameList semblables au nom 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;

Exemple 2 : déclaration de fonctions scalaires UDF avec des tables en entrée à l'aide de Java

L'exemple suivant illustre l'utilisation du type d'entrée table as locator. Il présente une instruction create function qui déclare une fonction nommée MyScalarFunc. L'implémentation Java™ de cette fonction UDF est conditionnée dans la classe com.ibm.test.udfs.TableConsumingScalarFunc.

Cette fonction admet deux listes de tuples en entrée et génère une valeur de chaîne qui concatène le contenu des deux listes de tuples en entrée. L'implémentation Java™ de cette fonction UDF est incluse dans la section Implémentation des fonctions définies par l'utilisateur.

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

Exemple 3 : déclaration de fonctions de table UDF à l'aide de Java

L'exemple suivant illustre l'utilisation de la clause return table. Cet exemple présente une instruction create function qui déclare une fonction de table appelée MyScalarFunc. L'implémentation Java™ de la fonction UDF est conditionnée dans la classe com.ibm.test.udfs.TableConsumingTableFunc. Cette fonction UDF admet deux listes de tuples en entrée et génère en sortie une liste de tuples résultant de la fusion des deux listes d'entrée. L'implémentation Java™ de cette fonction UDF est incluse dans la section Implémentation des fonctions définies par l'utilisateur.

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

Exemple 4 : déclaration d'une fonction de table UDF implémentée en PMML

L'exemple suivant présente une instruction create function qui déclare une fonction de table nommée IrisDecisionTree en langage PMML. L'implémentation PMML de la fonction UDF est spécifiée dans le fichier IrisTree.xml, illustré dans l'exemple suivant. Le modèle stocké dans le fichier IrisTree.xml est un modèle d'arbre de décision.

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

Documentation de l'instruction create function avec des commentaires

Le commentaire AQL Doc d'une instruction create function contient les informations suivantes :

  • Une description générale de la fonction.
  • La description de @param qui spécifie le nom de chaque paramètre utilisé dans la fonction. Indiquez s'il s'agit d'un paramètre de type scalaire ou d'une table. Si le paramètre est une table, décrivez le schéma de la table, en incluant les noms de colonne et les types dans leur ordre d'apparition dans le schéma de la table attendue en entrée.
  • La description de @return qui spécifie les informations renvoyées par la fonction. Si la fonction renvoie une table, indiquez le schéma de sortie de la table, en incluant les noms de colonne et les types dans leur ordre d'apparition dans le schéma de la table de sortie.
/**
* 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;

Utilisation des fonctions définies par l'utilisateur

Les fonctions définies par l'utilisateur fonctionnent avec des instructions et clauses AQL.

Les fonctions scalaires définies par l'utilisateur fonctionnent avec des instructions et des clauses AQL semblables à des fonctions intégrées. Plus précisément, les fonctions scalaires UDF peuvent être utilisées dans les clauses select, where, having, group by et order by de la même façon que des fonctions scalaires intégrées, telles que GetBegin et LeftContext. Les fonctions scalaires définies par l'utilisateur qui renvoient un type booléen (Boolean) peuvent être utilisées comme prédicats dans les clauses where et having.

Les fonctions de table définies par l'utilisateur (fonctions de table UDF) peuvent être utilisées dans une clause from d'une instruction select ou extract.

Exemples

Exemple 1 : utilisation d'une fonction scalaire UDF implémentée en Java avec des valeurs scalaires en entrée

Cet exemple montre comment utiliser les fonctions udfCombineSpans et udfSpanGreaterThan déclarées à la section Déclaration des fonctions définies par l'utilisateur.

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

Exemple 2 : utilisation de fonctions scalaires UDF implémentées en Java avec des tables en entrée

L'exemple suivant montre comment utiliser une fonction scalaire avec des tables en entrée. Il illustre l'utilisation de la fonction de table UDF nommée MyScalarFunc, dont l'implémentation Java™ est incluse dans la section Implémentation des fonctions définies par l'utilisateur. Ces tables ont les mêmes types de colonne mais des noms de colonne différents.

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

Exemple 3 : utilisation de fonctions de table UDF implémentées en Java

Cet exemple illustre l'utilisation de la fonction de table UDF nommée MyTableFunc, dont l'implémentation Java™ est incluse dans la section Implémentation des fonctions définies par l'utilisateur.

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

Comme dans l'exemple 2, cet exemple définit deux vues : FirstInputView avec le schéma (match Span) et SecondInputView avec le schéma (spanCol Span, textCol Text). La dernière vue de cet exemple, TabFuncOutput, appelle la fonction de table nommée MyTableFunc dans la clause from, avec les deux vues d'entrée. Comme indiqué dans l'exemple 2, une vue est compatible avec un argument de fonction de type pointeur de table (table locator), tant que le nombre de colonnes et les types de colonne dans le schéma de la vue d'entrée et du pointeur de table correspondent. En revanche, il n'est pas nécessaire que les noms de colonne correspondent.

Et enfin, la clause select supprime la colonne outStr dans la table de sortie de MyTableFunc, en conservant uniquement les deux premières colonnes outSpan1 et outSpan2.

Exemple 4 : utilisation d'une fonction de table UDF implémentée en PMML

Cet exemple illustre l'utilisation de la fonction de table UDF nommée IrisDecisionTree déclarée dans l'exemple 4 de la section Déclaration des fonctions définies par l'utilisateur.

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