2016-12-30

Azure DocumentDB - Part 8 (LINQ to DocumentDB SQL)

LINQ(Language Integrated Query) 是微軟引進的創新技術,用來處理物件與資料的對應,讓資料查詢也可以擁有型別檢查及 IntelliSense。開發時可以使用一套語法,經由不同 provider 實際產生出不同查詢執行命令。因為其便利性讓許多 .Net 開發人員愛不釋手。LINQ to DocumentDB SQL 讓開發人員可以用熟悉的方式來查詢 DocumentDB ,大大降低進入門檻。


LINQ to DocumentDB SQL 架構

  • 官方架構圖

  1. LINQ 語法 --> IQueryable 物件
  2. IQueryable 物件 --> DocumentDB Query Provider 轉譯 --> DocumentDB SQL
  3. DocumentDB SQL --> 查詢 DocumentDB Server --> 取得
  4. JOSN 結果 --> JOSN 反列化 --> .NET Object

.NET 與 JSON 的對應

  • JOSN 的 Key --> .NET field 名稱
  • JSON 的 Value --> .NET field 值

LINQ 至 SQL 轉譯

  • 支援基本類型:

    1. 數值類型
    2. boolean
    3. string
    4. null
  • 支援的純量運算式

    類型 說明
    常數值 基本資料類型的常數值。
    屬性/陣列索引運算式 運算式參照物件或陣列項目的屬性。
    算術運算式 包括數值和布林值的一般算術運算式。
    字串比較運算式 比較字串值與某個常數字串值。
    物件/陣列建立運算式 運算式傳回複合值類型或匿名類型的物件,或是這類物件的陣列。這些值可以是巢狀值。
  • 支援的 LINQ 運算子清單

    LINQ 運算子 說明 LINQ Lambda sql
    Select 會轉譯為有建構物件的 SQL SELECT input.Select(f => f.parents[0].familyName); SELECT VALUE root["parents"][0]["firstName"] FROM root
    Where 會轉譯為 SQL WHERE,並支援 &&、|| 和 ! 到 SQL 運算子之間的轉譯 input.Where(f => f.LastName == "Andersen") SELECT * FROM root WHERE (root["lastName"] = "Andersen")
    SelectMany 可讓陣列回溯到 SQL JOIN 子句。可用來鏈結/巢串運算式來篩選陣列元素 input.SelectMany(f => f.Children); SELECT VALUE tmp FROM root JOIN tmp IN root["children"]
    OrderBy 和 OrderByDescending 以遞增/遞減順序轉譯為 ORDER BY ASC/DESC input.OrderBy(f => f.Children[0].Grade) SELECT * FROM root ORDER BY root["children"][0]["grade"] ASC
    CompareTo 轉譯為範圍比較。通常用於字串,因為字串在 .NET 中是無法比較的 input.Where(f => f.LastName.CompareTo("Andersen") == 0) SELECT * FROM root WHERE (root["lastName"] = "Andersen")
    Take 轉譯為 SQL TOP input.Take(1) SELECT TOP 1 * FROM root
    數學函數 支援從 .NET 的 Abs、Acos、Asin、Atan、Ceiling、Cos、Exp、Floor、Log、Log10、Pow、Round、Sign、Sin、Sqrt、Tan、Truncate 轉譯為對應的 SQL 內建函式。 input.Select(f => Math.Log(f.Children[0].Grade)) SELECT VALUE LOG(root["children"][0]["grade"]) FROM root
    字串函數 支援從 .NET 的 Concat、Contains、EndsWith、IndexOf、Count、ToLower、TrimStart、Replace、Reverse、TrimEnd、StartsWith、SubString、ToUpper 轉譯為對應的 SQL 內建函式。 input.Select(f => f.LastName.ToLower()); SELECT VALUE LOWER(root["lastName"]) FROM root
    陣列函數 支援從 .NET 的 Concat、Contains 和 Count 轉譯為對應的 SQL 內建函式。 input.Select(f => f.Children.Length); SELECT VALUE ARRAY_LENGTH(root["children"]) FROM root
    地理空間擴充函數 支援從虛設常式方法 Distance、Within、IsValid 及 IsValidDetailed 轉譯為對應的 SQL 內建函式。 input.Select(f => f.Location.IsValid()); SELECT VALUE ST_IsValid(root["location"]) FROM root
    使用者定義函式的擴充函數 支援從 stub metohd UserDefinedFunctionProvider.Invoke 轉譯為對應的使用者定義函式。 這個我試不出來,只能硬用 client.CreateDocumentQuery<dynamic>(UriFactory.CreateDocumentCollectionUri(databaseId, collectionId), string.Format("SELECT f.address.city, udf.seaLevelUdf(f.address.city) AS seaLevel FROM Families f")); SELECT f.address.city, udf.seaLevelUdf(f.address.city) AS seaLevel FROM Families f
    其他 支援聯合和條件式運算子的轉譯。可根據內容將 Contains 轉譯為字串 CONTAINS、ARRAY_CONTAINS 或 SQL IN。 沒想到什麼例子 -

參考資料

  1. LINQ 到 DocumentDB SQL
  2. DocumentDB .NET 範例
  3. 使用 DocumentDB 指令碼總管建立和執行預存程序、觸發程序和使用者定義函式

沒有留言:

張貼留言