[Cassandra] 要如何透過python與CQL來新增User Define Type欄位的資料
Cassandra是一個強大的nosql(在特定集群下資料的throughput可是mongo db的10幾倍),我只知道將其發揚光大的facebook,其歷史淵源我也不知多少,就先在此略過
nosql強調的是資料寫入、查詢的效能,但是為了突顯其效能,nosql有其內部的運作方式,因此有些使用上的特性必須去滿足他或是盡量要照著他的查詢規則,例如…cql的語法裡面,你的where條件必須一定要有partition key,而且還要照順序作條件,下update語法時,更新的條件,你一定要包含partition key,也只能使用=運算子,無法像sql那樣,批次大量地去異動資料(如果有錯,歡迎糾正),而且不是關鍵式資料庫特性,不需要正規化的那麼全面,甚至就是橫向的長下去也沒關系…但是若當資料格式是有1對多關系的時候,我仍然希望能存入到nosql的時候怎麼辦呢?
例如:
訂單order下,可能有很多的order item(購買項目),訂單匯總了金額,購買者,運送地址,購買項目關聯了訂單,並描述商品編號,商品數量,以往在RDB裡面,我們可能會設計2張表,然後透過join與transaction的方式來維護相關的資料。先舉個例子:我隨便設計一個產品明細類,然後再加入一個主表,我希望欄位就有1對多的產品明細關係,因此我訂了一個欄位叫order_items,然後型別就是list加上剛剛訂的order_product_item
以這樣的一張表有4個欄位,但是有明細與地址的進階型別,我們要如何新增呢?
若透過cql,只需要寫的像cql,並帶入json like的資料結構,就可以新增到我們的CustomerOrder的表了
查詢結果:
注意,欄位裡面可不是string,而是有指定型別的結構,因此是可以作為後續查詢的條件。在這邊為止…先切入今天希望記錄的主題,就是如何透過python來綁定這種user define type。在傳統sql與程式寫transaction sql時,我們常常會這樣寫
insert into a (fieldA, fieldB) Values(@fieldA, @fieldB)
然後帶入paramter的方式,來防止sql injection與型別判斷,而cql呢…他也可以做到類似這樣的寫法:
insert into a (fieldA, fieldB) Values(:fieldA, :fieldB)
insert into a (fieldA, fieldB) Values(?, ?)
然後定義一個字典物件,一併丟給cassandra的driver:session去執行,就可以如我們以前在sql常看到的參數binding一樣,去執行語法並新增
parameter = dict( fieldA=fieldA_Value, fieldBcreator=fieldB_Value)
然而若是user define type的話,如何解呢?list物件,應該就是對應到python的list,應該沒問題,那其他的欄位,有辦法對應下一層dictionary嗎? 試了老半天都是卡關…但是不確定是卡在動態參數binding那段,還是字典裡型別的問題 後來發現了關鍵的官網文件在此:https://datastax.github.io/python-driver/user_defined_types.html 擷圖如下 什麼!!竟然可以直接繼承object物件,然後定義一個初始化方法,指定所有user define type的名稱(帶入的型別由外面檢查) 就可以做到?!我一開始還想試另一條路(有空再說吧…),繼承cassandra usertype型別,使用它的orm方式來做,但是看起來用那個方法無法綁cql一起運作,他有他的獨立運作方式。
看了他的試範讓我馬上試著建立類別,並如上圖的方式,直接帶parameter定義的欄位,以我們訂單的例子:
下指令的方式已經像使用sql一樣簡單,而透過上述user define type的定義與python的程式操作可以更靈活的使用cassandra這個強大nosql的特性囉。只是回頭看看自己…捚頭苦幹…這個議題n小時,真的有點吃力不討好,在此紀念我今天try error浪費的光陰,不如官方文件看仔細一點…
ps: Word Press有沒有什麼可以插入code可以用很好的樣式來呈現的外掛呀…改天來研究一下…(先試試這個pastacode…相容於php7)