使用數據流對應數據
重要
此頁面包含使用 Kubernetes 部署指令清單來管理 Azure IoT Operations 元件的指示,其處於預覽狀態。 這項功能隨附 數個限制,不應用於生產工作負載。
請參閱 Microsoft Azure 預覽版增補使用規定,以了解適用於 Azure 功能 (搶鮮版 (Beta)、預覽版,或尚未正式發行的版本) 的法律條款。
使用資料流程對應語言,以在 Azure IoT 操作中轉換資料。 語法是一種簡單但功能強大的方式,可用來定義將資料從一種格式轉換成另一種格式的對應。 本文提供資料流程對應語言和重要概念的概觀。
對應可讓您將資料從一種格式轉換成另一種格式。 請考慮下列輸入記錄:
{
"Name": "Grace Owens",
"Place of birth": "London, TX",
"Birth Date": "19840202",
"Start Date": "20180812",
"Position": "Analyst",
"Office": "Kent, WA"
}
與輸出記錄比較:
{
"Employee": {
"Name": "Grace Owens",
"Date of Birth": "19840202"
},
"Employment": {
"Start Date": "20180812",
"Position": "Analyst, Kent, WA",
"Base Salary": 78000
}
}
在輸出記錄中,輸入記錄資料會有下列變更:
- 欄位已重新命名:欄位
Birth Date
現在是Date of Birth
。 - 已重新建構的欄位:
Name
和Date of Birth
都會分組在新的Employee
類別之下。 - 欄位已刪除:
Place of birth
因為欄位不存在於輸出中,所以會移除該欄位。 - 新增欄位:欄位
Base Salary
是類別中的Employment
新欄位。 - 域值已變更或合併:
Position
輸出中的欄位會Position
結合輸入中的 和Office
欄位。
轉換是透過 對應來達成,這通常牽涉到:
- 輸入定義:識別所使用的輸入記錄中的欄位。
- 輸出定義:指定輸入欄位在輸出記錄中組織的位置和方式。
- 轉換 (選用):修改輸入欄位以符合輸出欄位。
expression
當多個輸入欄位合併成單一輸出欄位時,是必要的。
下列對應是範例:
{
inputs: [
'BirthDate'
]
output: 'Employee.DateOfBirth'
}
{
inputs: [
'Position' // - - - - $1
'Office' // - - - - $2
]
output: 'Employment.Position'
expression: '$1 + ", " + $2'
}
{
inputs: [
'$context(position).BaseSalary'
]
output: 'Employment.BaseSalary'
}
對應範例:
- 一對一對應:
BirthDate
直接對應至Employee.DateOfBirth
而不轉換。 - 多對一對應:將
Position
和Office
合併成單一Employment.Position
欄位。 轉換公式 ($1 + ", " + $2
) 會將這些欄位合併成格式化字串。 - 關係型數據:
BaseSalary
會從名為position
的內容數據集新增。
欄位參考
欄位參考示範如何使用點表示法,或 Employee.DateOfBirth
透過 $context(position)
存取內容數據集中的數據,來指定輸入和輸出中的路徑。
MQTT 和 Kafka 元數據屬性
當您使用 MQTT 或 Kafka 作為來源或目的地時,您可以在對應語言中存取各種元資料屬性。 這些屬性可以在輸入或輸出中對應。
中繼資料屬性
- 主題:適用於 MQTT 和 Kafka。 其中包含發佈訊息的字串。 範例:
$metadata.topic
。 - 用戶屬性:在 MQTT 中,這是指 MQTT 訊息可以攜帶的自由格式索引鍵/值組。 例如,如果 MQTT 訊息是以索引鍵 「priority」 和 value 「high」 的使用者屬性發行,則參考會
$metadata.user_property.priority
保留 「high」 值。 使用者屬性索引鍵可以是任意字串,而且可能需要逸出:$metadata.user_property."weird key"
使用索引鍵「奇怪的索引鍵」(具有空格)。 - 系統屬性:這個詞彙用於不是用戶屬性的每個屬性。 目前僅支援單一系統屬性:
$metadata.system_property.content_type
,它會讀取 MQTT 訊息的內容類型屬性(如果設定的話)。 - 標頭:這是與 MQTT 用戶屬性相等的 Kafka。 Kafka 可以使用索引鍵的任何二進位值,但數據流僅支援 UTF-8 字串索引鍵。 範例:
$metadata.header.priority
。 這項功能類似於用戶屬性。
對應元數據屬性
輸入對應
在下列範例中,MQTT topic
屬性會對應至 origin_topic
輸出中的欄位:
inputs: [
'$metadata.topic'
]
output: 'origin_topic'
如果 MQTT 訊息中有使用者屬性 priority
,下列範例示範如何將它對應至輸出字段:
inputs: [
'$metadata.user_property.priority'
]
output: 'priority'
輸出對應
您也可以將元資料屬性對應至輸出標頭或使用者屬性。 在下列範例中,MQTT topic
會對應至 origin_topic
輸出使用者屬性中的 欄位:
inputs: [
'$metadata.topic'
]
output: '$metadata.user_property.origin_topic'
如果傳入承載包含 priority
欄位,下列範例示範如何將它對應至 MQTT 使用者屬性:
inputs: [
'priority'
]
output: '$metadata.user_property.priority'
Kafka 的相同範例:
inputs: [
'priority'
]
output: '$metadata.header.priority'
內容化資料集選取器
這些選取器允許對應從外部資料庫整合額外的數據,這些資料庫稱為 內容化數據集。
記錄篩選
記錄篩選牽涉到設定條件,用以選取應該處理或捨棄哪些記錄。
點表示法
點表示法在計算機科學中廣泛使用,以參考欄位,甚至遞歸方式。 在程式設計中,欄位名稱通常由字母和數字組成。 標準點表示法範例看起來可能像下列範例:
inputs: [
'Person.Address.Street.Number'
]
在數據流中,點表示法描述的路徑可能包含字串和某些特殊字元,而不需要逸出:
inputs: [
'Person.Date of Birth'
]
在其他情況下,需要逸出:
inputs: [
'Person."Tag.10".Value'
]
上述範例,以及其他特殊字元,包含功能變數名稱內的點。 若不逸出,功能變數名稱會做為點表示法本身的分隔符。
雖然資料流程會剖析路徑,但只會將兩個字元視為特殊字元:
- 點 (
.
) 作為欄位分隔符。 - 單引號,放在線段的開頭或結尾時,會啟動逸出區段,其中點不會被視為欄位分隔符。
任何其他字元都會被視為欄位名稱的一部分。 這種彈性適合用於 JSON 等格式,其中欄位名稱可以是任意字串。
在 Bicep 中,所有字串都會以單引弧括住 ('
)。 適用於 Kubernetes 之 YAML 中適當引用的範例不適用。
逸出
在點記號路徑中逸出的主要函式,是配合使用屬於欄位名稱的點,而不是分隔符號:
inputs: [
'Payload."Tag.10".Value'
]
在這裡範例中,路徑包含三個區段: Payload
、 Tag.10
和 Value
。
以點表示法逸出規則
個別逸出每個區段: 如果多個區段包含點,則必須以雙引號括住這些區段。 其他區段也可以加上引號,但不會影響路徑解譯:
inputs: [ 'Payload."Tag.10".Measurements."Vibration.$12".Value' ]
正確使用雙引號: 雙引號必須開啟並關閉逸出區段。 區段中間的任何引號都會被視為功能變數名稱的一部分:
inputs: [ 'Payload.He said: "Hello", and waved' ]
這個範例會定義兩個字段: Payload
和 He said: "Hello", and waved
。 當點出現在這些情況下時,它會繼續做為分隔符:
inputs: [
'Payload.He said: "No. It is done"'
]
在此情況下,路徑會分割成區段 Payload
、He said: "No
和 It is done"
(從空格開始)。
分割演算法
- 如果區段的第一個字元是引號,剖析器會搜尋下一個引號。 以這些引號括住的字串會視為單一區段。
- 如果區段不是以引號開頭,剖析器會搜尋下一個點或路徑結尾來識別區段。
萬用字元
在許多情況下,輸出記錄與輸入記錄非常類似,只需要稍微修改即可。 當您處理包含許多欄位的記錄時,手動指定每個欄位的對應可能會變得乏味。 萬用字元可藉由允許自動套用至多個欄位的一般化對應來簡化此流程。
我們來考慮一個基本案例,了解在對應中使用星號的方式:
inputs: [
'*'
]
output: '*'
此組態會顯示基本對應,其中輸入中的每個欄位都會直接對應至輸出中的相同欄位,而不會有任何變更。 星號 (*
) 作為符合輸入記錄中任何欄位的通配符。
以下是星號 (*
) 在此內容中運作的方式:
- 模式比對:星號可以比對路徑的單一區段或多個區段。 可以作為路徑中任何區段的預留位置。
- 欄位比對:在對應過程中,演算法會根據 中指定的模式,評估輸入記錄中的每個
inputs
欄位。 上一個範例中的星號會比對所有可能的路徑,有效地調整輸入中的每個個別欄位。 - 擷取的區段:星號符合的路徑部分稱為
captured segment
。 - 輸出對應:在輸出組態中,
captured segment
會放置星號出現的位置。 這表示輸入的結構會保留在輸出中,captured segment
會填入星號所提供的預留位置。
另一個範例說明如何使用萬用字元來比對子區段,並且一併移動。 此範例會有效地扁平化 JSON 物件內的巢狀結構。
原始 JSON:
{
"ColorProperties": {
"Hue": "blue",
"Saturation": "90%",
"Brightness": "50%",
"Opacity": "0.8"
},
"TextureProperties": {
"type": "fabric",
"SurfaceFeel": "soft",
"SurfaceAppearance": "matte",
"Pattern": "knitted"
}
}
使用通配符的對應組態:
{
inputs: [
'ColorProperties.*'
]
output: '*'
}
{
inputs: [
'TextureProperties.*'
]
output: '*'
}
產生的 JSON:
{
"Hue": "blue",
"Saturation": "90%",
"Brightness": "50%",
"Opacity": "0.8",
"type": "fabric",
"SurfaceFeel": "soft",
"SurfaceAppearance": "matte",
"Pattern": "knitted"
}
萬用字元放置
當您放置通配符時,必須遵循下列規則:
- 每個資料參考的單一星號: 單一資料參考中只允許一個星號 (
*
) 。 - 完整區段比對: 星號必須一律符合路徑的整個區段。 不能只用來比對區段的一部分,例如
path1.partial*.path3
。 - 定位: 星號可以放置在數據參考的各個部分:
- 開頭:
*.path2.path3
- 在這裡,星號會比對任何通往 的path2.path3
區段。 - 中間:
path1.*.path3
- 在此組態中,星號會比對 和path3
之間的path1
任何區段。 - 結尾:
path1.path2.*
- 結尾的星號會比對之後path1.path2
的任何區段。
- 開頭:
- 包含星號的路徑必須以單引號 (
'
) 括住。
多重輸入萬用字元
原始 JSON:
{
"Saturation": {
"Max": 0.42,
"Min": 0.67,
},
"Brightness": {
"Max": 0.78,
"Min": 0.93,
},
"Opacity": {
"Max": 0.88,
"Min": 0.91,
}
}
使用通配符的對應組態:
inputs: [
'*.Max' // - $1
'*.Min' // - $2
]
output: 'ColorProperties.*'
expression: '($1 + $2) / 2'
產生的 JSON:
{
"ColorProperties" : {
"Saturation": 0.54,
"Brightness": 0.85,
"Opacity": 0.89
}
}
如果您使用多重輸入通配符,星號 (*
) 在每個輸入中必須一致地表示相同 Captured Segment
。 例如,當 *
在模式 *.Max
中擷取 Saturation
時,對應演算法會預期對應的 Saturation.Min
與模式 *.Min
相符。 在此處,*
會由第一個輸入中的 Captured Segment
取代,引導後續輸入的比對。
請考慮此詳細範例:
原始 JSON:
{
"Saturation": {
"Max": 0.42,
"Min": 0.67,
"Mid": {
"Avg": 0.51,
"Mean": 0.56
}
},
"Brightness": {
"Max": 0.78,
"Min": 0.93,
"Mid": {
"Avg": 0.81,
"Mean": 0.82
}
},
"Opacity": {
"Max": 0.88,
"Min": 0.91,
"Mid": {
"Avg": 0.89,
"Mean": 0.89
}
}
}
使用通配符的初始對應群組態:
inputs: [
'*.Max' // - $1
'*.Min' // - $2
'*.Avg' // - $3
'*.Mean' // - $4
]
此初始對應會嘗試建置陣列(例如, 例如 Opacity
: [0.88, 0.91, 0.89, 0.89]
。 此組態失敗,因為:
- 第一個輸入
*.Max
會擷取區段,例如Saturation
。 - 對應預期後續輸入會出現在相同的層級:
Saturation.Max
Saturation.Min
Saturation.Avg
Saturation.Mean
由於 Avg
和 Mean
是巢狀在 內 Mid
,所以初始對應中的星號無法正確擷取這些路徑。
修正的對應設定:
inputs: [
'*.Max' // - $1
'*.Min' // - $2
'*.Mid.Avg' // - $3
'*.Mid.Mean' // - $4
]
此修訂后的對應會準確地擷取必要的欄位。 它會正確指定包含巢狀 Mid
對象的路徑,以確保星號可在 JSON 結構的不同層級上有效運作。
第二個規則與特製化
當您使用來自多輸入通配符的上一個範例時,請考慮下列對應,為每個屬性產生兩個衍生值:
{
inputs: [
'*.Max' // - $1
'*.Min' // - $2
]
output: 'ColorProperties.*.Avg'
expression: '($1 + $2) / 2'
}
{
inputs: [
'*.Max' // - $1
'*.Min' // - $2
]
output: 'ColorProperties.*.Diff'
expression: '$1 - $2'
}
此對應旨在針對 ColorProperties
底下的每個屬性,建立兩個不同的計算 (Avg
和 Diff
)。 此範例顯示結果:
{
"ColorProperties": {
"Saturation": {
"Avg": 0.54,
"Diff": 0.25
},
"Brightness": {
"Avg": 0.85,
"Diff": 0.15
},
"Opacity": {
"Avg": 0.89,
"Diff": 0.03
}
}
}
在此處,相同輸入上的第二個對應定義會做為對應的第二個規則。
現在,請考慮特定欄位需要不同計算的案例:
{
inputs: [
'*.Max' // - $1
'*.Min' // - $2
]
output: 'ColorProperties.*'
expression: '($1 + $2) / 2'
}
{
inputs: [
'Opacity.Max' // - $1
'Opacity.Min' // - $2
]
output: 'ColorProperties.OpacityAdjusted'
expression: '($1 + $2 + 1.32) / 2'
}
在此情況下,Opacity
欄位具有唯一的計算。 處理此重疊案例的兩個選項如下:
- 包含
Opacity
的兩個對應。 由於此範例中的輸出欄位不同,因此不會彼此覆寫。 - 針對
Opacity
使用更具體的規則,並移除較廣泛的規則。
請考慮相同欄位的特殊案例,以協助決定正確的動作:
{
inputs: [
'*.Max' // - $1
'*.Min' // - $2
]
output: 'ColorProperties.*'
expression: '($1 + $2) / 2'
}
{
inputs: [
'Opacity.Max' // - $1
'Opacity.Min' // - $2
]
output: ''
}
第二個定義中的空白 output
欄位表示不會在輸出記錄中寫入欄位 (有效地移除 Opacity
)。 此設定比較像是 Specialization
,而非 Second Rule
。
資料流程重疊對應的解決方式:
- 評估會從對應定義中的最上層規則進行。
- 如果新的對應解析為與上一個規則相同的欄位,則適用下列條件:
- 系統會根據萬用字元擷取的區段數目,針對每個解析的輸入計算
Rank
。 例如,如果Captured Segments
是Properties.Opacity
,則Rank
為 2。 如果只是Opacity
,則Rank
為 1。 不含萬用字元的對應具有 0 的Rank
。 - 如果後者規則的
Rank
等於或高於上一個規則,資料流程會將其視為Second Rule
。 - 否則,資料流會將組態
Specialization
視為 。
- 系統會根據萬用字元擷取的區段數目,針對每個解析的輸入計算
例如,將和 Opacity.Min
導向Opacity.Max
至空輸出的對應值為 Rank
0。 因為第二個規則的下 Rank
限低於上一個規則,所以它會被視為特製化並覆寫先前的規則,這會計算的值 Opacity
。
內容化資料集中的萬用字元
現在,讓我們看看如何透過範例搭配通配符使用內容化數據集。 請考慮名為 position
的資料集,其中包含下列記錄:
{
"Position": "Analyst",
"BaseSalary": 70000,
"WorkingHours": "Regular"
}
在先前的範例中,我們使用了此資料集的特定欄位:
inputs: [
'$context(position).BaseSalary'
]
output: 'Employment.BaseSalary'
此對應會 BaseSalary
直接從 Employment
內容數據集複製到輸出記錄的 區段。 如果您想要將程式自動化,並將資料集Employment
中的所有欄位position
包含在 區段中,您可以使用通配符:
inputs: [
'$context(position).*'
]
output: 'Employment.*'
此設定允許動態對應,其中 position
資料集內的每個欄位都會複製到輸出記錄的 Employment
區段:
{
"Employment": {
"Position": "Analyst",
"BaseSalary": 70000,
"WorkingHours": "Regular"
}
}
上一個已知的值
您可以追蹤屬性的最後一個已知值。 將輸入欄位 ? $last
後綴為 ,以擷取字段的最後一個已知值。 當屬性遺漏後續輸入承載中的值時,最後一個已知值會對應至輸出承載。
例如,請考慮下列對應:
inputs: [
'Temperature ? $last'
]
output: 'Thermostat.Temperature'
在此範例中,會追蹤 的最後一個已知值 Temperature
。 如果後續的輸入承載不包含值,則會在輸出中使用最後一個 Temperature
已知值。