IBM Cloud Docs
註釋查詢語言參考

註釋查詢語言參考

註釋查詢語言 (AQL) 是用於建立 IBM Watson® Knowledge Studio 進階規則擷取程式的主要語言。

  • 資料模型:AQL 的資料模型類似於 SQL 資料庫 (例如 DB2®) 使用的標準關聯式模型。 AQL 中的所有資料都儲存在值組、一或多個直欄的資料記錄或欄位中。 值組的集合會形成視圖。 視圖中的所有值組都必須有相同的綱目,綱目是所有值組之間的欄位名稱及類型。
  • 執行模型:運行環境元件具有一次一份文件的執行模型。 運行環境元件會收到一個文件集合,並對每份文件執行擷取程式,以從該文件擷取資訊。
  • AQL 陳述式:藉由使用 AQL 陳述式,您可以先建立再使用模組、視圖、表格、字典及函數。
  • 內建函數:AQL 有一個內建函數的集合,以便用於擷取規則。
  • create function 陳述式:若要對 AQL 不支援的擷取值執行作業,您可以定義自訂函數,以便用於稱為使用者定義函數 (UDF) 的擷取規則。

註釋查詢語言 (AQL) 語法

與許多程式設計語言一樣,AQL 也根據一般的語法和文法。

程式設計語言的詞彙結構是一組基本規則,用於定義該語言的記號或基本組成部分,例如其保留字、ID、常數等。

AQL 的語法類似於 SQL 的語法,但有數個重要差異:

  • AQL 區分大小寫。

  • AQL 目前不支援進階 SQL 特性,例如相關子查詢和遞迴查詢。

  • AQL 具有新的陳述式類型 extract,SQL 中不存在這種陳述式類型。

  • AQL 不容許關鍵字(保留字)作為視圖名稱、直欄名稱或函數名稱。

  • AQL 容許正規表示式用 Perl 語法表示,但這並不是必要的。 正規表示式以斜線 (/) 為開頭並以斜線 (/) 為結尾,如 Perl 語法中所示。 AQL 也容許正規表示式以單引號 (') 開頭,以單引號 (') 結尾。 例如,您可以使用 /regex/ 而非 'regex' 作為 AQL 中的正規表示式。

  • ID:ID 用來定義 AQL 物件的名稱,包括模組、視圖、表格、字典、函數、屬性及函數參數等的名稱。

  • 保留字:保留字是在 AQL 結構上下文內具有固定意義的字,且不能重新定義。 關鍵字是在語言語法內有特殊意義的保留字。

  • 常數:常數是固定值,可以是下列其中一種資料類型:String、Integer、Float 或 Boolean。

  • 註解:利用註解,使用基本說明來擴增 AQL 程式碼,以協助其他人瞭解程式碼並產生自我說明的已編譯模組。

  • 表示式:AQL 表示式是一個以上純量值和函數的組合,它會評估為單一純量值。

ID

ID 用來定義 AQL 物件的名稱,包括模組、視圖、表格、字典、函數、屬性及函數參數等的名稱。

有兩種類型的區分大小寫 AQL ID:

  • 簡單 ID

    簡式 ID 必須以小寫 (a-z) 或大寫 (A-Z) 字母或底線字元 (_) 開頭。 後續字元可以是小寫或大寫字母、底線字元或數字 (0-9)。 簡式 ID 必須不同於任何 AQL 關鍵字。

  • 加雙引號的 ID

    雙引號 ID 以雙引號字元 (") 開頭和結尾。 您可以使用開頭和結尾雙引號字元之間的任何字元。 加雙引號的 ID 不能包含句點 (.) 字元。 如果名稱中出現雙引號字元,必須在其前方加上反斜線字元 (\) 來跳出該字元,例如 \”

保留字

保留字是在 AQL 結構上下文內具有固定意義的字,且不能重新定義。 關鍵字是在語言語法內有特殊意義的保留字。

下列由 AQL 保留的關鍵字不能用來作為 ID,因為這些關鍵字在語言中各自都有明確定義的用途:

  • 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

下列保留字是內建純量類型的名稱:

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

下列其他保留名稱不能用來作為 ID:

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

常數

常數是固定值,可以是下列其中一種資料類型:StringIntegerFloatBoolean

常數在 selectextract 子句的 select 清單中使用,或者在內建或 UDF 函數和述詞中用來作為引數。 AQL 支援下列類型的常數:

  • 字串常數

    用單引號 (') 括起的字串,例如 'a string'。

  • 整數常數

    未用引號括起的 32 位元、帶正負號的整數值,例如 10 或 -1。

  • 浮點常數

    未用引號括起的單精度 32 位元浮點值,例如 3.14 或 -1.2。

  • 布林常數

    未用引號括起的值 true 或 false。

  • 空值常數

    未用引號括起的值 null。

註解

請使用註解來擴增 AQL 程式碼的基本說明,以協助其他人瞭解程式碼並產生自我說明的編譯模組。

註解容許 AQL 開發人員使用基本說明來擴增 AQL 程式碼,以便易於理解 AQL 原始碼,並產生自我說明的已編譯 AQL 模組。 AQL 中支援三種類型的註解:

  • 單行註解

    單行註解以雙連字號 (--) 為開頭。

  • 多行註解

    多行註解以斜線及星號 (/*) 開頭,以星號及斜線 (*) 結尾。 多行註解不能為巢狀。 例如,不容許使用下列巢狀多行註解:

    /*
    A comment with a /*nested comment*/
    */
    
  • AQL Doc 註解

    利用 AQL Doc 註解,可以使用淺顯易懂的語言說明模組或 AQL 物件,並且可說明不同的層面,以便其他使用者能夠理解上下文。 與會被 AQL 編譯器忽略的單行註解和多行註解不同,AQL Doc 註解會在已編譯模組(.tam 檔案)的 meta 資料中進行序列化,並且可供外部使用。

    AQL Doc 中針對陳述式和模組的所有註解都具有下列格式:

    • 註解為純文字(不支援 HTML 標籤)。

    • 註解以正斜線開頭,後面接著兩個星號 (/**) ,並以星號正斜線 (*/) 結尾。 選擇性地,每一行都可以星號 (*) 開頭。

    • 可以在星號前面使用任意數目的空格。

    • 可以在每行開頭或在選用性的星號後面使用以 @ 符號為字首的特殊標籤。

    • 不能巢狀放置 AQL Doc 註解。 AQL Doc 系統內支援兩個層次的精度。 在說明每個構件之陳述式和語法的主題中,詳細說明了用來記錄每個構件的格式。

    • 模組層次註解

      模組層次註解包含在名為 module.info 的特殊檔案中,該檔案直接位於模組資料夾下。 這些註解應該說明模組的語意以及模組的 Document 視圖綱目。

    • 陳述式層次註解

      陳述式層次註解包含在來源 AQL 檔案中,緊接在用於建立 AQL 物件的陳述式之前。 在一個陳述式的 AQL Doc 註解與該陳述式本身之間,容許使用單行註解和多行註解。

      可以使用 AQL Doc 註解來記錄下列最上層 AQL 陳述式:

      • create external view 陳述式
      • create external table 陳述式
      • create external dictionary 陳述式
      • create 函數
      • detag 陳述式
      • select... into 陳述式 AQL Doc 註解在模組的編譯表示法中進行序列化。

表示式

AQL 表示式是一個以上純量值和函數的組合,它會評估為單一純量值。

表示式可以是以下四種類型之一:

  • 常數
  • 直欄參照
  • 純量函數呼叫
  • 聚集函數呼叫

常數

表示式可以是類型為 IntegerFloatString 的常數,如下列範例所示:

select 'positive' as polarity

該表示式是字串常數 positive

直欄參照

表示式可以是直欄參照,如下列範例所示:

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

此視圖識別可以解釋為個人全名的文字(例如 "Samuel Davis" 和 "Vicky Rosenberg")。 表示式 F.nameL.name 是直欄參照表示式,分別用於傳回視圖 FL 的 name 直欄。 from 陳述式將視圖 FL 定義為視圖 FirstNameLastName(用於定義有效的名字和姓氏,在本範例中未顯示)的本端名稱。

純量函數呼叫

表示式可以由一個以上純量函數呼叫組成,每個純量函數呼叫都可以包含引數,引數也可以是類型為常數、直欄參照或純量函數呼叫的表示式。 純量函數呼叫可以是其中一個內建純量函數,也可以是使用者定義純量函數。 請考量下列範例:

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

此視圖藉由將具有相同姓氏的人員分組在一起並顯示所有姓名(其中姓氏使用小寫字元)來識別可能的家庭成員(例如,lastname keaton, firstnames (Elyse, Alex, Diane))。 GetText 函數呼叫的輸出用來作為 ToLowerCase 函數呼叫的引數,用於以小寫形式顯示姓名。 此範例中的scalar函數呼叫表示式為:ToLowerCase(GetText(P.lastname)ToLowerCase(GetText(P.firstname))GetText(P.lastname)

聚集函數呼叫

表示式可以是聚集函數呼叫。 此表示式類型可以將類型為直欄參照或類型為純量函數呼叫的另一個表示式當作引數。 下列範例顯示具有表示式類型直欄參照的聚集函數呼叫:

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

表示式只是 Count(Person.lastname),並計算文件中的 Person.lastname 註釋數目。 以上範例中,具有表示式類型純量函數呼叫的聚集函數呼叫範例存在為 List(GetText(P.firstname)),其中 List 聚集函數將 GetText 純量函數用來作為引數,以產生名字的清單。 聚集函數呼叫表示式僅容許在 select 陳述式的 select 清單中用來作為表示式。 select 陳述式的 extract 清單中,不容許使用聚集函數呼叫表示式,也不容許將聚集函數呼叫表示式作為純量或聚集函數呼叫的引數。

資料模型

AQL 的資料模型類似於 SQL 資料庫 (例如 DB2®) 使用的標準關聯式模型。 AQL 中的所有資料都儲存在值組、一或多個直欄的資料記錄或欄位中。 值組的集合會形成視圖。 視圖中的所有值組都必須有相同的綱目,綱目是所有值組之間的欄位名稱及類型。

輸入文件的內容會呈現為稱為 Document 的特殊視圖。

值組的欄位必須屬於 AQL 的其中一個內建資料類型:

  • 布林

    具有 true 或 false 值的資料類型。

  • float

    單精度浮點數。

  • 整數

    32 位元,帶正負號的整數。

  • ScalarList

    相同純量類型(Integer、Float、Text 或 Span)之值的集合。 資料類型為 ScalarList 的值,可以因為 AQL 內建聚集函數 List() 或 UDF 的結果而取得。

  • Span

    Span 是 Text 物件的相鄰地區,以其在 Text 物件中的開始和結束偏移量來識別。 假設輸入文字為:

    Amelia Earhart is a pilot.
    

    Span [0-6] 的文字為 Amelia

    可以將此 Span 視覺化為:

    0A1m2e3l4i5a6
    

    與此類似,Span [20-25] 的文字為 pilot

    Span [x-x] 代表一個字元結尾與下一個字元開頭之間的文字段。 在前一個範例中, [ 0-0 ] 是字元 A之前的空字串。 同樣地, [ 3-3 ] 的 Span 是 el字元之間的空字串。

    類型為 Span 的值可以因為 extract 陳述式、內建純量函數或 UDF 的結果而取得。

  • Text

    用於代表字元序列的 AQL 資料類型。 Text 物件包含 Unicode 字串,這稱為其字串值。 一個字串是連結另一個 Text 物件的不相連子字串所形成時,則該字串也包含對原始 Text 物件的參照,以及相關的偏移量對映資訊。 如果這兩個 Text 物件的所有組成部分都彼此對應相等,則會將這兩個物件視為彼此相等。

  • 比較類型為 Span 和 Text 的值 優先順序因子會影響類型 Span 與類型 Text 的值之間的比較。

比較類型為 Span 和 Text 的值

優先順序因子會影響類型 Span 與類型 Text 的值之間的比較。

類型 Span 和類型 Text 的值可以下列方式彼此進行比較:

  • 空值 Span 值的排序一律低於其他值。
  • Text 值的排序一律高於 Span 值。
  • 類型為 Text 的值首先依其字串值的詞法順序排序,然後依其原始 Text 順序和偏移量對映資訊(如果適用)進行排序。
  • 類型為 Span 的值首先依其基礎 Text 物件排序,接著依其開始偏移量排序,再依其結束偏移量排序。 開始偏移量較小的 Span 排序較低。 如果兩個 Span 的開始偏移量相同,則結束偏移量較小的 Span 排序較低。

執行模型

運行環境元件具有一次一份文件的執行模型。 運行環境元件會收到一個文件集合,並對每份文件執行擷取程式,以從該文件擷取資訊。

擷取程式由一個以上 AQL 模組組成,用於建立視圖集合,其中每個視圖定義一個關係。 其中一些視圖指定為輸出視圖,其他視圖則為非輸出視圖。 非輸出視圖可以包含匯入到模組或從模組匯出的某些視圖。 請務必注意,輸出視圖和匯出的視圖是正交關係。 例如,匯出的視圖不適合作為輸出視圖。 除了這些視圖外,獨特的 Document 視圖還代表此擷取程式所註釋的輸入文件。

Document 檢視

在 AQL 模組層次,Document 視圖是一個特殊視圖,用於代表正由該模組註釋的現行文件。 將兩個以上的模組結合在一起形成擷取程式時,所有模組之 Document 綱目的無重複聯集,就是所需的 Document 視圖。 使用 require document with columns 陳述式可指定 Document 視圖的綱目。 如果此陳述式不存在於模組中,會假設 Document 視圖的預設綱目為 (text Text, label Text):

  • text

    現行文件的文字內容。

  • 標籤

    正在註釋之現行文件的標籤。

關鍵字 Document 保留作為 Document 視圖的 ID,此視圖會在執行期間自動移入。 因此,您無法使用該名稱來定義其他視圖或表格。 但是,可以使用 Document 這個字作為屬性名稱和別名的 ID。

AQL 陳述式

藉由使用 AQL 陳述式,您可以建立然後使用模組、視圖、表格、字典及函數。

AQL 中支援下列陳述式:

  • 用於建立模組和宣告模組之間互動的陳述式

    module 陳述式

    export 陳述式

    import 陳述式

  • 用於建立 AQL 物件(視圖、字典、表格或函數)的陳述式

    create dictionary 和 create external dictionary 陳述式

    create table 陳述式

    create view 陳述式

    create external view 陳述式

    detag 陳述式

    extract 陳述式

    select 陳述式

    require document with columns 陳述式

    set default dictionary language 陳述式

    create function 陳述式

AQL 陳述式中的語法規格包含方括弧 ([ ])。 這些規格指出在撰寫陳述式時使用對應的語法時,方括弧及其所保留的建構是選用的。 此外,它們還作為位置保留元來定義如何指定建構或引數的其他實例。

module 陳述式

使用 module 陳述式可建立具有自行包含之必要資源的模組。 您可以將這些資源作為 AQL 物件匯出到其他模組,也可以從其他模組將這些資源作為 AQL 物件匯入。

語法

module <module-name\>;

說明

  • <module-name\>

    宣告現行檔案是名稱為 <module-name\>之模組的一部分。 模組名稱必須是簡單 ID。 不容許使用加雙引號的 ID 作為模組名稱。

    模組中的每個 AQL 檔案都必須有恰好一個模組宣告,並且此宣告必須是每個檔案中的第一個陳述式。 此宣告會建立與模組名稱同名的名稱空間。 此模組內的 AQL 檔案中宣告的所有視圖(以及其他物件,例如字典、表格和函數)都位於此單一名稱空間中。 這些可供此名稱空間中的所有 AQL 檔案存取。

    宣告為模組 <module-name\> 一部分的所有檔案都必須位於稱為 <module-name\> 的資料夾內,才能施行此名稱空間。 此模組資料夾中的 AQL 檔案不進行排序。 AQL 編譯器會檢查模組的所有 AQL 檔案,並確定模組中宣告的所有視圖、字典、表格和函數的正確編譯順序。

使用注意事項

  • 如果基礎 AQL 檔案不是模組(模組化 AQL)的一部分,並且以相容模式進行編譯,則不支援此陳述式。
  • 不容許視圖之間存在循環相依關係。
  • AQL 模組不支援子模組。
  • 將忽略最上層模組資料夾之子資料夾中的 AQL 檔案。

範例

範例 1:範例模組

在下列範例中,視圖 TheMentions 屬於名為 sample 的模組。

module sample;

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

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

export 陳述式

AQL 中的 export 陳述式用於從現行模組匯出 AQL 物件,以便可以在其他模組中匯入和使用該物件。

語法

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

說明

  • view|dictionary|table|function

    定義要匯出的物件類型。 物件類型可以是視圖、字典、表格或函數。

  • <object-name\>

    定義要匯出的物件名稱。 <object-name\> 可以是簡式 ID 或雙引號 ID。

使用注意事項

  • 無法匯出任何匯入的 AQL 物件。 藉由建立新視圖,可以產生重新匯出現行模組中之視圖或表格的效果:

    select * from <imported_view_name_or_table_name>;
    
  • 範例中顯示的 export viewoutput view 陳述式相互之間是正交關係。 換句話說,輸出視圖並不會自動成為匯出的視圖,而必須使用 export 陳述式明確匯出。 匯出的視圖並不會自動成為輸出視圖,而必須使用 output view 陳述式明確輸出。 在範例中,export 陳述式試圖匯出視圖 PersonName.FirstName,這是匯入的視圖。 這項嘗試會導致錯誤,意思是開發人員必須將匯入的視圖複製到新視圖中,然後改為匯出該視圖。

範例

範例 1:建立視圖和字典,然後將其匯出以在其他模組中使用

此範例會建立視圖 FirstName 和 NotFirstName。 視圖 FirstName 會收集 FirstNamesDictionary 字典中所表示名字的相關資訊。 另一個視圖會收集排除名字後剩餘的名稱。 需要兩個字典才能易於進行文字擷取。 一個字典包含您要搜尋的所有名字。 第二個字典 LastNamesDictionary 包含要搜尋的姓氏。 FirstNamesDictionary 字典已匯出,以便可以在其他模組中使用該字典。 還匯出了 FirstName 和 NotFirstName 視圖,以便可以在其他模組(例如,範例 2 中的模組 person)中匯入和使用這兩個視圖。

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;

範例 2:匯入要使用的視圖,但因匯出不正確,導致了錯誤

此範例顯示了匯入兩個視圖。 這些視圖已從範例 1 中的模組 personName 匯出。 模組人員現在可以匯入及參照那些視圖。 但是,此模組試圖匯出其所匯入的相同視圖 FirstName,因此導致了錯誤。

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;

導致此程式碼中出現該錯誤的原因是,從一個模組匯入的視圖無法在現行模組中匯出。 此外,除非使用 output view 陳述式定義輸出視圖,否則匯出的視圖並不會自動成為輸出視圖。

import 陳述式

可以使用 import 陳述式在現行模組的環境定義中參照從其他模組匯出的物件。

語法

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

說明

  • view\|dictionary\|table\|function

    識別要匯入的 AQL 物件類型。 物件的類型是必要的。

  • <object-name\>

    <object-name\> 可以是簡式 ID 或雙引號 ID。

  • <module-name\>

    <module-name\> 必須是簡式 ID。

  • <alias\>

    這種形式的 import 陳述式 (也稱為 alias import) 會將 <alias\> 名稱 (不是原始名稱) 下指定的 AQL 物件匯入至現行模組的名稱空間。 可以使用未限定別名,或使用以現行模組名稱(亦即,匯入 AQL 物件的模組)限定的別名,來參照匯入的元素。 不能使用 originalModule.elementName,因為 alias import 陳述式只會以別名匯入元素,而不會以限定的原始名稱來匯入元素。

使用注意事項

  • 不使用別名規格的 import 陳述式會將指定的 AQL 物件匯入到現行模組。 它可讓現行模組中定義的 AQL 陳述式以完整名稱 <original\_module\_name\>.<object-name\>來存取 AQL 物件。

  • 此 import 陳述式僅用於從現行模組以外的模組匯入 AQL 物件。 在模組 AQL 檔案中宣告的物件,會針對該相同模組中的其他任何 AQL 檔案顯示。 import 陳述式會將物件放在現行模組的環境定義中,而不是現行檔案的環境定義中。 因此,模組 A 中 1.aql 匯入的視圖,會針對相同模組中的 2.aql 中顯示,而無需任何其他 import 陳述式。

  • 所有 import 陳述式都必須緊接在模組宣告之後,且必須位於其他所有類型的陳述式之前。 只有明確從任何模組匯出的 AQL 物件才能匯入到另一個模組。 如果未遵守此需求,會導致發生編譯錯誤。

  • import view 陳述式與任何 create view 陳述式或相同模組中(不僅僅是現行檔案中)的其他 import 陳述式之間發生命名衝突時,會產生編譯錯誤。 除了視圖外,此限制也適用於對其他物件執行的 import

  • AQL 編譯器遵循舊版 AQL 中使用的命名慣例:

    • 模組不能包含同名視圖和表格。
    • 容許使用與表格或視圖同名的字典。
    • 容許使用與表格、視圖或字典同名的函數。
  • 模組中一個或多個 AQL 檔案中,不同 import 陳述式對不同 AQL 物件提供相同名稱時,會產生編譯錯誤。

  • 當模組內的 AQL 檔嘗試參照模組的另一個匯出視圖時,若未使用 import view 陳述式,便會產生編譯錯誤。 字典、表格或函數等也是如此。

  • 模組中的兩個 AQL 檔案使用兩個不同的別名(例如,A 和 B)從另一個模組匯入相同視圖 X 時,這兩個別名會視為同義。 此規則也適用於表格、字典及函數。

範例

範例 1:建立視圖,然後將其匯出,並匯入到其他模組中。

此範例會建立兩個視圖:FirstNameNotFirstName。 視圖 FirstName 會收集 FirstNamesDictionary 字典中所表示名字的相關資訊。 另一個視圖會收集排除名字後剩餘的名稱。 需要兩個字典才能易於進行文字擷取。 一個字典包含您要搜尋的所有名字。 另一個字典 LastNamesDictionary 包含要搜尋的姓氏。 匯出了 FirstNameNotFirstName 視圖,以便可以在其他模組(例如,範例 2 和 3 中的模組 person)中匯入和使用這兩個視圖。

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;

範例 2:使用 alias import 匯入視圖 FirstName

此範例會匯入在範例 1 中建立並匯出的其中一個視圖。 然後,會輸出 PersonFirstName 視圖,以便可以檢視其結果。

範例 import 陳述式稱為 alias import。 它將視圖 FirstName(不含模組限定元)匯入到現行模組 person 的名稱空間。 匯入的視圖只能透過別名 PersonFirstName 來存取,而不能透過其他任何形式存取。 例如,無法將匯入的視圖參照為 personName.FirstName,因為此視圖僅透過別名來匯入。

module person;

`import view FirstName from module personName as PersonFirstName;`

output view PersonFirstName;

範例 3:不使用 alias import 匯入視圖 NotFirstname

此範例 import 陳述式會將限定名稱 personName.NotFirstName(而不是該視圖的未限定名稱)匯入到現行模組 person 的名稱空間。 請一律使用限定名稱來參照匯入的視圖。 其他任何參照模式都會被標示為編譯器錯誤。

module person;

`import view NotFirstName from module personName;`


output view personName.NotFirstName;

import module 陳述式

可以使用 import module 陳述式來匯入和重複使用現有的 AQL 模組。

語法

 import module <module-name\>;

說明

  • <module-name\>

    指定要匯入的模組。 <module-name\> 必須是簡式 ID。

使用注意事項

  • 此 import 陳述式僅用於從現行模組以外的其他模組匯入 AQL 物件。

  • 所有 import 陳述式都必須緊接在模組宣告之後,且必須位於其他所有類型的陳述式之前。 只有明確從任何模組匯出的 AQL 物件才能匯入到另一個模組。 如果未遵守此需求,會導致發生編譯錯誤。

  • import view 陳述式與任何 create view 陳述式或相同模組中(不僅僅是現行檔案中)的其他 import 陳述式之間發生命名衝突時,會產生編譯錯誤。 除了視圖外,此限制也適用於對其他 AQL 物件執行的 import

  • 當模組內的 AQL 檔嘗試參照模組的另一個匯出視圖時,若未使用 import view 陳述式,便會產生編譯錯誤。 字典、表格或函數等也是如此。

  • 如果模組中的兩個 AQL 檔案使用兩個不同的別名(例如,A 和 B)從另一個模組匯入相同視圖 X,這兩個別名會視為同義。 此規則也適用於表格、字典及函數。

範例

在此範例中,import 陳述式會匯入兩個已匯出的視圖 personName.FirstNamepersonName.NotFirstName 的限定名稱。 未由模組 personName 匯出的任何視圖都不會在執行 import 陳述式的過程中匯入。

  • 範例 1:FirstName 和 NotFirstName 視圖都匯入

    此範例顯示了從模組 personName 匯出的所有視圖。 在 export 陳述式的範例區段中建立了視圖 FirstNameNotFirstName

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

set default dictionary language 陳述式

set default dictionary language 陳述式容許擷取程式開發人員針對包含模組自訂預設字典比對語言集。

語法

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

說明

  • <language codes\>

    對於在未明確指定 with language as 的情況下宣告的模組,指定用於編譯和比對其字典的語言。 <language codes\> 集必須是一份以逗點區隔的清單,每一個語言碼周圍都沒有空格。 不遵循此需求可能會導致發生編譯錯誤。

    此陳述式會影響下列字典:

    • 在現行模組中使用 create dictionarycreate external dictionary 陳述式(該陳述式不包含 with language as 子句)明確宣告的字典。
    • 來自外部檔案的字典。
    • extract pattern 陳述式的型樣規格中,類型為 'string' 的原子和類型為 <'string' [match parameters]> 的原子,沒有明確的 with language as 規格。 當模組內缺少此陳述式時,執行時期元件會預設為德文、西班牙文、英文、法文、義大利文及未指定語言 x 的語言集。 它定義為一組: [de,es,en,fr,it,x_unspecified]。 在一個模組中,此陳述式只能有一個實例。

使用注意事項

  • 可以更新 set default dictionary language 陳述式,以改善擷取程式涵蓋的語言範圍。 這種新增語言的能力有助於簡化自訂以及現有擷取程式的重複使用。

範例

範例 1:指定要用來比對字典項目的語言

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;

require document with columns 陳述式

藉由使用 require document with columns 陳述式,可以在編譯時定義特殊視圖 Document 的綱目。 此綱目定義指定了需要位於 Document 視圖內每個值組中的必要欄位及其類型的清單。

語法

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

說明

  • <columnName\>

    指定要在綱目中使用的直欄名稱。 <columnName\> 是屬性 ID ,它是簡式 ID 或加雙引號的 ID。

  • <columnType\>

    指定要在 Document 視圖的綱目中使用的直欄類型。 <columnType\> 可以是下列其中一種資料類型: 整數、浮點數、布林或文字。

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

    Document 視圖的綱目指定其他直欄名稱和類型。 它們遵循與 <columnName\><columnType\>相同的規則。

在較早版本的 AQL 中,特殊視圖 Document 的綱目預先定義為包含單一欄位 (text Text) 或兩個欄位 (text text, label Text)。 選擇使用其中哪個綱目會在執行時決定。 藉由使用 require document with columns 陳述式,可以在編譯時置換預設輸入文件綱目。

使用注意事項

  • 對於模組化 AQL 程式碼,任何 require document with columns 陳述式的範圍是定義了該陳述式的模組。
  • 每個 AQL 檔案只容許使用一個 require document with columns 陳述式。 在單一模組或通用模組中,可以有零個、一個,或多個具有 require document with columns 陳述式的 AQL 檔案。 模組中的所有 AQL 檔案會在整個模組層次合併其 require document with columns 陳述式,以形成模組層面的 require document with columns。 此陳述式定義該模組 Document 視圖的綱目。 如果模組或通用模組的 AQL 檔案都不包含 require 陳述式,則模組具有視圖 Document 的預設綱目。 此綱目由兩直欄組成:(text Text, label Text)。 如果模組中至少有一個 AQL 檔案具有一個 Document 陳述式,則不會為特殊視圖 require document with columns 建立預設直欄。
  • 結合多個模組以形成擷取程式時,整個擷取程式的 Document 視圖的綱目由每個模組的 Document 綱目的無重複聯集進行定義。 如果在多個 require document with columns 陳述式中找到的任何直欄的類型需求在各個模組之間存在衝突,那麼會引發異常。 例如,一個模組需要類型為 Y 的直欄 X,而正在載入的另一個模組需要類型為 Z 的直欄 X。
  • 如果提供的輸入文件值組不包含所有必要直欄,則在執行擷取程式時會引發異常狀況。 此外,如果直欄不符合其對應的必要類型,也會引發異常狀況。
  • 模組中存在 require document with columns 陳述式時,所參照的特殊視圖 Document 的每個直欄,必須至少在一個 require document with columns 陳述式中進行宣告。 該陳述式可以在相同模組內的不同 AQL 檔案中找到。 但是,所有此類 require document with columns 陳述式都將在模組層次進行合併,以形成模組層面的 require document with columns 陳述式。

範例

範例 1:具有類似直欄類型的 require document 陳述式

下列範例定義的文件綱目包含相同類型的四個欄位。 此 AQL 範例預期資料集合的每個文件值組都包含如同文件綱目中所定義的四個直欄。

請參閱 JSON 文件格式,以取得如何建立符合綱目之文件的相關詳細資料。

module person;

-- Require document statement with similar field types

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

範例 2:具有不同直欄類型的 require document 陳述式

下列範例定義的文件綱目包含欄位類型不同的直欄。

module sample;

-- Require document statement with varying field types

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

範例 3:合併文件綱目

此範例說明如何合併使用 first.aql、last.aql 和 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;

合併後的綱目為 (firstName Text, lastName Text, socialSecurityNo Integer)。

create view 陳述式

AQL 擷取程式的最上層元件是其視圖。 視圖是用於定義(但不一定運算)一組值組的邏輯陳述式。

語法

create view 陳述式可以採用三種形式之一。 最簡單的形式是定義由單一 selectextract 陳述式的值組所組成的邏輯視圖。 第二種是多重結合的形式,定義包含從數個 selectextract 陳述式的多重集聯集 (multiset union) 而得之值組的視圖。 第三個種形式是定義新視圖,其中包含兩個 selectextract 陳述式的值組之間的集差異。

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

說明

  • <viewname\>

    <viewname\> 可以是簡式 ID 或雙引號 ID。 不能包含句點字元。

  • <select or extract statement\>

    selectextract 陳述式會建立輸出,以便用來計算包含視圖的值組。

使用注意事項

  • 視圖名稱會區分大小寫。 例如,Person、PERSON 和 person 是不同的視圖名稱。
  • 相同 AQL 模組中的兩個視圖不能共用名稱,這會使視圖重複。 但是,同名的兩個視圖可以存在於兩個不同的模組中,因為其完整名稱是唯一的。
  • 依預設,create view 陳述式定義的視圖是一個非輸出視圖,直到將其指定為輸出視圖為止。
  • selectextract 形式的 union allminus 陳述式必須具有相容的輸出綱目。 如果兩個綱目的直欄數相同、直欄名稱的順序相同,並且具有相容的資料類型,則對於 unionminus 作業而言,會將這兩個綱目視為相容:
    • 相同資料類型的欄位相容於 unionminus
    • Span 和 Text 資料類型相容於 unionminus。 對於 Span 與 Text 類型之間的聯集,輸出類型為 Span。 但是,Text 類型的物件不會自動轉換為 Span 類型 - 僅當函數呼叫需要時才會執行自動轉換。
    • 不管基礎純量類型如何,兩個 ScalarLists 都相容於 unionminus

範例

範例 1:使用 select 或 extract 陳述式建立視圖

在以下範例中,視圖 Phone 使用 extract 陳述式來準備其值組。 視圖 PhoneNumber 使用 select 陳述式從視圖 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;

範例 2:使用 Union All 陳述式建立視圖

視圖 AllPhoneNumsPhoneExtension 視圖的值組,準備一個聯集的集合。 聯集的兩個視圖會具有相同的綱目。

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

範例 3:使用 Minus 陳述式建立視圖

下列範例顯示了如何使用 minus 從一組值組中過濾掉不需要的值組。

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

範例 4:minus 的綱目相容性

請務必注意,不同目標文字的文字段類型不同。 請參考下列 AQL 範例,其中使用 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);

輸出是將 'a string' 作為欄位值的一組記錄,而不是預期的空值組清單輸出。

雖然 OneStringTheSameString 視圖的內容看起來相同,但實際文字值具有不同的基礎 AQL 物件。 OneString.match 的類型為 'Span over OneString.match'。 TheSameString.match 的類型為 'Span over TheSameString.match'。 由於欄位類型不同,因此這兩個視圖不相容,無法用於比較。

若要取得所需的空白值組清單輸出,必須比較相同類型的值。 在下列範例中,GetString() 函數將 Span 物件轉換為 String 物件,以將相容的類型傳遞給 minus 作業。

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

使用 AQL Doc 記錄 create view 陳述式

create view 陳述式的 AQL Doc 註解包含下列資訊:

  • 關於視圖的一般說明。
  • 視圖中每個直欄名稱的 @field。

範例

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

output view 陳述式

output view 陳述式用於將視圖定義為輸出視圖。 運行環境元件只會輸出標示為輸出視圖的視圖值組。 AQL 編譯器只會編譯已標示為輸出或匯出的視圖,或者可從標示為輸出或匯出之視圖進行存取的視圖。

語法

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

說明

  • <view-name\>

    要輸出的視圖名稱,如同現行模組的名稱空間中已知的名稱。 <view-name\> 是簡式 ID 或雙引號 ID。 內建視圖 Document 不能作為輸出。

  • [as '<alias\>']*

    定義輸出視圖的 <alias\> 名稱。 未指定選用別名時,視圖使用下列名稱進行輸出:

    • 在模組化 AQL 中,視圖以 <module-name\>.<view-name\> 名稱輸出,其中 <module-name\> 是最初定義視圖所在模組的名稱 (可以不同於輸出視圖所在模組的名稱)。
    • 在 AQL 1.4 或更舊版本中,視圖會以 <view-name\> 名稱輸出 當您自訂不同網域的擷取程式時, output ... as <alias\> 陳述式非常有用。 當您定義輸出視圖時,使用 <alias\> 名稱可確保輸出名稱在自訂作業的不同實作之間相同。

    <alias\> 名稱不能在另一個 selectexport 陳述式中使用。 您必須以單引號括住 <alias\> ,且 <alias\> 名稱可以包含句點。

使用注意事項

  • AQL 擷取程式執行時,會為定義為輸出視圖的每個視圖計算結果值組。 此外,也會計算任何非輸出視圖的值組,但只有計算輸出視圖的結果值組需要這些值組時才會執行此計算。
  • 在模組化 AQL 中,output view 陳述式會使用完整視圖名稱(以其模組名稱限定)來輸出視圖的值組。 請參考下列範例,其中 output view Person; 陳述式會產生 personModule.Person 視圖的輸出:
module personModule;

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

output view Person;

此行為適用於沒有別名的任何視圖輸出,而不管視圖是在定義該視圖的模組中進行輸出,還是在匯入該視圖的模組中進行輸出,甚至是在利用 alias import 匯入該視圖時進行輸出。 例如,在輸出視圖 MyPerson 中,此範例會導致視圖使用其原始限定名稱 personModule.Person 進行輸出,而不是使用其本端別名 MyPerson 進行輸出

module employeeModule;

import view Person from module personModule as MyPerson;

output view MyPerson;
  • 建置擷取程式的程式庫時,如果其中相同類型的實體可以有許多不同的實作(具體取決於輸入文件的應用領域或語言),output alias 陳述式便非常有用。 定義輸出視圖時使用別名的主要優點,是可以在各個輸出視圖之間確保一致的命名法。 如果有多個模組,而每個模組會輸出語意類似的視圖,則在處理這些模組時,使用者的程式邏輯需要一致的命名法。 在模組化 AQL 中,output view 陳述式中使用別名時,視圖的值組會使用指定的別名進行輸出。 例如,下列程式碼將使用別名 PersonAlias 輸出結果,並且該別名未使用模組字首進行限定。
module personModule;

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

output view Person as 'PersonAlias';

範例

下列範例包含兩個模組:personModuleFrench 和 personModuleEnglish。 每個模組輸出一個視圖,分別名為 PersonNameFrench 和 PersonNameEnglish。 假設有類似的模組,每個模組輸出的視圖是人名擷取程式的語意變式。 藉由此視圖針對指定輸入語言的自訂差異,已針對不同語言自訂了這些模組。 最終,無論處理哪些模組,使用者可能都希望程式使用找到輸出視圖名稱為 PersonName 的模組。 這是正常的預期,因為針對語言、領域或其他用途自訂的每個模組預期會產生不同的結果。 基礎語意類似時,這些模組的使用者就無需改變其程式演算法來適應不同的輸出視圖名稱。

在此範例中,由於使用了別名 PersonName,因此使用者無需改變所尋求的視圖名稱。 但是,結果可能因處理的模組而異。 例如,在範例中,產生的相符項是以法文為基礎(範例 1)和以英文為基礎(範例 2)。

範例 1:產生的相符項以法文為基礎

下列範例定義了視圖 PersonNameFrench,並使用與實作無關的別名 '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';

範例 2:產生的相符項以英文為基礎

下列範例定義了視圖 PersonNameEnglish,並使用與實作無關的別名 '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';

範例模組的消費者可以透過別名 'PersonName' 來存取輸出值組。 消費者無需知道從中提取結果的實際模組。

extract 陳述式

extract 陳述式用於直接從文字中擷取基本特徵。

語法

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

說明

  • <select list\>

    以逗點定界的輸出表示式清單。 這些輸出表示式的結果將作為 extract 陳述式的輸出傳回,同時也會傳回評估擷取規格而產生的值組。 <select list\> 的格式與 select 陳述式的 <select list\> 相同。

  • <extraction specification\>

    將擷取規格套用至 <from list\>中所定義視圖的所有值組。 它會根據在 extract 陳述式中為值組直欄指定的對應別名,來重新命名這些值組直欄。 您可以使用下列其中一個擷取規格:

    • 正規表示式
    • 字典
    • 分割
    • 區塊
    • 詞性
    • 序列型樣
  • <from list\>

    以逗點定界的清單,用作要從中選取特性的值組來源。 <from list\> 的格式類似於 select 陳述式的 <from list\> 格式。 不過,如果 extract 陳述式沒有型樣規格,則 <from list\> 可以包含單一項目。

  • [having <having clause\>]

    指定套用至每一個擷取的輸出值組的過濾述詞 (在 <having clause\>中)。 在 <having clause\> 中指定的欄位名稱是指在 <select list\>中指定的任何別名。 這個子句是選用性的。

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

    定義如何處理合併 <policy\>中定義的重疊跨距。 在此規格中, <column\> 必須是輸出欄位的名稱,這是 extract 陳述式的一部分。 這個子句是選用性的。

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

    將每個文件中的輸出值組數限制至指定的最大。 這個子句是選用性的。

使用注意事項

extract 陳述式的語意如下所示:

  • 針對輸入關係的每個值組來評估擷取規格。 對於擷取產生的每一個結果,會產生包含擷取值的輸出值組,以及在 <select list\>中指定的原始值組的任何直欄。
  • 根據指定為 <select list\><extraction specification\>的一部分的別名,重新命名輸出值組的直欄。
  • 將選用性的 having 子句中的任何述詞套用於產生的輸出值組。
  • 根據選用性的 consolidation 子句合併傳遞述詞的值組,並將產生的值組新增到輸出。
  • 如果有選用性的 limit 子句存在,會將輸出限制為只顯示每個文件的指定值組數。

from 陳述式之 extract pattern 子句的語意,與沒有型樣規格之其他形式的 extract 陳述式不同。 如果 <from list\> 中至少一個視圖未包含特定文件上的任何值組,則 extract 陳述式的輸出是空的。 此輸出是空的原因是輸入視圖中值組的所有組合集是空的。

extract pattern 陳述式的特殊案例中,from 子句可作為位置保留元,用於宣告型樣規格中涉及的關係的名稱。 陳述式的語意只由型樣規格驅動。 特別要注意的是,陳述式的輸出可以為非空白,即使是部分輸入視圖為空白。

範例

範例 1:從預先定義視圖擷取電話號碼

此範例 extract 陳述式會針對預先定義視圖 Document 所代表輸入文字中的美國電話號碼,評估正規表示式。 然後,將輸出限制為只顯示每個文件中識別到的前三個電話號碼。 having 子句中的欄位名稱參照 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;

範例 2:擷取首字母大寫單字的區塊

在此範例中,extract 陳述式識別到由兩個到三個首字母大寫單字構成的區塊。 在 AQL 中,區塊是指相鄰文字段的記號,在本例中是二到三個記號。 此範例還使用合併原則從值組的輸出集內排除包含在較大區塊中的區塊。

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

consolidate 子句藉由擷取區塊規格套用於 capswords 欄位。 不同之處在於,consolidation 子句參照的目標欄位是 extract 陳述式的輸出欄位。 select 陳述式的目標欄位是輸入欄位。 此行為類似於 having 子句的行為。

範例 3:巢狀的 extractselect 陳述式作為視圖名稱

extract 陳述式的輸入視圖可以是視圖名稱(如範例 2 所示),也可以是巢狀的 extractselect 陳述式,如以下範例所示:

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;

範例 4:使用 select 清單擷取陳述式

在此範例中,將擷取型樣的相符項,同時從輸入視圖中選取多個屬性。

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;
  • 正規表示式 使用正規表示式擷取規格可識別輸入文字中正規表示式所包含的比對型樣。
  • 字典 使用字典擷取規格可從字串字典中包含的輸入文字擷取字串。
  • 分割 使用分割擷取規格可將大的文字段分割成較小的文字段。
  • 區塊 使用區塊擷取規格可識別輸入文字中連續文字段的區塊。
  • 詞性 使用詞性擷取規格可識別輸入文字中不同詞性的位置。
  • 序列型樣 使用型樣擷取規格可在輸入文件與從輸入文件擷取之其他文字段之間執行型樣比對。

正規表示式

使用正規表示式規格可識別輸入文字中之正規表示式所包含的比對型樣。

語法

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

說明

  • regex[es] /<regex1\>/

    指定要在擷取中使用的正規表示式。 依預設,AQL 對正規表示式使用 Perl 語法,這意味著正規表示式字面值會用兩個正斜線 (//) 字元括起。 正規表示式 ESC 序列優先於其他跳出字元。 AQL 容許使用採用 SQL 字串語法的正規表示式,因此可以將美國電話號碼的正規表示式表示為以下任一範例:

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

    列出要在擷取中使用的更多正規表示式。

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

    指定用於控制正規表示式比對的旗標組合。 這是選用參數。 這些旗標對應於 Java™ 實作中定義的部分旗標。 如果未提供旗標字串,則依預設 AQL 僅使用 DOTALL 旗標。

    若要指定多個旗標,請使用 | 字元來區隔各個旗標。 例如,若要指定多行比對、不區分大小寫的比對以及 Unicode 大小寫摺疊,請使用旗標字串 'MULTILINE|CASE_INSENSITIVE|UNICODE'

  • [<token spec\>]

    指示是否僅根據記號界限比對正規表示式。

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

    記號限制是規格的選用部分。 如果省略了記號限制,AQL 會傳回輸入文字中每個字元位置的最長非重疊相符項。 如果有記號限制存在,則 extract 陳述式將根據每個記號界限傳回最長相符項,但長度不超過指定的記號範圍長度。 每個傳回的相符項必須在記號開頭處開始,並在記號結尾處結束。 如果有多個重疊相符項,extract 陳述式會傳回所有這些相符項。

    記號界限的位置取決於運行環境元件用於對文件進行記號化的記號器。 如果引擎使用標準記號器,則記號會定義為單字字元序列或單一標點符號字元。

    例如,假設有以下字串:

    "The fish are pretty," said the boy.
    

    系統會在以下位置識別記號界限:

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

    套用了正規表示式的視圖名稱和直欄名稱。

  • <grouping spec\>

    確定如何處理正規表示式中的群組擷取。 擷取群組是正規表示式相符項中,由原始表示式中的括弧所識別的地區。 例如,表示式 (fish)(cakes) 具有三個擷取群組:

    • 群組 0 是整個相符項 fishcakes
    • 群組 1 是 fish
    • 群組 2 是 cakes。 在語法的 return 子句中指定群組 ID 時,每個群組 ID 必須對應於語法中指定為 extract regex 子句一部分之每個正規表示式中的有效群組。

    以下是分組規格的格式:

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

    若要僅傳回群組 0 (整個相符項) ,您可以使用較短的替代格式,如範例 1 所示。 此格式相當於 return group 0 as <name><name> 可以是簡式 ID 或雙引號 ID。

使用注意事項

  • 通常,AQL 支援的特性與 Java 5 正規表示式實作的相同,如「類別型樣:java.util.regex」中所述。 運行環境元件包含多個正規表示式引擎實作,包括 Java 的內建實作。 在編譯期間,最佳化程式會檢查每個正規表示式,並選擇可以執行表示式的最快引擎。

  • 替代執行引擎對於特定極端情況可能具有略微不同的語意。 尤其是,AQL 不保證對替代項目的評估順序。

    例如,假設某個 extract 陳述式透過文字 "fisherman" 與正規表示式 /fish|fisherman/ 相符。 該陳述式可能與 "fish" 或 "fisherman" 相符,具體取決於內部使用的正規表示式引擎。

AQL 旗標字串 Java 旗標 說明
CANON_EQ CANON_EQ 標準等值:相同字元的不同 Unicode 編碼視為相等。
CASE_INSENSITIVE CASE_INSENSITIVE 執行不區分大小寫的比對。依預設,不區分大小寫的比對會假設只有 US-ASCII 字集的字元會相符。 可以藉由搭配此旗標指定 UNICODE 旗標,啟用能辨別 UNICODE 且不區分大小寫的比對。
UNICODE UNICODE_CASE 如果指定了不區分大小寫的比對,請使用 Unicode 大小寫摺疊以與 Unicode 標準一致的方式,確定在不區分大小寫的比較中,兩個字元是否相等。 依預設,不區分大小寫的比對會假設只有 US-ASCII 字集的字元會相符。**附註:**如果在不同時使用 CASE_INSENSITIVE 旗標的情況下使用此旗標,其行為並未定義。
DOTALL DOTALL 使點字元 . 符合所有字元,包括換行字元。
LITERAL LITERAL 將表示式視為字面值字元序列,忽略正常的正規表示式 ESC 序列。
MULTILINE MULTILINE 讓字元 ^$ 符合任何行的開頭和結尾,而不是符合整個輸入文字的開頭和結尾。
UNIX_LINES UNIX_LINES 僅將 UNIX™ 換行字元 視為換行字元,忽略換行字元 \r
  • 遵循以下準則可使擷取程式執行速度更快並且更易於維護:
    • 避免使用很長的複雜正規表示式,而使用與 AQL 陳述式結合在一起的較小、較簡單的正規表示式。
    • 在正規表示式中避免不必要地使用先行斷言和後行斷言。 通常,可以藉由將述詞新增至 extract 陳述式的 having 子句來達到相同的效果。
    • 儘可能使用正規表示式擷取規格中的記號限制。

範例

範例 1:使用標準 Unicode 等值來確定相符項

此範例顯示了如何尋找不是名字的首字母大寫單字。 標準 Unicode 字元等值用來確定相符項。 請注意 ‘CANON_EQ’ 旗標的用法,且正規表示式是針對記號執行:

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

範例 2:使用擷取群組

下列範例示範如何在 extract regex 陳述式中使用擷取群組。 程式碼會使用擷取群組來擷取美國電話號碼的欄位:

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;

範例 3:對輸入文字套用多個正規表示式

可以在相同 extract regex 陳述式中使用 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;

範例 4:誤用分組規格

此程式碼範例中的正規表示式未包含 group -1group 3000。 這會導致發生編譯錯誤。

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

字典

使用字典擷取規格可從字串字典中包含的輸入文字擷取字串。

語法

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

說明

  • '<dictionary\>'

    參照使用 create dictionary 陳述式、create external dictionary 陳述式或檔案系統上的字典檔建立的字典。

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

    參照要用於擷取的其他字典。

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

    控制字典比對。 目前支援兩個選項:

    • 確切

      提供完全相符且區分大小寫的比對。

    • IgnoreCase

      提供不區分大小寫的比對。

如果未指定任何旗標,字典會根據建立時指定的任何旗標進行比對。 如果未在建立期間指定任何旗標,則會使用 IgnoreCase 旗標進行比對。

使用注意事項

  • 字典一律會在記號界限進行評估。 具體而言,如果字典項目的第一個記號與文字地區的第一個記號相符合,項目的第二個記號與文字地區的第二個記號相符合,依此類推,那麼該項目與該文字地區相符合。 將忽略兩個連續記號之間的字元。

    例如,假設使用的是以空格為基礎的簡單記號化模型,且該模型適用於英文等語言。 此外,假設輸入文字為 "Let’s go fishing!" 如果字典包含術語 go fish,則在文字 Let's go fishing! 中沒有相符項。 但是,如果字典包含 go fishing 項目(請注意,go 和 fishing 之間有兩個空格),則文字 Let's go fishing! 中有一個相符項。 空格指定 gofishing 是兩個不同的記號。 如果在輸入文字中的兩個記號 gofishing 之間有一個以上的空格字元,則會有一個相符項。

    對於字典項目與輸入文字的每個相符項,extract dictionary 陳述式都會產生輸出值組。

範例

範例 1:從字典檔中擷取術語

搭配使用常見名字和姓氏的字典檔與區分大小寫比對來尋找人名。

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

以下是 last.dict 的範例內容:

#Dictionary for surnames
Anthony
Aparicio
Cate
Lehmann
Radcliff

以下是 first.dict 的範例內容:

#Dictionary for given names
Aaron
Candra
Freeman
Mathew
Matthew
Zoraida

附註:

  • extract dictionary 陳述式中直接參照的字典檔系統無法明確配置為套用一組語言,以便在執行時編譯和套用字典。 如果模組包含 set default dictionary language 陳述式,請改為使用此陳述式來指定語言集。

    因此,建議不要在 extract dictionary 陳述式中直接參照字典檔,未來可能會停止使用此功能。 偏好作法是使用 create dictionary from file 陳述式明確定義字典物件,然後在 extract 陳述式中使用該字典。

  • 編譯器和運行環境元件會試圖在配置的搜尋路徑下尋找 AQL 中參照的字典檔。

範例 2:從行內字典擷取術語

使用行內字典和不區分大小寫的預設比對來尋找連接詞。

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

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

分割

使用分割擷取規格可將大的文字段分割成較小的文字段。

語法

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

說明

分割擷取規格採用兩個引數:

  • 包含較長目標文字段之文字的直欄。
  • 包含分割點的直欄。

分割演算法會對輸入視圖執行兩次。 第一次作業會依目標直欄,將所有輸入值組分組。 第二次作業會經歷每個群組中的值組,並使用分割直欄的每個值分割目標直欄。

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

    指定用於擷取的分割點。

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

    指定如何處理每個結果的左右端點。 這是選用引數。

    • 如果指定了 retain left split point,每個輸出文字段還包含左側的分割點(如果此類分割點存在)。
    • 如果指定了 retain right split point,系統會使每個輸出文字段包含右側的分割點。
    • 分割擷取還接受空值作為分割點。 對於每個此類值,擷取會傳回包含整個輸入文字段的值組。
  • <name\>.<column to split\>

    指定用於擷取的目標直欄。

  • <output name\>

    定義擷取輸出的名稱。

範例

範例 1:分割點和 retain 子句

如果分割點是片語 fish are swimming in the fish pond 中單字 fish 的所有實例,那麼 retain 子句的各種版本會產生下列結果:

  • 省略了 retain 子句

    " are swimming in the " 和 " pond"

  • retain right split point

    " are swimming in the fish" 和 " pond"

  • retain left split point

    "fish are swimming in the " 和 "fish pond"

  • retain both split points

    "fish are swimming in the fish" 和 "fish pond"

範例 2:分割擷取

此範例將文件分割為句子。 它首先使用正規表示式來識別句子界限,然後使用分割擷取規格根據句子界限分割文件文字。

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;

區塊

使用區塊擷取規格可識別輸入文字中連續文字段的區塊。

語法

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

說明

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

    指定可以組成一個區塊的文字段數目。 <min\><max\> 值指定可組成區塊的文字段數目下限和上限。

  • [between 0 and] <max\>

    指定文字段之間容許的間距,超過此間距後,這些文字段即不會再視為相鄰文字段。

  • (tokens| characters)

    指定文字段的間距代表的是記號數還是字元數。

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

    要套用區塊運算子的視圖名稱和直欄名稱。

  • <output name\>

    指定區塊運算子之輸出的名稱。

使用注意事項

  • 如果輸入掃描在輸入文字段中包含多個重疊區塊,則區塊擷取陳述式會傳回所有可能的區塊。 使用合併可過濾掉冗餘區塊。
  • 使用區塊擷取規格的 extract 陳述式會產生多個區塊,其中每個區塊由多個輸入值組中某個特定欄位的值聚集組成。 因此,其 select 清單不能包含其輸入視圖中的欄位。

範例

範例 1:擷取某個字元範圍內的單字區塊

在下列程式碼中,視圖 TwoToThreeCapitalizedWords 識別了包含彼此相距 100 個字元之內的兩個到三個首字母大寫單字的區塊。

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;

範例 2:擷取某個記號範圍內的單字區塊

下列程式碼識別了恰好包含彼此相距五個記號之內的兩個首字母大寫單字的區塊。

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

詞性

使用詞性擷取規格可識別輸入文字中不同詞性的位置。

語法

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>

說明

  • '<part of speech spec\>'

    識別要從輸入文字中擷取的詞性。 '<part of speech spec\>' 是下列其中一個字串:

    • 包含由多語言記號器產生之詞性標籤的逗點定界清單
    • 內部詞性名稱和旗標的組合,如對照表所定義
  • [and '<part of speech spec\>']*

    識別用於擷取的其他詞性標籤。

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

    指定要在擷取中使用的語言。 <language code\> 是兩個字母的小寫語言碼,例如 'en' 或 'ja'。 如果省略此引數,會假設詞性擷取的語言為英文。

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

    指定 AQL 表格的名稱,該表格將原始詞性標籤(如 "NOUN")對映到高階詞性和旗標的組合。 雖然選用對照表可以具有可變的名稱,但是詞性對照表必須具有以下直欄名稱:

    • tag

      保留多語言記號器詞性標籤的直欄。

    • basetag

      保留對應內部標籤的直欄。

    • flagstr

      保留與所指出詞性相關聯之旗標清單直欄,清單會以逗點定界。

    對照表必須在使用該對照表的 extract create table 陳述式所在的模組中使用 part_of_speech 陳述式進行定義。 映射表格不能是匯入的表格,也不能是外部表格。

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

    指定要從中擷取詞性資訊之輸入視圖的直欄。

  • <output column\>

    指定具有所指出詞性之記號文字段將傳送到的直欄名稱。

  • <input view\>

    指定要從中擷取詞性資訊的輸入視圖。

使用注意事項

  • 僅當使用多語言記號器時,詞性擷取才有效。 如果系統使用標準記號器,則 part_of_speech 擷取會產生錯誤。

語言的詞性標籤

對於所有支援的語言,多語言記號器使用下表列出的詞性標籤。

標籤 說明
ADJ 形容詞
ADP 介系詞
ADV 副詞
AUX 助動詞
CCONJ 對等連接詞
DET 限定詞
INTJ 感嘆詞
NOUN 名詞
NUM 數字
PART 質詞(又稱為介副詞)
PRON 代名詞
PROPN 專有名詞
PUNCT 標點符號
SCONJ 從屬連接詞
SYM 符號
VERB 動詞
X other

範例

範例 1:在 extract 陳述式中直接使用詞性標籤

視圖 EnglishNoun 會擷取英文名詞(單數或不可數)或專有名詞(單數)。

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

序列型樣

使用型樣擷取規格可在輸入文件與從輸入文件擷取之其他文字段之間執行型樣比對。

語法

序列型樣的一般語法是首先指定要在文字中比對的型樣,然後指定要由擷取程式傳回的內容。 序列型樣的最後一部分指定作為型樣輸入的內容;這可能是先前已定義視圖中的直欄,也可能是整個文件文字。

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

說明

  • <pattern specification\>

    <pattern specification\> 由多個原子組成。 個別原子可以是已定義視圖中的直欄、固定字串或正規表示式。 可以將原子指定為選用和重複,並指定原子之間的記號間隙。

    型樣規格是包含 extract 子句的較大 AQL 陳述式的一部分。

    以下是一個簡單的範例,說明如何建立視圖來包含先前定義的視圖中的三個相鄰相符項。 在此範例中,將傳回整個組合,即 group 0 參照的內容:

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

    如果原子無需彼此完全相鄰,那麼可以使用原子之間的記號間隙來容許更多相符項。 此範例尋找在相距 0 到 2 個記號之內的位置後跟電話號碼的人員提及項目。 請注意 <Token>{0,2} 建構,指出 person 和 phone 註釋之間容許有 0 到 2 個記號的間隙。

    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;
    

    記號間隙建構限制為在序列表示式中執行。 此外,序列中的每個記號間隙的前後必須為「非記號間隙」表示式。 因此,extract pattern 陳述式會產生以下異常:

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

    使用 (min,max) 語法可指示每個原子重複的次數。 您也可以使用? 語法,指出 Atom 或重複 Atom 是選用的。 原子及其關於重複性和選用性的指示結合在一起以建立序列。

    以下是顯示如何重複元素的更複雜範例。 藉由識別一個到三個首字母大寫單字的出現項目(後面接著 "Hotel" 或 "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;
    

    您也可以使用 | 運算子來指出原子之間的選擇,例如 extract pattern <A.match>| <B.match> <C.match> as match from Apple A, Bacon B, Chocolate C;。 此型樣可以解釋為「與任一 A.match 相符合,或者與 B.match 後跟 C.match 的序列相符合」。 您可以在範例 1 中查看使用 | 運算子的完整範例。

    建立型樣之後,每一個符合 <pattern specification> 的項目都會根據型樣規格的 return 子句,以及 extract 陳述式開頭的選用 <select list> 來建構輸出結果。 結果會根據 having 陳述式的 consolidatelimitextract 子句進行過濾及合併。 例如,如果型樣規格有多個重疊相符項,則會傳回所有可能的相符項,並且您可以使用 consolidation 子句來過濾掉冗餘輸出。

    請參考先前的範例,但現在的目標是移除包含單字 "Sheraton" 的相符項,並藉由移除包含在更大相符項中之相符項來合併產生的相符項。 例如,我們不希望在相同文字段內找到 "Best Garden Hotel" 和 "Garden Hotel" 。

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

既然您已熟悉語法和一些範例,下圖概述了型樣規格的完整語法。 您開始建置型樣時,請參閱此完整語法,以瞭解如何組織要建置之型樣的結構。

如果您熟悉以 POSIX 字元為基礎的正規表示式,則會發現語法類似。 在本例中,語法容許元素之間使用空格,此外還定義了為了滿足 AQL 用途可以使用的元素。請注意,在本例中,術語 Alternation 表示選項。 在元素之間使用垂直線指示存在選項,選項可以使用 ( ) 進行分組。

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 )

具體而言,原子可以具有六種格式:

  • <view_name.column_name\>

    指定在 extract pattern 陳述式的 from 清單中指定的其中一個視圖、表格或表格函數參照中的直欄。

  • 'string'

    使用 AQL 預設字典比對語意來指定與指定字串的相符項。

  • <'string' [match parameters]\>

    使用 [match parameters] 指定的字典比對語意來指定與指定字串的相符項。 [match parameters] 的格式為 case (exact | insensitive)。 此格式指定用於確定字串相符項的大小寫摺疊的類型。 若要指定區分大小寫的完全相符項,請選取 exact。 若要指定相符項不區分大小寫,請選取預設值 insensitive。

  • /regex/

    指定以字元為主的正規表示式相符項,讓比對限制在文件文字中的單一記號。 此外,語法容許在序列表示式中指定特殊記號間隙建構,以指示 minmax 個記號內的相符項。

  • <token\>

    任何記號的相符項。

  • [return clause]

    根據 return 子句為型樣表示式的每個相符項產生擷取值。 return 子句的語意與 return 陳述式中 extract regex 子句的語意相同。

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

    對於原子(例如,字串和正規表示式原子),with inline_match 子句會確定系統用於字串或正規表示式擷取的文字物件。 例如,如果子句為 with inline_match on Email.subject,那麼型樣規格中行內定義的所有字典和正規表示式都將套用於 Email 視圖的 subject 欄位。 如果不存在 with inline_match,那麼依預設會對整個 Document.text 執行字串和正規表示式擷取。 在這種情況下,viewname 必須是在現行模組中定義或從其他模組匯入的視圖或表格的名稱。with inline_match 子句中不容許參照表格函數。

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

    對於要用於評估字串的語言,指定以逗點定界的雙字母語言碼清單,例如 en(英文)或 zh(中文)。 對於其語言碼未包含在此字串中的文件,沒有任何相符項。 如果省略了 language 參數,則評估語言預設為下列其中一個語言集:

    • 透過包含模組中 set default language 陳述式指定的語言集(如果已宣告)。
    • 包含德文 (de)、西班牙文 (es)、英文 (en)、法文 (fr)、義大利文 (it) 和未指定語言 (x_unspecified) 的語言集。

使用注意事項

  • extract pattern 陳述式的語意受型樣規格的影響。 每個相符項根據型樣規格的 return 子句以及 extract 陳述式頂端的 select 清單來建構輸出結果。 結果會根據 extract 陳述式的 havingconsolidatelimit 子句進行過濾及合併。 如果型樣規格有多個重疊相符項,則型樣擷取會輸出所有可能的相符項。 使用合併可過濾掉冗餘輸出。

  • from 陳述式之 extract pattern 子句的語意,與沒有型樣規格之其他形式的 extract 陳述式不同。 extract 陳述式的一般語意需要在 <from list\>中定義的每一個視圖組合上評估擷取規格。 如果 <from list\> 中至少一個視圖未包含特定文件的任何結果,則 extract 陳述式的輸出是空的,因為輸入視圖中所有結果組合的集合是空的。 在 extract pattern 陳述式的特殊案例中,from 子句可作為位置保留元,用於宣告型樣規格中涉及的關係的名稱。 陳述式的語意只由型樣規格驅動。 特別要注意的是,陳述式的輸出可以為非空白,即使是部分輸入視圖為空白。

  • 使用序列型樣擷取的 extract 陳述式可以結轉 from 清單中任何視圖的直欄,但唯有視圖名稱未顯示在型樣規格的重複元素中時,才可執行此作業。 例如,CapsWordOneToThree 陳述式會導致發生編譯錯誤。 發生此錯誤的原因是 extract 陳述式頂端的歸入直欄 CW.type 屬於型樣規格的重複元素 <CW.word>{1,3} 中的視圖名稱 CW

    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;
    

    對於從型樣規格的替代項目或選用元素中顯示的視圖名稱帶入的直欄,當文字中不存在對應的替代項目或選用元素時,輸出直欄的值為 null。 說明此點的範例位於範例 1 的 Person 視圖中。

  • 在重複元素下出現的群組,不能是陳述式的 return 子句輸出。 例如,下列陳述式會導致異常:

    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;
    

範例

範例 1:具有擷取群組的序列型樣

此範例的目標是藉由識別名字、後接中間名縮寫(選用),再接姓氏的出現項目來尋找人名,以及尋找整個相符項(選擇性地在前面加上常用稱呼)。 此外,擷取程式會將整個相符項作為參照傳回、將第一群組作為稱呼傳回、將第二群組作為姓名傳回,並帶入個別輸入視圖中的名字、中間名縮寫和姓氏的值。

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;

由於子型樣表示式 ('Mr.'|'Ms.'|'Miss')? 是選用的,因此當文字中沒有稱呼時,稱呼輸出直欄的值是 null 。 同樣地,由於型樣子表示式 <M.initial>? 是選用的,因此當中間起始值不存在時,輸出直欄中間值是 null

範例 2:具有字串相符項和比對參數的序列型樣

此範例的目標是藉由檢查文件的標題註釋,來尋找已知專案會議記錄的出現項目。 請注意,with inline_match 子句指定根據視圖 Title 的比對欄位來執行字串比對,而不是對整個文件文字執行字串比對。

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;

範例 3:即使輸入視圖是空的,也會傳回非空結果的序列型樣

即使輸入視圖 LastName 是空的,下列陳述式也會產生結果。 型樣規格 <L.name\>? 的第二部分包含選用元素。 型樣規格的語意設計是要輸出由 FirstName.name 文字段或 FirstName.name 文字段(其後緊跟 LastName.name 文字段)組成的所有文字段。 因此,對於視圖 LastName 空白的文件,該陳述式的結果會包含由從該文件中識別之單一 FirstName.name 文字段組成的所有文字段。

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;

select 陳述式

AQL 中的 select 陳述式提供了強大的機制來使用各種規格建構和結合值組集。

語法

select 陳述式在結構方面類似於 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>`];

說明

  • <select list\>

    以逗點定界的輸出表示式清單。

  • <from list\>

    以逗點定界的清單,用作要選取之值組的來源。

  • [where <where clause\>]

    針對從 from 子句的關係中所有值組的卡氏乘積產生的每個值組,定義要對其套用的述詞。 這個子句是選用性的。

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

    定義用於管理重疊文字段的合併原則。 這個子句是選用性的。

  • [group by<group by list\>]

    依照指定欄位的共同值,對從相同文件產生的值組進行分組。 這個子句是選用性的。

  • [order by<order by list\>]

    select 陳述式從每個文件產生的輸出值組排序。 排序是根據排序方式清單(以逗點定界的表示式清單)的值。 這個子句是選用性的。

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

    將每個文件的輸出值組數目限制為指定的最大值。 這個子句是選用性的。

使用注意事項

select 陳述式的語意如下所示:

  • 藉由接受 from 清單中之關係的卡氏乘積來確定輸入資料(以值組形式)。
  • 對於產生的每個輸入值組,藉由在(選用)where 子句中套用述詞,對其進行過濾。
  • 如果有選用性的 group by 子句,將依分組依據清單中指定的值對從相同文件產生的值組進行分組,並運算 select 清單中 aggregate 函數的結果。
  • 根據(選用)consolidation 子句中定義的原則,合併任何重疊值組。 如果存在選用性的 order by 子句,將依排序依據清單的值對這些值組排序。
  • 運算每個值組上 select 清單中的所有表示式,並對 as 子句指定的直欄重新命名。
  • 如果存在選用性的 limit 子句,那麼會將輸出值組數限制至每個文件的指定值組數。

範例

以下是如何使用 select 陳述式來擷取與型樣相符合之電話號碼的範例。 假設已經定義了 PhoneNumbers 視圖,該視圖會擷取型樣為 XXX-XXX-XXXX 的美國電話號碼。 此 select 陳述式會針對輸入文字中的型樣 444-888-XXXX 評估正規表示式。 該視圖具有輸出直欄 documentTextphoneNumber。 此外,輸出限制為只顯示每個文件中識別到此電話號碼型樣的第一個出現項目。

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

另一個範例是如何使用 select 陳述式來尋找人員及其對應電話號碼的約略對映。 假設已經定義了視圖 Person,並且該視圖具有直欄 person 和視圖 PhoneNumbers。 此 select 陳述式會評估 where 子句,以尋找包含人員提及項目並在相距 1 到 3 個單字或記號之內的位置後面接著電話號碼的文字段。 此陳述式的輸入由 from 清單中 PersonPhoneNumbers 視圖的連接代表。

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

personPhoneSpan 直欄將包含用於提供近似人員-電話對映的符合文字段。

personPhoneSpan
John : 433-999-1000
Martha Mob 433-999-1001
  • select 清單 AQL selectextract 陳述式中的 select 清單包含以逗點定界的輸出表示式清單。
  • from 清單 AQL 中 selectextract 陳述式的第二個部分是 from 清單。 from 清單是以逗點區隔的清單,它是要選取或擷取之值組的來源。
  • where 子句 選用性的 where 子句定義要在每個從卡氏乘積產生之值組上套用的述詞,其中的卡氏乘積取自於 from 子句之關係中的所有值組。
  • consolidate on 子句 選用性的 consolidate on 子句會指定 selectextract 陳述式輸出的值組之間,重疊文字段的解析方式。 具有非重疊文字段的值組,在使用這個子句時不受影響。
  • group by 子句 group by 陳述式的選用性 select 子句會指示運行環境元件,依照指定欄位的共同值,而對從相同文件產生的值組進行分組。
  • order by 子句 選用性的 order by 子句會指示運行環境元件,將 select 陳述式從每份文件根據 order by 清單值而產生的輸出值組排序,其中 ordery by 清單是一份以逗點定界的表示式集
  • limit 子句 選用性的 limit 子句會指定 select 陳述式針對文件產生輸出值組數的限制。
  • select... into 陳述式 select ... into 陳述式適用於在單一陳述式中定義視圖並指定它是輸出視圖。

select 清單

AQL selectextract 陳述式中的 select 清單包含以逗點定界的輸出表示式清單。

語法

每個 select 表示式都必須為下列其中一種格式:

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>

說明

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

    • <viewname\>

      指定要從中選取直欄的視圖。

    • <colname\>

      指定該視圖中的直欄。

    • <alias\>

      指定表示所選欄位已知的名稱。 此欄位是選用欄位, 可選取作為每個輸出值組的一部分。 如果未指定 <alias\> ,依預設,直欄的名稱是 <colname\>。 可以是簡單的 ID 或加上雙引號的 ID。

  • <viewname\>.*

    指定視圖的名稱。 此語法指示指定視圖的所有直欄都必須結轉到最外圍的 selectextract 陳述式。

    與 SQL 一樣,AQL 也容許簡寫的 select * 陳述式。 此陳述式的效果是從 from 陳述式的 select 子句中指定的所有輸入中選取所有直欄。 但是,不支援簡寫的 extract * 陳述式。

  • <expr\> as <alias\>

    代表將表示式指派給包含視圖的屬性。

    • <expr\>

      指定由純量函數呼叫、聚集函數呼叫或常數組成的表示式。

    • <name\>

      代表保留 <expr\> 指定為 <alias\>之表示式結果的直欄名稱。 如果未指定 <alias\> ,依預設,直欄的名稱是 <name\>。 可以是簡單的 ID 或加上雙引號的 ID。

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

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

      指定傳回類型 Boolean 的純量函數。

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

      指定由純量函數呼叫組成,並且必須傳回相同類型的表示式。

    如果 <function1()\> 的結果為 true ,則 case 表示式的結果為 <expr1\>的結果,且不會評估任何後續的 when 子句。 否則,會以相同方式評估後續的 when 子句(如果有的話)。

    當未滿足 when 子句的任何條件時,此 case 表示式的結果是預設表示式 <expr\_default\>的結果。 此表示式在選用性的 else 子句中指定。 如果不存在 [else] 子句,那麼此 case 表示式的結果為 null

使用注意事項

  • 不支援下列陳述式:

    select * from Document;
    

    在發出此 Document 陳述式的 .aql 檔案現行上下文或範圍中,可能無法完全瞭解 select 視圖的內容。 缺少內容相關資訊的原因是,此特殊 require document with columns 視圖在模組層次使用時,現行 .aql 檔案以外提供的多個 Document 陳述式可能改變了此視圖的最終綱目定義。 簡寫的 Document.* 陳述式不是有效的 AQL 建構。

  • 您可以從 Document 視圖中明確選取欄位。 下列範例顯示了如何從 Document 視圖中有效地明確選擇欄位:

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

範例

下列範例說明各種形式的 select 清單。

範例 1:使用常數明確指派值

此範例顯示將常數值指派給 select 清單內的 view 屬性。 名為 polarity 的欄位指出 PS.match 的極性是正還是負(請注意,已明確指派常數值給此屬性)。

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;

範例 2:使用函數呼叫明確指派值

下列範例說明如何將函數呼叫的結果明確指派給 select 清單中的 view 屬性。

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

範例 3:從字典擷取獲得 select 清單表示式

下列範例說明 select 清單表示式可以如何從字典擷取的結果中選取類型為 Span 的值。

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

範例 4:case 表示式範例

第一個範例顯示如何指定對特定欄位的空值處理:

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

此範例說明如何分類資料:

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;

from 清單

AQL 中 selectextract 陳述式的第二個部分是 from 清單。 from 清單是以逗點區隔的清單,它是要選取或擷取之值組的來源。

語法

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

說明

  • <from list item\>

    視圖、表格、表格函數參照或巢狀的 AQL 陳述式。 AQL 中的所有巢狀陳述式都必須用括弧括起。

  • <name\>

    <from list item\>的本端名稱,範圍在 select 陳述式或 extract 陳述式內。 本端名稱可以是簡單 ID,也可以是加雙引號的 ID。 包含空格、標點符號符號字元或 AQL 關鍵字的本端名稱必須用雙引號括起。

範例

範例 1:具有視圖和巢狀陳述式的 from 清單

此範例顯示了參照視圖和巢狀的 extract 陳述式的 from 清單。 此範例為陳述式的結果指派了本端名稱 FN。 此範例還為 LastName 視圖的輸出指派了本端名稱 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);

下列名稱包含在外部字典 first.dict 中:

#Dictionary for given names
Aaron
Candra
Freeman
Mathew
Matthew
Zoraida

where 子句

選用性的 where 子句定義要在每個從卡氏乘積產生之值組上套用的述詞,其中的卡氏乘積取自於 from 子句之關係中的所有值組。

語法

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

說明

  • <where clause\>

    指定一個以上的述詞。 where 子句中的任何述詞包含屬於 from 清單的多個視圖中的欄位時,都將執行連接。 此述詞必須是一組內建述詞函數或其他傳回 Boolean 資料類型之使用者定義函數的連結:

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

    where 子句是選用性的,如果沒有要套用的述詞,可以從 select 陳述式省略此子句。

範例

範例 1:在 WHERE 子句中使用述詞來過濾掉結合的值組

此範例顯示的 where 子句只會尋找由有效名字所組成的詞組,且這些名字在相距 0-1 個字元之內的位置後面接著有效的姓氏。

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

下列名稱包含在外部字典 first.dict 中:

#Dictionary for given names
Aaron
Candra
Freeman
Mathew
Matthew
Zoraida

下列名稱包含在外部字典 last.dict 中:

#Dictionary for surnames
Anthony
Lehman
Radcliff

consolidate on 子句

選用性的 consolidate on 子句會指定 selectextract 陳述式輸出的值組之間,重疊文字段的解析方式。 具有非重疊文字段的值組,在使用這個子句時不受影響。

語法

下列程式碼是此子句的一般結構範例:

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

說明

  • <target\>

    from 子句中指定視圖中的直欄,或者指定由純量函數呼叫(包含在 from 子句中指定為引數的視圖的直欄)組成的表示式。

  • '<policy\>'

    指定 Text Analytics 支援的下列其中一個合併原則:

    • ContainedWithin

      此原則是預設。 如果文字段 A 和 B 重疊,並且 A 完全包含 B,則此原則將從輸出移除包含文字段 B 的值組。 如果 A 與 B 相同,則會移除其中一個。 要移除哪個值組是任意選擇。

    • NotContainedWithin

      如果文字段 A 和 B 重疊,並且 A 完全包含 B,則此原則將從輸出移除文字段 A。 如果 A 與 B 相同,則會移除其中一個。 要移除哪個值組是任意選擇。

    • ContainsButNotEqual

      此原則與 ContainedWithin 相同,但會保留完全相等的文字段。

    • ExactMatch

      如果一組文字段涵蓋相同文字地區,則此原則會傳回其中恰好一個文字段。 其他所有文字段都保持不變。

    • LeftToRight

      此原則依照從左到右的順序依次處理文字段。 發生重疊時,會保留最左側、最長的非重疊文字段。 此原則模擬大多數正規表示式引擎的重疊處理原則。

  • <priority\_column\>

    指定類型為 Text、String、Integer 或 Float 的直欄。 只能與 LeftToRight 合併原則一起指定。

  • <priority\_order\>

    指定升冪或降冪。 只能與 LeftToRight 合併原則一起指定。 升冪可確保如果值組 T1 的優先順序為 1,值組 T2 的優先順序為 2,那麼 T1 的優先順序高於 T2。 與之相反,如果優先順序為遞減,那麼 T2 的優先順序更高。 優先順序順序的預設值為遞增。

使用注意事項

  • 存在 priority 子句時,合併的語意遵循以下順序:
    • 從左到右依次處理文字段,在文字段重疊時,保留最左側的文字段。
    • 如果有多個重疊文字段在相同偏移量開始,將根據優先順序來保留優先順序最高的重疊文字段。
    • 藉由在優先順序相同的文字段中保留最長的文字段,而中斷剩餘的關係。
  • 合併將空值視為完全相同。 所有具有空值 <consolidate target\> 的輸入都會產生單一輸出值組,該值組在這些輸入之間隨機選擇。 此行為類似於合併目標直欄中具有相同文字段之值組的作法。 但例外的狀況是,如果原則為 ContainsButNotEqual,則不會產生單一輸出值組。 在該情況下,空值 <consolidate target\> 會輸出具有空值合併目標的所有輸入。

範例

範例 1:根據單一直欄進行合併

此範例會指示系統檢查所有輸出值組的 Person.name 欄位,並使用 ContainedWithin 合併原則來解決重疊問題。

consolidate on Person.name
  using 'ContainedWithin'

範例 2:根據包含多直欄的表示式進行合併

此範例會指示系統檢查將 CombineSpans 純量函數套用於每個輸出值組中的 Person.firstnamePerson.lastname 欄位的結果。 此範例使用 ContainedWithin 合併原則來解決重疊問題。

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

範例 3:使用 LeftToRight 原則和優先順序順序進行合併

假設從輸入文字 John Doe 中擷取下列術語值組:

match: `John`,
priority: `1`

AND

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

這兩個文字段具有相同的開始偏移量。 使用 LeftToRight 原則以及升冪優先順序順序進行合併時,將保留值組 (match: John, priority: 1),因為此值組的優先順序更高。 使用遞減優先順序進行合併時,將保留值組 (match: John Doe, priority: 2),如下列範例所示:

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;

group by 子句

group by 陳述式的選用性 select 子句會指示運行環境元件,依照指定欄位的共同值,而對從相同文件產生的值組進行分組。

語法

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

說明

  • <group by list\>

    指定在 from 子句和純量函數呼叫中,包含視圖之直欄的表示式逗點定界清單。 套用 group by 子句時,共用所有 group by 表示式的公共值的每群組值組都會產生代表整個群組的單一輸出值組。

    未顯示在 group by 子句中的欄位或表示式不能出現在 select 清單中,除非在聚集函數呼叫中使用了該欄位或表示式。 清單中表示式的順序無關緊要。

    group by 子句會將所有空值視為相同。 在具有空值的直欄上, Group by 會導致單一群組。

範例

範例 1:運算聚集值

使用 group by 子句可運算聚集值。 此範例統計文件中每個名字的出現次數。 在此範例中,Count 是聚集函數。

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

在本例中,first.dict 是包含下列項目的外部字典:

#Dictionary for given names
Aaron
Candra
Freeman
Matthew
Zoraida

下列步驟說明了此陳述式的語意:

  1. from 子句中的子查詢產生的值組,依其 firstname 欄位的文字內容進行分組。
  2. 對於每個群組,計算具有非 null firstname 值的值組數目。 對於每個此類群組產生單一輸出值組,其中包含兩個值:名字和該群組中的值組數。

範例 2:將不同欄位分組在一起的問題

此範例說明無效的陳述式。

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

不接受在 select 清單中包含 GetText(P.lastname),因為具有相同 firstname 值的值組可能具有不同的 lastname 值,這會導致語義不明確。

order by 子句

選用性的 order by 子句會指示運行環境元件,將 select 陳述式從每份文件根據 order by 清單值而產生的輸出值組排序,其中 ordery by 清單是一份以逗點定界的表示式集

語法

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

說明

  • <order by list\>

    指定以逗點定界的表示式清單。

    排序是根據以逗點定界之表示式清單的值。 order by 子句支援傳回數字(Integer 或 Float)、Text 或 Span 資料類型的表示式。 如果 order by 子句中的表示式傳回類型為 Span,則將藉由比較相關文字段值來比較結果值組。 在下列範例中,將比較 person 欄位的文字段值。

    order by P.person
    
    

    order by 子句將空值視為未排序(空值之間)。 空值的排序低於其他物件。

範例

範例 1:根據多個表示式排序

假設 person 是類型為 Span 的欄位。 下列 order by 子句指定陳述式傳回每個文件中的值組。 值組先依 person 欄位的文字、再依 person 欄位的開頭,依照字典順序進行排序。

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

limit 子句

選用性的 limit 子句會指定 select 陳述式針對文件產生輸出值組數的限制。

語法

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

說明

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

    指定每個文件的上限輸出值組數。 如果 limit 值大於或等於可以傳回的值組總數,將傳回所有值組。

範例

範例 1:限制傳回數

此範例會傳回每個文件中的前三個人名:

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

select... into 陳述式

select ... into 陳述式適用於在單一陳述式中定義視圖並指定它是輸出視圖。

語法

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

說明

  • <output view name\>

    指定陳述式所定義的輸出視圖的名稱。 select ... into 陳述式與 select 陳述式相同,但附加 into <output view name\> 子句除外。

範例

範例 1:定義視圖

此範例定義了名為 PersonPhone 的視圖,同時將此視圖指定為輸出視圖。

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

此範例等同於下列兩個陳述式:

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

output view PersonPhone;

detag 陳述式

AQL 中的 detag 陳述式提供了用於在執行 AQL 擷取程式之前從 HTML 或 XML 文件中取消所有標籤的函數。

detag 陳述式還可以保留標籤的原始位置以及這些標籤中儲存的任何值。 detag 陳述式從文件中移除標籤時,運行環境元件會記住已取消標籤的文字的偏移量與原始標籤來源的偏移量之間的對映。 Remap 函數是一個特殊的內建函數,用於將已取消標記之文字中的文字段,對映回原始來源中的相等文字段。

語法

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

說明

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

    • <input view name\>

      指定要對其執行 detag 處理程序的輸入視圖的名稱。 <input view name\> 可以是簡式 ID 或雙引號 ID。

    • <text column\>

      指定要對其執行 detag 處理程序的輸入視圖的文字欄位。 <text column\> 可以是簡式 ID 或雙引號 ID。

  • <output view name\>

    指定包含已取消標籤的文字的輸出視圖的名稱。 輸出視圖包含名為 text 的單一直欄,用於保存已取消標籤的文字。 <output view name\> 可以是簡式 ID 或雙引號 ID。

  • always|never

    指定是否在處理 detag 陳述式之前驗證內容是為 HTML 還是 XML。 當您透過 Swagger 來執行非 HTML 及非 XML 文字時,如果文字包含 XML 特殊字元 (例如 <>&) ,則可能會發生問題。 如果缺少 detect content_type 子句,則預設值為 always,並且系統一律會偵測內容。

    • always

      指定在試圖作業之前一律執行驗證,以避免剖析非 HTML 或 XML 的文件時發生問題。 如果 <text column\> 的值似乎不包含標記,系統會跳過現行文件的分離。

    • never

      指定在試圖執行 detag 作業之前從不執行驗證。 即使文字不包含任何 HTML 或 XML 內容,系統也會試圖對目標文字執行取消標籤作業。

  • <element name\>

    指定要註釋之 HTML 或 XML 元素的名稱。 選用性的 annotate 子句可以指示運行環境元件藉由建立一個以上視圖來記住已移除之標籤的相關資訊。

  • <auxiliary view name\>

    指定建立用於保留原始標籤及其屬性的視圖名稱。 可以是簡單的 ID 或加上雙引號的 ID。

  • <attribute name\>

    HTML 或 XML 元素的屬性名稱。

  • <column name\>

    <auxiliary view name\> 中用來儲存 <attribute name\>值的直欄名稱。 可以是簡單的 ID 或加上雙引號的 ID。

範例

範例 1:指定 detag 輸出視圖和輔助視圖

在此範例中,將建立 DetaggedDoc 視圖以保存 text 視圖的 Document 屬性中,原始文字取消標籤的版本。 除了建立 DetaggedDoc 視圖外,annotate 子句還會建立名為 Anchor 的輔助視圖。 此輔助視圖有兩直欄。 一直欄名為 match,用於包含錨點文字。 另一直欄名為 linkTarget,用於包含作為文字的鏈結實際目標。 match 直欄中的文字段是根據 DetaggedDoc 視圖的 text 值。

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

範例 2:使用 Remap 函數

下列範例說明如何使用 Remap 函數,將已取消標記之文字中的文字段,對映回原始來源中的相等文字段。

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

使用 AQL Doc 記錄 detag 陳述式

detag 陳述式的 AQL Doc 註解包含下列資訊:

  • 關於陳述式功能的一般說明。
  • @field,表示要對其執行 detag 處理程序的輸入視圖的每個文字欄位。
  • @auxView,指定視圖名稱。
  • @auxViewField,指定視圖的完整直欄名稱。
/**
* 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;

create dictionarycreate external dictionary 陳述式

create dictionarycreate external dictionary 陳述式用於定義單字或詞組的單字字典,以透過 extract 陳述式或述詞函數識別輸入文字中的比對術語。 create dictionary 陳述式容許在來源 AQL 程式碼中指定字典內容,並且字典內容會在模組的編譯表示法(.tam 檔案)內進行序列化。 create external dictionary 陳述式容許在實例化擷取程式時指定字典內容,而不是在來源 AQL 程式碼中指定字典內容,並且不必重新編譯模組。 因此,外部字典是功能強大的建構,容許 AQL 開發人員在已編譯的模組中公開自訂點。

可以從三個來源建立字典:

  • 字典檔
  • 行內字典宣告
  • 使用 create table 陳述式和 create external table 陳述式建立的表格。

語法

內部 create dictionary 陳述式具有三種語法形式:from filefrom table 和行內格式。

  • 內部字典

    從檔案:

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

    從表格:

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

    行內格式

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

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

說明

  • <dictionary name\>

    指定新的內部或外部字典的名稱。 可以是簡單 ID,也可以是加雙引號的 ID。

  • '<file name\>'

    指定包含字典項目的檔案名稱。 字典檔是以換行定界的文字檔,其中每行有一個字典項目。 字典檔中的項目可以包含多個記號。

  • <table name\>

    指定要從中新增字典項目的表格名稱。 無法利用從其他模組匯入的表格來建立字典。

  • <column name\>

    指定要從中新增字典項目之表格中的直欄名稱。

  • required [true|false]

    指定是否需要外部字典的外部內容才能執行模組。

    • true

      如果子句為 required true,則必須提供包含外部內容之檔案的位置 URI。 指定的檔案必須包含內容。 如果未提供 URI,或檔案不包含內容,則運行環境元件會擲出異常狀況。

    • false

      如果子句為 required false,即使未提供此字典的外部內容 URI,也可以順利執行模組。 如果未提供 URI,運行環境元件會將其視是空的字典。

    現在已淘汰使用 create external dictionary <dictionary-name\> allow_empty ,並導致編譯器警告。

  • '<language code(s)\>'

    對於要用於評估字典的語言,或外部字典的文件語言,指定以逗點定界的雙字母語言碼清單,例如 en(英文)或 zh(中文)。 對於語言碼未包含在此字串中的文件,字典不會產生任何結果。

    如果省略了 language 參數,則字典語言預設為下列其中一個語言集:

    • 透過包含模組中 set default language 陳述式指定的語言集(如果已宣告)。
    • 包含德文 (de)、西班牙文 (es)、英文 (en)、法文 (fr)、義大利文 (it) 和未指定語言 (x_unspecified) 的語言集。
  • lemma_match

    使用詞形還原化在文件中尋找與單字典術語類似單字的相符項。

    詞形還原化是確定給定單字之詞目的程序。 詞目是一個單字,可以用來作為單一給定術語的相符項。 例如,術語 "go" 可以與術語 "goes" 、 "going" 、 "gone" 或 "went" 相符合。 此程序涉及複雜的作業,例如理解上下文並確定句子中某個單字的詞性。 IBM 多語言記號器為其提供詞性支援的所有語言都可以使用詞形還原化。

    詞目比對僅針對使用 lemma match 子句宣告的字典執行。

    使用 lemma_match 子句的字典擷取的語意如下所示:

    • 會計算輸入文件中每個記號的詞形還原化形式。
    • 將根據詞形還原化的文件來評估字典。 不能將 lemma_match 選項與 case exact 選項一起使用。 如果同時使用這兩個選項,將傳回編譯器錯誤。
  • case (exact | insensitive)

    指定字典在確定特定文件地區是否相符合時,所執行的大小寫摺疊類型。

    • exact

      指定區分大小寫的完全相符。

    • insensitive

      指定相符項不區分大小寫。 此選項是預設值。

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

    指定要包含在行內字典中的字串。 行內字典中的項目可以包含一個以上記號。

使用注意事項

  • 建議使用 from filefrom table 格式,尤其是預期要修改項目,或者有許多項目時。 使用這兩種格式,可以修改字典的內容,而無需修改程式碼。

  • create dictionary 陳述式由模組化 AQL 編譯器處理時,對 create dictionary ... from file 語法中指定的字典檔位置的參照必須相對於發出此 create dictionary 陳述式的模組的根目錄。

  • 在字典檔中可以藉由在註解前面加上字元 # 來指定註解。 註解可以在一行中任意處開始。

  • 如果要指定跨多行的註解,必須在每行前面加上註解字元。 如果註解字元是字典項目的一部分,必須使用反斜線字元 (\) 將它跳出,如 \# 中所示。 如果反斜線字元是字典項目的一部分,必須用反斜線將它自己跳出,如 \\ 中所示。

  • 對於外部字典,在載入模組期間,必須指定正在載入的模組所需外部字典的 URI 清單。

  • 字典詞形還原化:現有字典比對語意與詞形還原化語意之間的主要差異是,後者是針對詞形還原化形式的文件(而不是原始形式的文件)執行比對。

    屬於已啟用詞目比對之字典的字典項目具有下列必要條件:

    • 字典項目可以包含一個以上記號,其中每個項目記號都是一個詞目。 若要建立詞目的字典,可以使用 GetLemma 純量函數。
    • 字典項目的記號應該用空格區隔。 如果記號包含空格,則應該使用反斜線 (\) 字元來跳出空格。
  • 下表顯示了 create external dictionary 陳述式與 create dictionary 陳述式之間的差異:

create external dictionary create dictionary
  • 為字典定義位置保留元,其內容在起始設定時提供。
  • 需要在編譯時期提供字典的內容。
  • 在模組的編譯表示法 (.tam) 中序列化。

範例

範例 1:建立外部字典

外部字典 PersonPositiveClues 應該在載入時使用外部檔案中的值進行移入。 此外,該字典也應該針對其旗標所指定的某些西方語言進行比對。

module PersonModuleEnglish;

create external dictionary PersonPositiveClues
  allow_empty false
  with case exact;

export dictionary PersonPositiveClues;

範例 2:詞形還原化

假設字典啟用了詞目比對,並包含兩個項目:go shop 和 went shopping。 文件中包含文字 Anna went shopping。 詞形還原化形式的輸入文件為 Anna go shop。 詞目比對會將 went shopping 傳回作為 go shop 項目的相符項。 原始文件文字不會與字典項目進行比較,只有詞形還原化的文件文字才會與字典項目進行比較。 因此,文件中沒有 went shopping 項目的相符項。

記錄具有 AQL Doc 的 create dictionarycreate external dictionary 陳述式

create dictionary 陳述式的 AQL Doc 註解包含下列資訊:

關於字典的一般說明。

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

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

create external dictionary 陳述式的 AQL Doc 註解包含所建立字典的相關一般說明。 下列字串說明格式:

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

create table 陳述式

create table 陳述式用於建立 AQL 表格。

AQL 中的 create table 陳述式用於定義靜態參考表,以使用相關資訊來擴增註釋。

語法

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

說明

  • <table name\>

    指定要建立的表格的名稱。 <table name\> 可以是簡式 ID 或雙引號 ID。

  • <colname\>

    指定要建立的直欄名稱。

  • <type\>

    指定相關聯直欄的 AQL 資料類型。 所有直欄必須為是文字、整數、浮點數或布林等類型。

  • <value\>

    指定要在建立的表格中移入的值組。

範例

範例 1:建立公司名稱表格

在此範例中,create table 陳述式新增了更多位置 meta 資料到公司名稱註釋:

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

使用 AQL Doc 記錄 create table 陳述式

create table 陳述式的 AQL Doc 註解包含下列資訊:

  • 關於表格的一般說明。
  • 此表格綱目中每個直欄名稱的 @field。
/** 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');

create external table 陳述式

已編譯的模組在所有輸入文件中執行時,可以使用 create external table 陳述式來指定具有已確定內容的表格。 您可在載入時提供表格內容,而不是在來源 AQL 程式碼中提供表格內容,並且不必重新編譯模組。

外部表格是功能強大的建構,容許 AQL 開發人員在已編譯的模組中公開自訂點。

語法

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

說明

  • <table-name\>

    指定要建立的外部表格的名稱。 <table-name\> 可以是簡式 ID 或雙引號 ID。

  • <colname\>

    指定要建立的直欄名稱。

  • <type\>

    指定相關聯直欄的 AQL 資料類型。 所有直欄必須為是文字、整數、浮點數或布林等類型。

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

    指定要在外部表格中使用的其他直欄和 AQL 物件。

  • allow_empty [true|false]

    指定 allow_empty 子句的值。

    • true

      如果子句為 allow_empty true,那麼即使未提供此表格的外部內容的 URI,也可以順利執行模組。 如果未提供 URI,那麼運行環境元件會將其視是空的表格。

    • false

      如果子句為 allow_empty false,那麼必須提供包含外部內容的檔案的位置 URI。 指定的檔案必須包含內容。 如果未提供 URI,或檔案不包含內容,則運行環境元件會擲出異常狀況。

使用注意事項

  • 模組的編譯表示法包含模組定義之外部物件(視圖、字典和表格)的相關 meta 資料。
  • 在載入模組期間,必須指定正在載入的模組所需外部表格的 URI 清單。
  • 外部表格內容支援的格式是包含標頭的一個 CSV (.csv) 檔案。

下表顯示了 create external table 陳述式與 create table 陳述式之間的差異:

create external table create table
  • 為表格定義位置保留元,其內容在起始設定時提供。
  • 需要在編譯時期提供表格的內容。
  • 在模組的編譯表示法 (.tam) 中序列化。

範例

範例 1:建立在載入時移入的外部表格

外部表格 PersonNegativeClues 應該在載入時進行移入,因為有 allow_empty false 旗標。

module PersonModuleFrench;

create external table PersonNegativeClues (name Text)
  allow_empty false;

export table PersonNegativeClues;

範例 2:使用外部表格建立字典

字典還可以從外部表格建立,這類似於從使用 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;

使用 AQL Doc 記錄 create external table 陳述式

create external table 陳述式的 AQL Doc 註解包含下列資訊:

  • 關於表格的一般說明。
  • 此表格綱目中每個直欄名稱的 @field。
/** 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;

create external view 陳述式

除了用於保留文字和標籤內容的預先定義 create external view 視圖外,AQL 中的 Document 陳述式也容許將文件的更多相關 meta 資料指定為新視圖。

語法

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

說明

  • <view_name\>

    指定外部視圖的內部名稱。 在 AQL 規則中,外部視圖是以這個名稱進行參照。 <view_name\> 可以是簡式 ID 或加雙引號的 ID。 <view_name\> 不能包含句點字元。

  • <colname\>

    指定要在外部視圖中定義的直欄名稱。

  • <type\>

    指定相關聯直欄的資料類型。 外部視圖直欄支援的資料類型為 Text、Span、Integer 和 Float。

  • '<view_external_name\>'

    指定外部視圖的外部名稱。 在外部視圖中移入值組的外部系統會以外部名稱參照外部視圖。 '<view_external_name\>' 必須是用單引號 ('ExternalName ') 括住的字串常數。

範例

為了說明外部視圖,假設有一個應用程式範例需要您識別電子郵件訊息中的人名。

範例 1:識別電子郵件訊息中的人名

假設電子郵件訊息的文字為 "Ena, please send me the document ASAP" 。 雖然人可能能夠根據電子郵件文字理解 Ena 是人名,但撰寫用於以高精準度識別一般文字中之人名的 AQL 規則可能過於保守,根據 Ena 是首字母大寫單字這點,無法以高信賴度得出相同結論。

提高規則涵蓋面的一種方法,是使用電子郵件的寄件人收件人抄送欄位中的單字作為更多證據。

如果電子郵件是發給 "Ena Smith" 的,並且應用程式將此資訊提供給擷取程式使用,則擷取程式開發人員可以撰寫更多 AQL 規則來提升擷取程式的涵蓋面(基於電子郵件通常發送給人員這一領域知識)。

例如,可以撰寫 AQL 規則來識別電子郵件 meta 資料欄位中的人員記號。 然後,在確定電子郵件文字中的首字母大寫記號是否為人名時,可以將此資訊用作重要線索。 通常,電子郵件訊息 meta 資料並不是實際電子郵件訊息的一部分,但應用程式可以使用外部視圖使這些 meta 資料可供擷取程式使用。

在執行時,對於必須處理的每個電子郵件,應用程式可以將電子郵件文字作為文件文字(用於移入 Document 視圖)傳遞。 此外,應用程式也可以使用適當定義的外部視圖來傳遞額外的 meta 資料。

下列陳述式定義名為 EmailMetadata 的外部視圖。 該外部視圖的綱目包含類型為 Text 的三個欄位。 在執行時,視圖 EmailMetadata 會自動從名為 EmailMetadataSrc 的外部類型進行移入。 然後,可以在 AQL 規則中參照 EmailMetadata 視圖,這類似於參照其他任何視圖的作法。

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

使用 AQL Doc 記錄 create external view 陳述式

create external view 陳述式的 AQL Doc 註解包含下列資訊:

  • 關於視圖的一般說明。
  • 視圖中每個直欄名稱的 @field。
/**
* 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';

外部構件的檔案格式

支援三種類型的外部構件:外部視圖、外部字典和外部表格。

外部字典

下面定義了包含外部字典項目的檔案的格式:

  • 以換行定界的文字檔。
  • 每行一個字典項目。
  • 建議的副檔名為 .dict,但也可以支援其他副檔名。
  • 字典中的項目可以包含多個記號。
  • 註解可以藉由在註解內容前面加上字元 # 來指定。
  • 註解可以在一行中任意處開始。
  • 多行註解必須在每行開頭包含 # 字元。
  • 字典項目可以包含註解字元,但每個註解字元都須使用反斜線字元跳出。 例如,\#

外部表格

外部表格內容支援的檔案格式是包含標頭的 .csv 檔案。

下列範例顯示了 create external table 陳述式以及指定此外部表格的內容的 .csv 檔案。

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

.csv 檔案的第一行包含標頭。 其餘行包含資料。

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

外部視圖

可以用下列方式指定外部視圖的內容:

  • 當您執行擷取程式時,唯有在使用 JSON 輸入格式的情況下,才能為資料集合指定外部視圖內容。

內建函數

AQL 有一個內建函數的集合,以便用於擷取規則。

  • 聚集函數 聚集函數用來在一組輸入值之間實作運算(例如計數、數學運算及其他運算)。 這些函數只會傳回一個結果。
  • 述詞函數 述詞函數會對其輸入引數測試特定的述詞,並傳回對應的布林值。
  • 純量函數 純量函數會對一組輸入值組之間的一個欄位值執行運算,並傳回非布林值,例如文字段、文字或整數。 這些函數可以用於 select 陳述式或 select 陳述式的 extract 清單內。 它們也可以用來作為述詞函數的輸入。

聚集函數

聚集函數用來在一組輸入值之間實作運算(例如計數、數學運算及其他運算)。 這些函數只會傳回一個結果。

這些函數可以在 select 陳述式的 select 清單中使用,但不能在 extract 陳述式中使用。

下列範例是一般形式的聚集函數呼叫:

Aggregate_Function_Name(argument)

argument 可以是:

  • 表示式,包含 from 子句中視圖的直欄,或者包含涉及 from 子句中視圖直欄的純量函數的組合。

    在除了說明的情況之外的大多數情況下,會忽略引數的空值。

  • 字元 *,適用於 Count(*) 聚集函數的特殊案例。

    在這種情況下,將計算輸出的所有列,包括空值。

聚集函數 引數類型 傳回類型 回覆值
Avg(expression) 整數、浮點數 浮點數 所有輸入值的平均,如果未選取任何列,將為空值
計數 (\ *) 整數 所有輸入列數
Count(expression) 任何 整數 所有非空值輸入值的數目
List(expression) 整數、浮點數、文字、文字段 與輸入引數類型相同的純量值的清單 非空輸入值的未排序清單:這是包,而不是集,因此可能包含重複項。 如果只選取了空值,那麼為空清單
Max(expression) 整數、浮點數、文字、文字段 與引數類型相同 所有輸入值中的最大元素,如果未選取任何列,將為空值
Min(expression) 整數、浮點數、文字、文字段 與引數類型相同 所有輸入值中的最小元素,如果未選取任何列,將為空值
Sum(expression) 整數、浮點數 與引數類型相同 所有輸入值的和,如果未選取任何列,將為空值

現行版本的限制:

現行版本的 AQL 支援透過 aggregate 函數清單來建立純量值。

範例

下列範例說明聚集函數可以如何計算人名註釋數目,或計算與文件中識別之每個不同姓氏相關聯的名字集合:

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

下列範例說明 Min 和 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;

述詞函數

述詞函數會對其輸入引數測試特定的述詞,並傳回對應的布林值。

述詞函數的輸入引數除了包含字典、正規表示式等外,還可包含其他純量函數或聚集函數的回覆值。 這些函數可以在 where 陳述式的 select 子句以及 extract 陳述式的 having 子句中使用。

AND

And 函數接受可變數目的 Boolean 引數,並傳回所有輸入參數中邏輯 AND 運算的結果。

在邏輯 AND 運算過程中,AQL 最佳化程式不會試圖最佳化此函數之引數的評估順序。 如果任何輸入為 null,則結果為 null

假設有以下查詢格式:

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

因此,使用 AND 運算的查詢格式的執行速度通常比以下形式的相同查詢慢得多:

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

請儘可能使用 SQL 樣式和關鍵字,而不要使用此函數。

包含

Contains 函數會以兩個文字段作為引數:

Contains(<span1>, <span2>)

如果 TRUE 完全包含 span1,此函數會傳回 span2。 如果 span2 的開始位置等於 span1 的開始位置或位於其之後,並且結束位置等於 span1 的結束位置或位置其之前,那麼將完全包含 span2。 如果任一引數為 null,此函數會傳回 null

ContainsDict

ContainsDict 函數會檢查某個文字段的文字是否包含給定字典中的任何項目。 此函數接受以下內容作為輸入引數:一個字典、一個選用性的旗標指定以及一個要進行評估的文字段。

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

如果文字段包含字典的一個以上相符項,ContainsDict 函數會傳回 TRUE。 旗標可以為 ExactIgnoreCase

  • 如果使用 Exact,會針對字典中每個術語執行區分大小寫的比對。
  • 如果使用 IgnoreCase,針對字典中每個術語執行的比對不會區分大小寫。
  • 如果未指定任何旗標,字典會根據建立時指定的任何旗標進行比對。 如果未在建立期間指定任何旗標,則會使用 IgnoreCase 旗標進行比對。

如果文字段為 null,則函數會傳回 null

下列範例說明 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);

字典一律會在記號界限進行評估。 例如,如果字典包含術語 fish,則在文字 Let's go fishing! 中沒有相符項。

ContainsDicts

ContainsDicts 函數會檢查某個文字段的文字是否包含任何給定字典中的任何項目。 此函數接受以下內容作為輸入引數:兩個以上的字典、一個選用性的旗標指定以及一個要進行評估的文字段。

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

如果文字段包含其中至少一個指定字典中的一個以上相符項,ContainsDicts 函數會傳回 TRUE。 旗標可以為 ExactIgnoreCase

  • 如果使用 Exact,會針對字典中每個術語執行區分大小寫的比對。
  • 如果使用 IgnoreCase,針對字典中每個術語執行的比對不會區分大小寫。
  • 如果未指定任何旗標,字典會根據建立時指定的任何旗標進行比對。 如果未在建立期間指定任何旗標,則會使用 IgnoreCase 旗標進行比對。

如果任一引數為空值或這兩個引數均為空值,此函數會傳回 null

下列範例說明如何使用具有 ContainsDicts 旗標的 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

ContainsRegex 函數會檢查某個文字段的文字是否與給定正規表示式相符。 此函數接受以下內容:一個要與其比對的正規表示式、一個選用性的旗標指定以及一個要與其比對的輸入文字段。

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

如果該文字段的文字(作為個別的 Java™ 字串)包含正規表示式的一個以上相符項,此函數會傳回 TRUE。 如果文字段為 null,此函數會傳回 null。 選用性的旗標會影響比對行為,這類似於 Java 正規表示式中使用的旗標。

旗標字串是藉由使用 | 作為分隔字元,結合下列一個以上旗標而形成:

  • CANON_EQ
  • CASE_INSENSITIVE
  • DOTALL
  • LITERAL
  • MULTILINE
  • UNICODE(沒有 CASE_INSENSITIVE 時無意義)
  • UNIX_LINES

flags 字串的範例為

'UNICODE | CASE_INSENSITIVE'

假設有以下範例,其中 ContainsRegex 識別產品名稱及其任一端的版本號碼提及項目。 與 MatchesRegex 的範例不同,版本號碼相符項並不是使用 regex 嚴格識別,而是根據包含與 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)
);

等於

Equals 函數接受任意類型的兩個引數:

Equals(<arg1>, <arg2>)

如果兩個文字段的開始和結束偏移量相同,並且包含相同的文字,這兩個文字段會視為相等。 如果任一引數為空值或這兩個引數均為空值,此函數會傳回 null

下列範例說明 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));

Follows

Follows 述詞函數接受兩個 Span 引數和兩個 Integer 引數:

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

如果 TRUE 結束位置與 span1 開始位置之間的字元數介於 span2minchar(含 minchar 和 maxchar)之間,此函數會傳回 maxchar。 如果任何引數為 null,則函數會傳回 null

FollowsTok

FollowsTok 述詞函數是 Follows 的一個版本;但是,FollowsTok 距離引數計算的是記號數,而不是字元數:

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

如果 FollowsTok 結束位置與 TRUE 開始位置之間的記號數介於 span1span2(含 mintok 和 maxtok)之間,那麼 mintok 函數會傳回 maxtok。 如果任何引數為 null,則函數會傳回 null

GreaterThan

GreaterThan 述詞函數接受任意類型的兩個引數:

GreaterThan(<arg1>, <arg2>)

如果 <arg1> 大於 <arg2>,則此函數會傳回 TRUE 。 如果任一引數為 FALSE,則此函數會傳回 null

IsNull

IsNull 函數用於測試資料是否為空值。 此函數接受任何類型的單一引數,如果單一引數為 TRUE,則此函數會傳回 null,否則傳回 FALSE。 此述詞和已定義之 NotNull 述詞的行為,與在輸入為空值時傳回空值的其他所有述詞不同。

MatchesDict

MatchesDict 函數會以一個字典(如字典擷取)、一個選用性的旗標指定以及一個文字段作為引數:

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

如果文字段與字典中的一個以上術語完全相符,MatchesDict 函數會傳回 TRUE。 旗標可以為 ExactIgnoreCase

  • 如果使用 Exact,會針對字典中每個術語執行區分大小寫的比對。
  • 如果使用 IgnoreCase,針對字典中每個術語執行的比對不會區分大小寫。
  • 如果未指定任何旗標,字典會根據建立時指定的任何旗標進行比對。 如果未在建立期間指定任何旗標,則會使用 IgnoreCase 旗標進行比對。

如果任何引數為 null,則函數會傳回 null

字典一律會在記號界限進行評估。 例如,如果字典包含術語 fish,則在文字 Let's go fishing! 中沒有相符項。

MatchesRegex

MatchesRegex 函數的語法類似於 ContainsRegexContainsRegex 函數與 MatchesRegex 函數不同,唯有作為個別 Java 字串採用之文字段的整個文字與正規表示式相符時,才會傳回 TRUE。 如果任何引數為 null,則函數會傳回 null。 選用性的旗標會影響比對行為,這類似於 Java 正規表示式中使用的旗標。

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

旗標字串是藉由使用 | 作為分隔字元,結合以下部分旗標而形式:

  • CANON_EQ
  • CASE_INSENSITIVE
  • DOTALL
  • LITERAL
  • MULTILINE
  • UNICODE(沒有 CASE_INSENSITIVE 時無意義)
  • UNIX_LINES

flags 字串的範例為

'UNICODE | CASE_INSENSITIVE'

假設有以下範例,其中 MatchesRegex 用於識別產品名稱及其右側的版本號碼提及項目。 與 ContainsRegex 區段中的範例不同,在此範例中,確切的版本號碼被識別為緊跟在產品名稱提及項目之後的記號。

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

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

Not

Not 函數接受單一 Boolean 引數,並傳回其補充項。 如果引數為 null,則函數會傳回 null

NotNull

NotNull 函數接受任何類型的單一引數。

顧名思義,如果引數的值非空值,則 NotNull 函數會傳回 TRUE;如果引數為 FALSE,則會傳回 null

Or

Or 函數接受可變數目的非 null Boolean 引數。 如果任何引數為 null,則函數會傳回 null

如果其中任一個評估為 Or,則 TRUE 函數會傳回 TRUE

Overlaps

Overlaps 函數接受兩個 Span 引數:

Overlaps(<span1>, <span2>)

如果兩個輸入文字段在文件文字中重疊,此函數會傳回 TRUE。 如果任一引數為 null,此函數會傳回 null

純量函數

純量函數會對一組輸入值組之間的一個欄位值執行運算,並傳回非布林值,例如文字段、文字或整數。 這些函數可以用於 select 陳述式或 select 陳述式的 extract 清單內。 它們也可以用來作為述詞函數的輸入。

如果需要 Span 物件,而提供的是 Text 物件,則會根據此 Text 物件,使用涵蓋該 Text 物件全長的開始和結束偏移量,自動產生已轉換的 Span 物件。

如果需要 Text 物件,而提供的是 Span 物件,則會根據該 Span 物件的文字值,自動產生已轉換的 Text 物件。

Chomp

Chomp 函數類似於 Perl 中的 Chomp 運算子,但 Chomp 是對文字段(而不是字串)運作:

Chomp(<span1>)

下列範例說明 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;

如果輸入文字段在開頭或結尾包含任何空格,那麼 Chomp 函數會將文字段縮減到足夠小,以移除空格。 然後,此函數會傳回沒有前導或尾端空格的新文字段。 如果輸入文字段沒有前導或尾端空格,則 Chomp 函數會傳回相同的文字段。 如果輸入文字段為 null,則 Chomp 會傳回 null

CombineSpans

CombineSpans 函數會以兩個文字段作為輸入,如果這兩個文字段是根據相同文字物件,此函數會傳回完全涵蓋兩個輸入文字段的最短文字段。

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

CombineSpans 函數對其輸入文字段的順序很敏感,除非使用 IgnoreOrder 參數。 使用選用性的 IgnoreOrder 參數時,將忽略兩個文字段的順序。

下列範例說明 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);

此函數的語意如下所示:

  • 如果 span1span2null,或者這兩個文字段是根據不同的 Text 物件,此函數會傳回 null
  • 否則,如果 span1 小於 span2,或者使用了 IgnoreOrder 參數,此函數會傳回涵蓋 span1span2 的最短文字段。
  • 否則,如果 span1 大於 span2,並且未使用 IgnoreOrder,此函數會傳回運行環境錯誤。

根據 Span 的定義,CombineSpans 函數引數的不同情境如下所示:

  • 跨距 2 一律在跨距 1 之後。 換句話說,會維持由左至右的順序:

    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]
    
  • 跨距 2 不在跨距 1 之後。 換句話說, 不會 維護由左至右的順序:

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

GetBegin 函數接受單一 Span 引數,並傳回輸入文字段的開始偏移量。

例如:

GetBegin([5, 10])

傳回值 5

與此類似,GetEnd 函數用於傳回其輸入文字段的結束偏移量。

下列範例說明 GetBeginGetEnd 函數的用法。

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

對於這兩個函數,如果引數為 null,則函數會傳回 null

GetLanguage

GetLanguage 函數接受單一 Span 引數,並傳回文字段之來源文字的雙字母語言碼。 如果引數為 null,則函數會傳回 null

僅當資料來源使用合適的語言來標籤文字欄位時,此陳述式才會產生有意義的結果。

GetLemma

GetLemma 函數會以單一 Span 或 Text 物件作為引數,並傳回包含詞形還原化形式之輸入文字段的字串。 如果引數為 null,則函數會傳回 null。 使用進行詞目比對的字典項目,此函數可以確定記號器傳回的詞形還原化形式的各種記號。 例如,對於文字段 went shopping,GetLemma 會傳回詞目字串 go shop

此函數的結果遵循以下規則:

  • 如果輸入文字段的開始和結束位置與記號的開始和結束位置相同,則結果會包含詞目序列,而該序列以第一個記號的詞目為開頭,後面依序接著一個空格、第二個記號的詞目、一個空格,依此類推(例如,dog cat fish bird ...)。 如果記號的詞目由空格組成,則請使用反斜線字元跳出空格 (\)。
  • 如果輸入文字段以空格為開頭或結尾(例如,在兩個記號之間開始或在兩個記號之間結束),則此函數會忽略開頭和尾端的空格。
  • 如果輸入文字段從記號中間開始或在記號中間結束,則輸出會由下列內容組成(順序如下),並以空格區隔各內容:
    • 表面形式的第一個局部記號(如果存在)。
    • 詞目序列,對應於第一個到最後一個完整記號。 如果任何完整記號的詞目由空格組成,請使用反斜線字元跳出空格 (\)。
    • 表面形式的最後一個局部記號(如果存在)。

如果使用的記號器無法產生詞目,則此函數會傳回錯誤。

您可以使用 GetLemma() 函數來建立詞形還原化形式的字典。 對包含其詞形還原化形式要包含在字典中之術語的輸入,呼叫 GetLemma()

GetLength

GetLength 函數接受單一 Span 引數,並傳回輸入文字段的長度。 如果引數為 null,則函數會傳回 null

例如:

GetLength([5, 12])

傳回值 7。

GetLengthTok

GetLengthTok 函數接受單一 Span 引數,並傳回記號中輸入文字段的長度。 如果輸入引數為 null,則函數會傳回 null

GetString

GetString 函數會以單一 AQL 物件作為其引數,並傳回從 Text 物件之字串表示形成的 Text 物件。

對於 Span 和 Text 引數,傳回的值與 GetText() 傳回的值不同。 對於 Text 物件,傳回的值包含以單引號括住的字串。 對於 Span 物件,傳回的值還包含用方括弧括起的偏移量。

對於純量清單,此函數會傳回清單中元素的 GetString() 值,並以分號連接各值。 對於 Integer、Float、Boolean 和 String 引數,此函數會將引數的值作為字串傳回。 對於值為 null 的引數,此函數會傳回 null

GetText

GetText 函數會以單一 Span 或 Text 作為引數。 對於文字段輸入,此函數會根據該文字段標示的實際字串來傳回文字物件。 對於文字輸入,此函數會傳回輸入文字物件。 如果輸入為 null,則函數會傳回 null。 例如:

GetText([5, 12])

該文字段傳回文件中字元位置 5 - 12 的子字串。

GetText 函數有兩個主要用途。

測試兩個文字段所標示文字之間的字串是否相等。

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

將一個文件分割為多個更小的子文件。

例如,如果主要文件是由多篇部落格文章組成的部落格,您可以使用 GetText 為每篇部落格文章建立一個子文件。

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

LeftContext 函數會以 Span 和 Integer 作為輸入:

LeftContext(<input span>, <nchars>)

LeftContext(<input span\>, <nchars\>) 函數會傳回新的文字段,其中包含緊接在 <input span\>左側的文件 nchars 字元。 如果輸入文字段從文件開頭開始少於 <nchars\> 個字元,則 LeftContext() 會傳回從文件開頭開始直到輸入文字段開頭為止的文字段。

例如,LeftContext([20, 30], 10) 會傳回文字段 [10, 20]。 文字段 LeftContext([5, 10], 10) 會傳回 [0, 5]。

如果輸入從文件的第一個字元開始,LeftContext() 會傳回長度為零的文字段。 與此類似,RightContext 函數會傳回其輸入文字段右側的文字。 針對這兩個函數,如果任何引數為 null,則函數會傳回 null

LeftContextTok 及 RightContextTok

LeftContextTokRightContextTok 函數是 LeftContextRightContext 的變體版本,採用記號數作為距離:

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

下列範例說明 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;

針對這兩個函數,如果任何引數為 null,則函數會傳回 null

Remap

Remap 函數接受單一 Span 引數:

Remap(<span>)

如果輸入文字段所根據的文字物件是藉由轉換另一個文字物件而產生,則 Remap 函數會將該文字段轉換為根據原始「來源」文字的文字段。

例如,如果文字段 N.name 是根據已取消標記的文件,且該文件是透過 AQL detag 陳述式執行 HTML 而產生,則

Remap(<N.name>)

會傳回原始 HTML 的相等文字段。

如果藉由對空文件執行 detag 陳述式而產生 Span 引數,則此函數會將文字段重新對映到文件的開頭(換句話說,Document.text[0-0])。 此外,如果 detag 陳述式產生了空字串,此函數也會將文字段重新對映到文件開頭。 AQL 中唯一會產生此類衍生文字物件的就是 detag 陳述式。

下列範例說明 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;

如果 Remap 的引數不是衍生的文字物件,也不是根據衍生文字物件的文字段,則此函數會產生錯誤。 如果引數為 null,則函數會傳回 null

SpanBetween

SpanBetween 函數會以兩個文字段作為輸入,如果這兩個文字段是根據相同文字物件,此函數會傳回恰好涵蓋這兩個文字段之間文字的文字段;如果這兩個文字段是根據不同的文字物件,則會傳回 null

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

使用選用性的 IgnoreOrder 參數時,AQL 編譯器將忽略兩個文字段的順序。

如果兩個文字段之間不存在任何文字,則 SpanBetween 會傳回從 <span1>結尾開始的空白文字段。

CombineSpans類似,除非您使用 IgnoreOrder 參數,否則 SpanBetween 會對其輸入的順序敏感。 因此,

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

會傳回文字段 [10, 50],而

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

會傳回文字段 [60, 60]

如果 SpanBetween 的引數為 null,此函數會傳回 null

SpanIntersection

SpanIntersection 函數會以兩個文字段作為輸入,如果這兩個文字段是根據相同文字物件,此函數會傳回涵蓋這兩個輸入所涵蓋文字的文字段;如果這兩個文字段是根據不同的文字物件,則會傳回 null

SpanIntersection(<span1>, <span2>)

例如:

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

會傳回文字段 [10, 20],而

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

會傳回文字段 [7, 10]

如果這兩個文字段不重疊,SpanIntersection 會傳回 null。 如果任一文字段輸入為 null,此函數會傳回 null

SubSpanTok

SubSpanTok 函數會以一個文字段及一對進入該文字段中的偏移量作為輸入:

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

如函數名稱所示,根據系統配置使用的任何記號器, <first_tok><last_tok> 引數是記號中的距離。

SubSpanTok 函數會傳回一個新文字段,其中涵蓋輸入文字段內所指示的記號範圍(含兩端值)。 如果指定的記號範圍從輸入文字段內開始,並且超出輸入文字段的結束位置,則將傳回所包含的記號範圍部分。 如果 <first_tok> 代表目標文字段以外的距離,則 SubSpanTok 會傳回從輸入文字段開頭開始的零長度文字段。

如果任何輸入為 null,此函數會傳回 null

ToLowerCase

ToLowerCase 函數會以單一物件作為其引數,並傳回該物件的小寫字串表示。 轉換為字串的執行方式與 GetString() 函數執行轉換的方式相同。

此函數的主要用途是執行不區分大小寫的等值連接:

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

如果輸入物件為 null,此函數會傳回 null

create function 陳述式

若要對 AQL 不支援的擷取值執行作業,您可以定義自訂函數,以便用於稱為使用者定義函數 (UDF) 的擷取規則。

AQL 支援使用者定義純量函數和使用者定義表格函數。 Java™ 和 PMML 是 UDF 唯一支援的實作語言。 純量函數傳回單一純量值,而表格函數傳回一個以上值組(也就是一個表格)。

您可以遵循四個步驟來實作使用者定義的函數 (UDF):

  1. 實作函數

    AQL 支援使用 Java 或 PMML 實作的使用者定義函數 (UDF)。

  2. 在 AQL 中宣告函數。

    您可以使用 create function 陳述式,讓來自 PMML 檔案的使用者定義純量函數及機器學習模型可供 AQL 使用。

  3. 在 AQL 中使用函數。

    使用者定義函數與 AQL 陳述式及子句搭配使用。

  4. 除錯 UDF。

    因為以 Java 為基礎的使用者定義函數 (UDF) 在 Java 類別中實作為公用方法,因此對 UDF 進行除錯的方式與針對 Java 程式進行除錯的方式相同。

實作使用者定義函數

AQL 支援使用 Java™ 或 PMML 實作的使用者定義函數 (UDF)。

此區段特別著重說明使用 Java 實作的 UDF。 對於使用 PMML 實作的 UDF,機器學習模型會儲存在 PMML XML 檔案中。 如需如何建立這些模型的相關資訊,請參閱 PMML 的文件: [http://dmg.org/pmml/v4-1/GeneralStructure.html]

您可以在 Java 類別中將純量 UDF 作為公用方法實作。 還可以在延伸 API com.ibm.avatar.api.udf.TableUDFBase 的 Java 類別中將表格 UDF 作為公用方法實作。 此外,表格 UDF 可以選擇性置換超類別 com.ibm.avatar.api.udf.TableUDFBase 的 initState() 方法。

如果 UDF 具有類型為 Span、Text 或 ScalarList 的輸入參數,或者 UDF 的傳回類型為 Span、Text 或 ScalarList,那麼 Java 類別必須匯入 com.ibm.avatar.algebra.datamodel.Span、com.ibm.avatar.algebra.datamodel.Text 或 com.ibm.avatar.algebra.datamodel.ScalarList 類別才能編譯。

表格函數需要額外 API 來提供輸出綱目資訊。 這些 API 屬於基礎類別 com.ibm.systemt.API.udf.TableUDFbase。 如果子類別包含多個表格函數,那麼會為每個實例建立個別的 Java 物件。

若要讓 UDF 程式碼可從其 Jar 檔中擷取非類別資源,唯一支援的方法是 getResourceAsStream()。 不支援使用其他方法(例如,getResource()getResources()getSystemResource())來存取資源。 例如,包含 com.ibm.myproject.udfs 包中 my.properties 內容檔的 UDF Jar 檔可以使用下列 Java 陳述式對其進行存取:

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

使用 Java 實作的 UDF 生命週期

在對擷取程式進行編譯 (CompileAQL.compile() API)、實例化 (OperatorGraph.createOG() API) 和驗證 (OperatorGraph.validateOG() API) 時將執行下列作業,對於 AQL 中的每個 create function 陳述式恰好執行一次:

  1. 使用全新的類別載入器來載入包含 UDF 方法的 Java 類別。 該類別會在對應的 create function 陳述式中指定的 UDF JAR 中進行搜尋。 載入此類別時所需的其他任何類別也會在相同 UDF JAR 中進行搜尋,如果找不到所需類別,那麼會將搜尋委派給已實例化運行環境的類別載入器。
  2. 建立該類別的實例。
  3. 對於表格 UDF,呼叫 initState() 方法。

由於這些步驟是針對每個 create function 陳述式執行的,因此如果 Java 類別包含多個 UDF 方法(以及在 AQL 的不同 create function 陳述式中使用的所有方法),則會多次載入該類別,每次都會在個別的類別載入器中執行(步驟 1)。 接下來,將建立該類別的多個實例(步驟 2),然後對每個實例呼叫一次 initState() 方法(步驟 3)。 每個 UDF 都會產生個別類別載入器的原因,是為了容許不同的 UDF 使用相同類別(或程式庫)的不同版本。

在運行環境 (OperatorGraph.execute() API),不會重新載入 UDF 類別,因為已在擷取程式實例化期間載入該類別。 將根據需要呼叫實作 UDF 的 Java 方法,以運算輸出的各部分。 擷取程式用於單一執行緒時,這表示對於每個輸入文件,呼叫次數可能為零,也可能有很多次(並且極有可能在 Operator Graph 物件的整個生命週期中有多次呼叫)。 擷取程式在多個執行緒中共用時,不同的執行緒可能在大約相同的時間(使用不同的輸入)呼叫此方法。

如果需要對 UDF 程式碼的特定部分進行恰好一次評估(例如,為了起始設定在各個呼叫中 UDF 方法所需的資料結構),則不應該將程式碼放在 UDF 評估方法中,因為該方法極有可能在擷取程式的整個生命週期中執行多次(與 OperatorGraph 物件一樣),並且當擷取程式在多個執行緒之間共用時,可能會幾乎同時呼叫此方法。 請改為執行下列動作:

  1. 對於純量 UDF,遵循標準 Java 程式設計原則。 例如,將程式碼放在靜態區塊中。
  2. 對於表格 UDF,將程式碼放在 initState() 方法中,或者遵循標準 Java 程式設計原則。 例如,將程式碼放在靜態區塊中。

執行上述動作時,請記住,在擷取程式編譯、實例化和驗證期間,可能會多次載入該類別,如以上步驟 1-3 中所述。 如果用於起始設定 UDF 的程式碼放在靜態區塊中,則每次載入類別時(可能會多次載入)都會執行該程式碼,這會在編譯和運算子圖形實例化期間造成額外負擔。 如果額外負擔較大,請遵循以下最佳作法:

  • 為了讓編譯時期的額外負擔降到最低,最佳作法是將消耗大量編譯時間的資源(例如大型字典或起始設定時間很長的 UDF)放在個別的 AQL 模組中,並將其匯出。 嘗試僅編譯發生變更的 AQL 模組以及依賴這些模組的其他模組。
  • 為了讓運算子圖形實例化和驗證期間的額外負擔降到最低:
    1. 如果單一 UDF 方法需要起始設定碼,請將該 UDF 方法放在個別的 Java 類別中(並像之前那樣將高額外負擔實例化程式碼放在靜態起始設定程式中,或者使用可確保程式碼僅執行一次的其他某種機制)。
    2. 如果起始設定碼由多個 UDF 方法共用,則運行環境和 AQL 不會提供明確機制來確保起始設定碼恰好執行一次。 在這類狀況下,如果起始設定時間太長,則唯一的解決方案是將共用資源和起始設定碼放在系統類別路徑上。 換句話說,將起始設定碼放在新類別 MySeparateClass.java 中,並將起始設定結果儲存在此類別的靜態變數中,例如 MySeparateClass.myVar。 將 MySeparateClass.java 以及起始設定期間所需的任何資源包裝成 JAR 檔,然後將 JAR 放在系統類別路徑上。 UDF 方法可以使用 MySeparateClass.myVar 靜態變數來參照已起始設定的模型。 現在,起始設定碼只會執行一次 - 在系統類別載入器載入 MySeparateClass.java 類別時執行。

提示:

模組的編譯表示法(.tam 檔案)包含 UDF 的序列化二進位程式碼。 因此,如果兩個不同模組中的 create function 陳述式參照了相同的 UDF 程式碼,該 UDF 程式碼在這兩個模組的編譯表示法中進行序列化。 換言之,UDF 程式碼會序列化兩次。 在此類情況下,可以藉由建立充當 UDF 程式庫的個別模組來避免冗餘,然後在其他模組中重複使用該程式庫。 若要建立 UDF 程式庫,請遵循下列步驟:

  1. 建立一個模組。
  2. 將所有 UDF Jar 檔放入該模組中。
  3. 使用 create function 陳述式定義所有必要的函數。
  4. 使用 export function 陳述式將這些函數全部匯出,以便可以在其他模組中將其匯入並加以使用。

範例

範例 1:實作純量 UDF

此範例顯示了名為 toUpperCase 的純量 UDF 實作。 這個 UDF 會以類型為 Span 的值作為輸入,並輸出由輸入 Span 之文字內容組成的字串值,且轉換為大寫。

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

範例 2:實作使用表格作為輸入的純量 UDF

此範例顯示了名為 TableConsumingScalarFunc 的純量 UDF 實作。 這個 UDF 會以兩個值組清單為輸入,並輸出連接兩個輸入值組清單內容的字串值。

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

範例 3:實作使用表格作為輸入的表格 UDF

此範例顯示了名為 TableConsumingTableFunc 的表格 UDF 實作。 這個 UDF 會以兩個值組清單作為輸入,並輸出單一值組清單,其中包含第一個輸入中的值組與第二個輸入中值組的混合。 請注意,該實作從基礎類別 com.ibm.avatar.API.udf.TableUDFBase 延伸,該基礎類別提供了用於取得輸入和輸出綱目的 API。

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

}

宣告使用者定義函數

您可以使用 create function 陳述式,讓來自 PMML 檔案的使用者定義純量函數及機器學習模型可供 AQL 使用。

語法

create function 陳述式的一般語法如下所示:

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

說明

  • <function-name\>

    <function-name\> 宣告 UDF 的 AQL 名稱。 在 AQL 程式碼中使用此名稱參照 UDF。

  • <input-schema-definition\>

    指定 UDF 的輸入參數。 輸入參數具有指定為 <column-name\>的名稱,且可以是純量類型或表格定位器。 當語言為 PMML 時,該函數必須採用名為 params 的單一表格作為引數。

  • <column-name\>

    指定 UDF 的輸入或輸出中直欄的名稱。

  • <data-type\>

    UDF 輸入純量參數的類型、UDF 輸入表格的綱目中直欄的類型,或 UDF 輸出表格的綱目中直欄的類型。 <data-type\> 的可能值為 Integer、Float、String、Text、Span、Boolean 或 ScalarList。

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

    此輸入類型容許函數將給定 AQL 視圖的整個內容(對現行文件進行運算的結果)作為輸入。 locator 參數將視圖或表格作為引數參照。

  • <return-type\>

    對於純量 UDF , <return-type\> 指定 UDF 傳回的純量值類型。 傳回類型的可能值為 Integer、Float、String、Text、Span、Boolean 或 ScalarList。 如果傳回類型為 Integer,那麼實作 UDF 的 Java™ 函數會傳回類型為 Integer 的物件。 UDF 實作無法傳回初始類型 int。 如果傳回類型為 Text 或 Span,請指定從中衍生傳回類型的輸入參數。 可以使用選用性的 like 規格來指定輸入參數,因為文字段一律來自基礎直欄。 如果傳回類型為 ScalarList,請指定要從中推斷 ScalarList 中純量類型的輸入參數。 當語言為 PMML 時,該函數必須傳回表格。

  • <output-schema-definition\>

    對於表格 UDF , <output-schema-definition\> 指定 UDF 所傳回表格的輸出綱目,包括直欄名稱及其類型。

  • <ext-name\>

    external_name 指定在何處尋找 UDF 的實作。 當語言是 Java時,它是 '<jar-file-name\>:<fully-qualified-class-name\>!<method-name\>'格式的字串,由三個部分組成:

    • Jar 檔名:編譯模組化 AQL 時,UDF Jar 檔的位置參照必須相對於在其中進行參照之模組的根目錄。
    • 類別名稱:包含 UDF 實作的完整類別名稱。
    • 方法名稱:方法必須是類別的公用方法。 方法簽章必須與 create function 陳述式中指定的參數類型相符合。 運行環境元件不會執行自動類型轉換。 當語言為 PMML 時,external_name 子句會指定字串,該字串是 PMML 檔案與模組根目錄相對的位置。 現行實作支援使用 PMML 標準 4.1 版表達的模型,並使用 1.0.22 版 org.jpmml 程式庫進行評估。
  • language

    language 規格指向 UDF 的實作語言。 運行環境元件僅支援使用 Java™ 實作的 UDF。

  • deterministic/not deterministic

    選用性的 deterministic/not deterministic 指定函數是否為無狀態函數。 唯一性函數針對同一組輸入值,一律會傳回相同的值。

  • return null on null input

    選用性的 return null on null input 指定當一個以上輸入值為空值時的函數行為。 如果指定 return null on null input,則系統會對空值輸入傳回 null,而不呼叫 UDF。 如果指定了 called on null input,那麼即使輸入值為空值,也會呼叫 UDF。

使用 PMML 實作的 UDF 的用法說明

從 PMML 檔案建立的函數會以稱為 params 的單一表格作為其引數,並輸出表格。 此函數的實作會在 create function 陳述式中宣告的輸入和輸出綱目與 PMML 檔案中指定的綱目之間對映輸入欄位。 換言之,即 DataDictionary 區段(說明可以在該模型產生和使用之輸入和輸出記錄中出現的欄位名稱和類型)、MiningSchema 區段(指示在代表特徵向量的每個值組中,包含了在 DataDictionary 區段中定義的哪些命名檔案)和 Output 區段(指示在模型輸出的外部代表的每個值組中,包含了 DataDictionary 區段中定義的哪些命名欄位)。 這些函數必須為表格函數;表格中的每一列都會傳遞到 PMML 模型,並產生輸出列。

這些綱目資訊是必要的,因為 PMML 和 AQL 類型的系統並不完全相符。 例如,PMML 有多種類型可代表時間戳記,而 AQL 目前需要使用者將時間戳記編碼為字串值。 透過綱目資訊,瞭解 AQL 但不瞭解 PMML 的開發人員也可以理解 AQL 規則集。

AQL 編譯器會根據 PMML 檔案的輸入綱目來檢查輸入綱目,以確保這兩種綱目相容。 如果這兩種綱目包含同名但類型不相容的欄位,則編譯會失敗,並顯示適當的錯誤訊息。 如果函數的輸入或輸出綱目包含多餘直欄或缺少直欄,則 resulting 函數會忽略這些直欄,而不會產生錯誤。 AQL 定義和 PMML 檔案中的直欄名稱順序可能不同。 如果某個直欄名稱同時出現在輸入和輸出綱目中,但未出現在 PMML 綱目中,則該直欄的值會傳遞到函數的輸出。

範例

範例 1:使用 Java 宣告將純量值作為輸入的純量 UDF

下列範例顯示用於宣告名為 create function 之函數的 udfCombineSpans 陳述式。 該使用者定義函數會以兩個文字段作為輸入,並傳回類似於第一個輸入文字段的合併文字段。 實際 UDF Java™ 函數包裝成名為 udfs.jar 的 JAR 檔,位於 udfjars 目錄下。 實作該函數的方法為 combineSpans 類別中的 com.ibm.test.udfs.MiscScalarFunc。 如果文字段大於指定的大小,則此方法也會宣告傳回 udfSpanGreaterThantrue 函數。

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

下一個範例顯示如何宣告名為 udfCompareNames 的函數,其中為該函數提供名單 nameList 和單一名稱 myName。 輸出是類似於輸入清單的清單,該清單僅包含 nameList 中與 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;

範例 2:使用 Java 宣告將表格作為輸入的純量 UDF

下列範例說明 table as locator 輸入類型的用法。 此範例顯示用於宣告名為 MyScalarFunc 之函數的 create function 陳述式。 此 UDF 的 Java™ 實作包裝在 com.ibm.test.udfs.TableConsumingScalarFunc 類別中。

這個 UDF 會以兩個值組清單為輸入,並輸出連接兩個輸入值組清單內容的字串值。 UDF 的 Java™ 實作包含在實作使用者定義的函數中。

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

範例 3:使用 Java 宣告表格 UDF

下列範例說明 return table 子句的用法。 此範例顯示了用於宣告名為 MyScalarFunc 的表格函數的 create function 陳述式。 此 UDF 的 Java™ 實作包裝在 com.ibm.test.udfs.TableConsumingTableFunc 類別中。 此 UDF 採用兩個值組清單作為輸入,並輸出將輸入清單合併在一起的值組清單。 UDF 的 Java™ 實作包含在實作使用者定義的函數中。

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

範例 4:宣告使用 PMML 實作的表格 UDF

下列範例顯示了用於使用 PMML 語言宣告名為 IrisDecisionTree 的表格函數的 create function 陳述式。 此 UDF 的 PMML 實作指定於 IrisTree.xml 檔案中,這顯示於下列範例中。 儲存在 IrisTree.xml 中的模型是決策樹狀結構模型。

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

記錄具有註解的 create function 陳述式

create function 陳述式的 AQL Doc 註解包含下列資訊:

  • 關於函數的一般說明。
  • @param 說明,指定函數中使用的每個參數名稱。 指出參數的類型:是純量類型還是表格。 如果參數是表格,則說明表格的綱目,包括直欄名稱和直欄類型,順序為這些直欄在預期作為輸入之表格的綱目中的顯示順序。
  • @return 說明,指定函數傳回的資訊。 如果函數傳回表格,那麼指定表格的輸出綱目,包括直欄名稱和直欄類型,順序為這些直欄在輸出表格的綱目中的顯示順序。
/**
* 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;

使用使用者定義函數

使用者定義函數與 AQL 陳述式及子句搭配使用。

使用者定義純量函數與 AQL 陳述式和子句搭配使用,類似於內建函數。 具體而言,純量 UDF 可以在 selectwherehavinggroup byorder by 子句中使用,使用方式與內建純量函數(例如,GetBeginLeftContext)相同。 傳回 Boolean 類型的使用者定義純量函數可用作 wherehaving 子句的述詞。

使用者定義表格函數(表格 UDF)可以在 from 陳述式或 select 陳述式的 extract 子句中使用。

範例

範例 1:使用以 Java 實作的將純量值用作輸入的純量 UDF

此範例示範如何使用在udfCombineSpans宣告使用者定義函數udfSpanGreaterThan中宣告的 函數。

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

範例 2:使用以 Java 實作的將表格用作輸入的純量 UDF

下列範例顯示了如何使用將表格作為輸入的純量函數。 此範例說明 MyScalarFunc 表格 UDF 函數的用法,該函數的 Java™ 實作包含在實作使用者定義函數中。 它們是相同的直欄類型,但具有不同的直欄名稱。

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

範例 3:使用以 Java 實作的表格 UDF

此範例說明 MyTableFunc 表格 UDF 函數的用法,該函數的 Java™ 實作包含在實作使用者定義函數中。

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

與範例 2 類似,該範例定義了兩個視圖:FirstInputView(綱目為 (match Span))和 SecondInputView(綱目為 (spanCol Span, textCol Text))。 該範例中的最後一個視圖 TabFuncOutputtable 子句中呼叫包含這兩個輸入視圖的 from 函數 MyTableFunc。 如範例 2 中所述,只要輸入視圖與表格定位器的綱目中的直欄數和直欄類型相符合,則視圖便與函數的表格定位器引數相容。 但是,直欄名稱不必相符。

最後,select 子句將捨棄 MyTableFunc 輸出表格中的 outStr 直欄,而僅保留前兩直欄 outSpan1outSpan2

範例 4:使用以 PMML 實作的表格 UDF

此範例說明在宣告使用者定義函數的範例 4 中宣告的 IrisDecisionTree 表格 UDF 函數用法。

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