Azure 串流分析中的 JavaScript 使用者定義函式

Azure 串流分析支援以 JavaScript 撰寫的使用者定義函式。 JavaScript 提供豐富的 StringRegExpMathArrayDate 方法,可讓使用串流分析作業建立複雜的資料轉換變得更容易。

概觀

JavaScript 使用者定義的函式支援無狀態且只做為計算用途的純量函式,而且不需要外部連線能力。 函數的傳回值只能是純量 (單一) 值。 將 JavaScript 使用者定義函式新增至作業之後,您可以在查詢中的任何位置使用函式,就像是內建的純量函式。

從以下的一些案例可以看出 JavaScript 使用者定義函式很實用:

  • 剖析及操作具有規則運算式函式的字串,例如:Regexp_Replace()Regexp_Extract()
  • 解碼和編碼資料,例如:從二進位轉換成十六進位
  • 使用 JavaScript Math 函式進行數學運算
  • 進行陣列作業,例如,排序、連結、尋找及填入

以下是一些在串流分析中無法使用 JavaScript 使用者定義函式達成的事項:

  • 呼叫外部 REST 端點,例如,進行反向 IP 查詢或從外部來源提取參考資料
  • 對輸入/輸出執行自訂事件格式序列化或還原序列化
  • 建立自訂彙總

雖然沒有在函式定義中封鎖 Date.GetDate()Math.random() 等函式,您仍應避免使用這些函式。 這些函式不會在每次呼叫時都傳回同樣的結果,且「串流分析」服務不會記錄函式叫用和傳回值的日誌。 若函式針對同樣事件傳回不同的值,則當您或串流分析重新啟動某項作業之後,將不保證其具有可重覆性。

將 JavaScript 使用者定義函式新增至作業

注意

下列步驟適用於設定為在雲端執行的 Stream Analytics 作業。 如果您的串流分析作業設定為在 Azure IoT Edge 上執行,請改為使用 Visual Studio 並使用C# 撰寫使用者定義的函式

若要在串流分析作業中建立 JavaScript 使用者定義的函式,請選取 [作業拓撲] 底下的 [函式]。 然後,從 [+新增] 下拉式功能表中選取 [JavaScript UDF]

Add JavaScript UDF

您接著必須提供下列屬性,然後選取 [儲存]

屬性 說明
函式別名 輸入名稱以在查詢中叫用函式。
輸出類型 會由 JavaScript 使用者定義函式傳回給串流分析查詢的類型。
函式定義 可實作會在每次從查詢中叫用 UDF 時執行的 JavaScript 函式。

針對 JavaScript UDF 進行測試和疑難排解

您可以在任何瀏覽器中測試和偵錯 JavaScript UDF 邏輯。 串流分析入口網站目前不支援對這類使用者定義函數的邏輯進行偵錯和測試。 函數如預期般運作後,即可將函數新增至串流分析工作 (如上所述),然後直接從查詢加以叫用。 您可以使用適用於 Visual Studio 的串流分析工具來以 JavaScript UDF 測試查詢邏輯。

JavaScript 執行階段錯誤會被視為嚴重問題,並顯示在活動記錄。 若要擷取記錄檔,在 Azure 入口網站中,請移至您的作業並選取 [活動記錄]

在查詢中呼叫 JavaScript 使用者定義函式

在查詢中使用前面加上 udf 的函式別名,即可輕易地叫用 JavaScript 函式。 以下舉例說明一個會在串流分析查詢中叫用的 JavaScript UDF,其會將十六進位值轉換為整數。

    SELECT
        time,
        UDF.hex2Int(offset) AS IntOffset
    INTO
        output
    FROM
        InputStream

支援的 JavaScript 物件

Azure 串流分析 JavaScript 使用者定義函式支援標準的內建 JavaScript 物件。 如需這些物件的清單,請參閱全域物件

串流分析與 JavaScript 類型轉換

串流分析查詢語言與 JavaScript 支援的類型有一些差異。 此表列出兩者之間的轉換對應:

串流分析 JavaScript
bigint Number (JavaScript 只能準確地表示最高到 2^53 的整數)
Datetime Date (JavaScript 只支援毫秒)
double 數字
nvarchar(MAX) String
錄製 Object
陣列 陣列
NULL Null

以下是 JavaScript 至串流分析的轉換:

JavaScript 串流分析
數字 Bigint (若數字為整數且介於 long.MinValue 和 long.MaxValue 之間,否則為 double)
Date Datetime
String nvarchar(MAX)
Object 錄製
陣列 陣列
Null、Undefined NULL
任何其他類型 (例如,函式或錯誤) 不支援 (產生執行階段錯誤)

JavaScript 語言需區分大小寫,且 JavaScript 程式碼中物件欄位的大小寫必須符合內送資料中欄位的大小寫。 相容性層級 1.0 的作業會將 SQL SELECT 陳述式欄位轉換成小寫。 若是相容性層級 1.1 和以上,SELECT 陳述式的欄位會與 SQL 查詢中所指定的大小寫相同。

其他 JavaScript 使用者定義函式模式

將巢狀 JSON 寫入至輸出

如果您的後續處理步驟使用串流分析作業輸出做為輸入,且其需要 JSON 格式,您可以將 JSON 字串寫入至輸出。 以下範例會呼叫 JSON.stringify() 函式以包裝所有輸入的名稱/值對,並將它們以單一字串值於輸出中寫入。

JavaScript 使用者定義函式定義:

function main(x) {
return JSON.stringify(x);
}

範例查詢︰

SELECT
    DataString,
    DataValue,
    HexValue,
    UDF.jsonstringify(input) As InputEvent
INTO
    output
FROM
    input PARTITION BY PARTITIONID

將字串轉換成 JSON 物件以供處理

如果您有 JSON 字串欄位,而且想要將其轉換成 JSON 物件,以便在 JavaScript UDF 中進行處理,您可以使用 JSON.parse() 函式來建立可供使用的 JSON 物件。

JavaScript 使用者定義函式定義:

function main(x) {
var person = JSON.parse(x);  
return person.name;
}

範例查詢︰

SELECT
    UDF.getName(input) AS Name
INTO
    output
FROM
    input

使用 try/catch 進行錯誤處理

Try/catch 區塊可協助您識別傳遞至 JavaScript UDF 中的輸入資料格式不正確的問題。

JavaScript 使用者定義函式定義:

function main(input, x) {
    var obj = null;

    try{
        obj = JSON.parse(x);
    }catch(error){
        throw input;
    }
    
    return obj.Value;
}

樣本查詢:將整個記錄當作第一個參數來傳遞,以便能在發生錯誤時傳回。

SELECT
    A.context.company AS Company,
    udf.getValue(A, A.context.value) as Value
INTO
    output
FROM
    input A

toLocaleString()

JavaScript 中的 toLocaleString 方法可以用來傳回區分語言的字串,其代表呼叫此方法的日期時間資料。 雖然 Azure 串流分析只接受 UTC 日期時間作為系統時間戳記,但此方法可以用來將系統時間戳記轉換成另一個地區設定和時區。 此方法遵循的實作行為會與 Internet Explorer 中提供的行為相同。

JavaScript 使用者定義函式定義:

function main(datetime){
    const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
    return datetime.toLocaleDateString('de-DE', options);
}

樣本查詢:傳遞日期時間作為輸入值

SELECT
    udf.toLocaleString(input.datetime) as localeString
INTO
    output
FROM
    input

此查詢的輸出將會是 de-DE 的輸入日期時間,並且包含選項。

Samstag, 28. Dezember 2019

使用者記錄

當作業正在執行時,記錄機制可讓使用者擷取自訂資訊。 記錄資料可用來即時偵錯或評估自訂程式碼的正確性。 此機制可透過三種不同的方法取得。

Console.Info()

Console.Info 方法可用來記錄程式碼執行期間的一般資訊。 此方法會記錄資料,而不會中斷計算。 記錄的訊息將會標示為事件層級資訊。

console.info('my info message');

Console.Warn()

Console.Warn 方法可用來記錄可能不正確或預期但仍接受計算的資料。 此方法不會中斷計算,且會在傳回方法之後繼續執行。 記錄的訊息將會標示為事件層級警告。

console.warn('my warning message');

Console.Error() 和 Console.Log()

Console.Error 方法僅用於記錄無法繼續執行程式碼的錯誤案例。 這個方法會擲回例外狀況,並提供錯誤資訊作為輸入參數,而作業將會停止執行。 記錄的錯誤訊息將會標示為事件層級錯誤。

console.error('my error message');

您可以透過 診斷記錄存取記錄訊息。

atob() 和 btoa()

btoa() 方法可用來將 ASCII 字串編碼為 Base64。 這通常是為了以二進位格式傳輸資料。 atob() 方法可用來將 Base64 編碼的資料字串解碼為 ASCII 字串格式。

var myAsciiString = 'ascii string';
var encodedString = btoa(myAsciiString);
var decodedString = atob(encodedString);

下一步