Friday, February 8, 2019

從 SQL 到 Datomic query (datalog)

要理解新的概念,一般而言,用舊的、已經熟悉概念來加以連結新的概念,會是比較容易的方法。另一方面,要讓人們去接受新的解決方案,先確定舊的問題都可以在新的解法中解決,也是有效增加人們信心的作法。

當我使用 SQL 來開發 web application 時,最常用的 SQL query 是什麼呢? 其實未必是複雜的 join operation 。最常用的,反而是樸實無華的查看單一或是多個 rows:
(1) SELECT * FROM A
(2) SELECT * FROM A WHERE A.col = b

那麼,這麼簡單的 SQL query ,如果是在 Datomic 的世界,又是怎麼對應呢?我在 datomic 官方的 mbrainz-sample 找出的一段 query 。用了之後,覺得非常容易可以對應上述的兩種情境。sample code  在下方
舉例來說明:
如果有一個「使用者」的概念,要用資料庫加以建模。使用者有電子郵件、密碼、名字三種屬性。同時,我們需要一個資料庫查詢 (query) ,可以根據電子郵件來查出對應的使用者

1. 用 RDB 來建模的話,這個 sql query 會長成這樣子:
SELECT * FROM user WHERE user.email = "ecoboy@qwerty.com";

2. 用 Datomic 來建模的話,一旦利用上述的 utility functions ,這個 query 就可以用下列的函數產生。
(find-by db :user/email "ecoboy@qwerty.com")

附註:
(a) 在 SQL best practices 裡,因為要考慮效率,往往不建議用 select * 這種 query 直接放在 production code 裡。
(b) 在 Datomic  best practices 裡,因為 datomic 的 query 並不需要往返 client-server ,同時 Entity 有 lazy evaluation 的特性,一般而言,推荐的作法是直接取回 Entity ,相當於 SQL 裡的 row 概念。