Operators 聯想篇:RxJS

前言

這幾天看到另一個問題:”看得懂官方文件,但是不知道怎麼用(Operators)。
當然最好的辦法就是找一堆案例來說明,讓大家很容易理解與體會,這種重責大任當然不會落在筆者身上,畢竟使用過的 Operators 一隻手就數得出來,所以腦筋就動到資料處理的老大哥 SQL 身上,40年的演化讓它成為一個非常成熟的技術,查詢的能力當然是首屈一指。

SQL 語法處理順序

下面是一個非常常見的 SQL 查詢語法,透過產品主檔與訂單明細來查詢訂購數量大於10個的產品折扣前後的價格。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SELECT 
Name AS ProductName,
NonDiscountSales = (OrderDetail.OrderQty * Product.UnitPrice),
Discounts = ((OrderDetail.OrderQty * Product.UnitPrice) * Product.UnitPriceDiscount)
FROM
Product
JOIN
OrderDetail
ON
Product.ProductID = OrderDetail.ProductID
WHERE
OrderDetail.OrderQty > 10
ORDER BY
ProductName;

接著我們開始思考資料庫對於這段與法式如何執行的。

FROM

我們要處理”某個資料”當然首先要知道它的資料來源在哪,這邊是指 產品主檔(Product) 這個資料表。

1
2
3
FROM 
Product

對 RxJS 來說資料來源就是 Observable,可能是外部提供或者是由我們自己建立(create、from、of)。
img

JOIN

接著有可能需要整合其他資料,這邊加入了 訂單明細(OrderDetail) 這個資料表。

1
2
3
4
JOIN 
OrderDetail
ON
Product.ProductID = OrderDetail.ProductID

對 RxJS 來說資料來源就是 merge、concat 系列語法來合併資料(Observable)。

WHERE

接下來就是篩選資料,這邊只要列出詢訂購數量大於10個的產品。

1
2
3
WHERE
OrderDetail.OrderQty > 10

對 RxJS 來說就是利用 filter 來篩選資料(Observable)。

SELECT

接下來就是轉換資料,將原始資料轉換成我們所需要的格式,這邊透過計算特定欄位列出了產品名稱與對應的售價與折扣價。

1
2
3
4
5
SELECT 
Name AS ProductName,
NonDiscountSales = (OrderDetail.OrderQty * Product.UnitPrice),
Discounts = ((OrderDetail.OrderQty * Product.UnitPrice) * Product.UnitPriceDiscount)

對 RxJS 來說可以利用 map 來轉換輸出的資料。

其他

first、last、skip、take 這一系列 Operators 會與 SQL TOP 語法相近。
distinct 當然與 SQL 的 DISTINCT 一樣負責篩選掉重複的資料。
還有一些運算類型的,例如 count、max、min,其實也與 SQL 雷同。

後記

其他的 Operators 我們可以透過彈珠圖來思考它的功能比較像 SQL 語法的哪一個類型,看不懂的就先跳過吧!因為既然無法理解那現階段你也不會想要使用它。  
對於會 SQL 的人來說,其實透過 SQL 語法的觀念來思考要使用那些 Operators 應該是不錯的模式,因為除了容易聯想,這種邏輯順序的可讀性也較容易讓別人理解其用意,雖然不能解決所有的情境,但是對於大部分的需求來說應該都可以套用,當然可能會有效能問題,不過”優化“應該是等上手再去思考。