搜尋老魚筆摘(本網誌及所屬協作平台)

2010-10-25

[製圖分享] Play! Framework 1.1+架構圖(混合Scala開發模式)

『思慮熟則得事理,得事理則必成功。』- <韓非子-解老篇>

Play! Framework, http://www.playframework.org/, 是一個相當於 GRails (一個使 Groovy 語言為基的Java Web 開發框架), Play! 與 GRails 同屬 JVM 下的產物; 如果您同我一樣曾研用過 RoR(Ruby) / Django(Python), 且您又不想離開 Java, 那 Play! 會是您最好的選擇之一.

其實真正吸引我去了解 Play! Framework 最大誘因, 並不是為了理解更多雷同“敏捷開發”的 Web Framework, 這類的產品目前已是百花齊放大同小異, 不如把時間用以理解歸納它們所採用的設計模式.

Play! 最特別的一點是它可以混合 Java 與 Scala 在同一個軟體專案下共存共用, 這點也比先前我在研玩 Lift web Framework (純 Scala 語言) 更適合一個現有的專案團隊, 過激的要求團隊學習一個新語言和使用該框架, 易於讓軟體專案的風險管理估算失控. Play! 減少了這問題, 可輕易的在二者間自行調整佔用的語言比重, 更可因善用 Scala 特性提供更佳的敏捷性.

圖表:Play! Framework 1.1+架構圖(混合Scala開發模式)
(大圖!請另存後再使用~)

2010-07-19

[Scala 教學範例] 中醫學(TCM)-經絡 API

夫言人之陰陽,則外為陽,內為陰。言人身之陰陽,則背為陽,腹為陰。言人身之藏府中陰陽。則藏者為陰,府者為陽。肝心脾肺腎五藏皆為陰,膽胃大腸小腸膀胱三焦六府皆為陽。 - 黃帝內經-素問-金匱真言論篇第四

繼前篇 [Java 教學範例] Google Guava 與中醫學(TCM)-經絡 API 後, 老魚再試著用 Scala 2.8 來完成這個與中醫學(TCM)的經絡查詢器的核心 API, Scala 有著眾多的特性, 這使得除了可以擁有完整的 Java 特性與 JVM 效能外, 在撰寫程序上更有著許多先進的思維.


以 Java 為陽, 內以 Scala 為陰 ...


以這個範例來說, 為了達到該物件能成為 單例(Singleton)模式, 我們不再需要像 Java 使用靜態(Static)宣告與靜態空間的資源, Scala 能較 Java 達到真正單例模式的保證, 在前一篇中我們為了使其集合容器(Container)物件能達到 不可變性(Immutable) 以加快處理性能與 RAM, 我籍助了 Google Guava 中的不變性集合 APIs, 而在 Scala 則本身早已將這部份納為核心實作, 故不依賴任何的外部實作參考, 在本例中也使用了 函數式程式語言 的基本特性, Scala 創造了在相較同是 JVM 的 Java 所未有的眾多新特性與簡潔內容, 非常值得推篤給您學習, 或者混搭在 Java專案開發中~


深度加入老魚的 Scala 學習分享團隊與筆記本,


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package org.wisdomfish.tcm.scala

/**
 * 中醫藥學-TCMES-經絡
 * The meridian (simplified Chinese: 經絡;
 * traditional Chinese: 經絡; pinyin: jīngluò) 
 * @author WisdomFish.ORG - 郭朝益(ChaoYi, Kuo), http:://www.wisdomfish.org
 * @version 0.1 dev (SCALA 2.8)
 * @since 2010-07-19
 */

object Meritan {
 
 private val NOT_POINTS = 1
 private val IS_KEY_CNAME = 0
 private val handlefunc = (s: String) => s.split("\\s").toList
 private val Meridians = Map.newBuilder[String, List[String]] += (
   "LU" -> handlefunc("手太陰肺經 中府 雲門 天府 俠白 尺澤 孔最 列缺 經渠 太淵 魚際 少商"),
   "LI" -> handlefunc("手陽明大腸經 商陽 二間 三間 合谷 陽溪 偏歷 溫溜 下廉 上廉 手三里 曲池 肘髎 手五里 臂臑 肩髃 巨骨 天鼎 扶突 口禾髎 迎香")
   ) result
 
 def getMeridianIds: List[String] =
   Meridians.keys.toList
 def getMeridianCName(keyID: String) =
   Meridians(keyID) view(IS_KEY_CNAME)
 def getAcupuncturePointsSize(keyID: String) =
   Meridians(keyID).size - NOT_POINTS
 def getAcupuncturePoints(keyID: String) =
   Meridians(keyID) slice(NOT_POINTS, getAcupuncturePointsSize(keyID))
 def getAcupuncturePointName(keyID: String, numID: Int) =
   Meridians(keyID) view(numID)
}



老魚相關文章:

  1. [Java 教學範例] Google Guava 與中醫學(TCM)-經絡 API

2010-07-17

[Java 教學範例] Google Guava 與中醫學(TCM)-經絡 API

肝藏血,血捨魂, 肝氣虛則恐,實則怒。脾藏營,營舍意,脾氣虛則四肢不用,五藏不安;實則腹脹,經按不利。 心藏脈,脈捨神,心氣虛則悲;實則笑不休。肺藏氣,氣捨魄,肺氣虛則鼻塞不利少氣;實則喘喝, 胸盈仰息。腎藏精,精舍志,腎氣虛則厥;實則脹,五藏不安。必審五藏之病形,以知其氣之虛實, 謹而調之也。 - 黃帝內經-靈樞-本神論第八

近來老魚持續自習著中醫學, 為了讓自己在背近400多個"經絡"穴道有一個好工具, 逐著手開始撰寫了這個 API 以便在不久能與其它表現層技術相結合, 讓老魚在背頌同時有更好的"快快樂樂學經絡"的學習輔助工具~

這個範例完全使用 Google Guava API 來完成, 若您想了解它, 可以另外參考老魚的另一本學習筆記相關主題頁:
http://sites.google.com/site/javaenterpriseeditiongroup/se-in-depth/google-guava

程序執行結果圖:


範例的更新與完整說明連結:
http://iching.wisdomfish.org/tcm/tcmis/meridian

JAVA CODE   :中醫藥學-TCMES-經絡-Meridian
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
package org.wisdomfish.tcm;

import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

// Java EE 6, JSF 2.0
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;


/**
 * 中醫藥學-TCMES-經絡
 * The meridian (simplified Chinese: 經絡;
 * traditional Chinese: 經絡; pinyin: jīngluò) 
 * @author WisdomFish.ORG - 郭朝益(ChaoYi, Kuo), http:://www.wisdomfish.org
 * @version 0.1 dev
 * @since 2010-07-16
 * 
 */
@ManagedBean
@ApplicationScoped
public class Meridian {

    private final static ImmutableMap<String, ImmutableList<String>> Meridians;
    private final static int NOT_POINTS = 1;
    private final static int IS_KEY_CNAME = 0;
    private Meridian(){};
    
    static {
        Builder<String, ImmutableList<String>> init = ImmutableMap.builder();
        Meridians = init.
                put("LU", ImmutableList.copyOf(
                "手太陰肺經 中府 雲門 天府 俠白 尺澤 孔最 列缺 經渠 太淵 魚際 少商".
                split("\\s"))).
                put("LI", ImmutableList.copyOf(
                "手陽明大腸經 商陽 二間 三間 合谷 陽溪 偏歷 溫溜 下廉 上廉 手三里 曲池 肘髎 手五里 臂臑 肩髃 巨骨 天鼎 扶突 口禾髎 迎香".
                split("\\s"))).
                put("PC", ImmutableList.copyOf(
                "手厥陰心包經 天池 天泉 曲澤 隙門 間使 內關 大陵 勞宮 中沖".
                split("\\s"))).
                build();
    }
    
    /**
     * 取得經絡代碼清單
     * @return 經絡代碼清單
     */
    public static ImmutableSet<String> getMeridianIds() {
        return Meridians.keySet();
    }
    
    /**
     * 查詢指定經絡代碼之中文名稱.
     * @param keyID 經絡代碼
     * @return 經絡代碼中文名稱
     */
    public static String getMeridianName(String keyID) {
        return Meridians.get(keyID).get(IS_KEY_CNAME);
    }
   
    /**
     * 查詢指定經絡的腧穴總數值
     * @param keyID 經絡代碼
     * @return 腧穴總數數值
     */
    public static int getAcupuncturePointsSize(String keyID) {
        return Meridians.get(keyID).size() - NOT_POINTS;
    }
    
    /**
     * 取得指定經絡腧的腧穴中文名稱清單
     * @param keyID 經絡代碼
     * @return 腧穴中文名稱清單
     */
    public static ImmutableList<String> getAcupuncturePoints(String keyID) {   
        return Meridians.get(keyID).subList(NOT_POINTS, Meridians.get(keyID).size());
    }
    
    /**
     * 查詢指定經絡中特定編號的腧穴中文名稱
     * @param keyID 經絡代碼
     * @param numID 腧穴代碼
     * @return 腧穴中文名稱
     */
    public static String getAcupuncturePointName(String keyID, int numID) {
        return Meridians.get(keyID).get(numID);
    }
    
    
    
    public static void main(String[] args) {
        final String KEY_ID = "PC";
        final int NUM_ID = 5;
        long startTime = System.nanoTime()/1000000L;
//        System.out.println("經絡總清單:" + Meridians.entrySet());
        System.out.println("經絡代碼清單:" + Meridian.getMeridianIds());
        System.out.println("代碼名稱-" + KEY_ID + " = " + Meridian.getMeridianName(KEY_ID));
        System.out.println(Meridian.getMeridianName(KEY_ID) + " 腧穴總數:" + 
                Meridian.getAcupuncturePointsSize(KEY_ID) + " 穴");
        System.out.println(Meridian.getMeridianName(KEY_ID) + " 腧穴清單:" + 
                Meridian.getAcupuncturePoints(KEY_ID));        
        System.out.println(Meridian.getMeridianName(KEY_ID) + " 腧穴編號-" + KEY_ID + NUM_ID +
                " = " + Meridian.getAcupuncturePointName(KEY_ID, NUM_ID) + "穴");
        long endTime = System.nanoTime()/1000000L;
        long time = endTime - startTime;
        System.out.println("處理耗時:" + time + "ms");
    }
    
}



2010-07-06

[製圖分享] 中醫學之十二正經絡 / 論醫德《大醫精誠》

凡大醫治病,必當安神定志,無欲無求,先發大慈惻隱之心,誓願普救含靈之苦。若有疾厄來求救者,不得問其貴賤貧富,長幼妍媸,怨親善友,華夷愚智,普同一等,皆如至親之想。亦不得瞻前顧後,自慮吉凶,護惜身命,見彼苦惱,若己有之,深心淒愴,勿避險,晝夜寒暑,飢渴疲勞,一心赴救,無作功夫形跡之心。如此可為蒼生大醫。反此則是含靈巨賊。自古名賢治病,多用生命以濟危急,雖曰賤畜貴人,至於愛命,人畜一也。損彼益己,物情同患,況於人乎?夫殺生求生,去生更遠,吾今此方,所以不用生命為藥者,良由此也。
-- 千金要方 大醫精誠篇第二 唐 孫思邈

《大醫精誠》一文出自中國唐朝 孫思邈所著之《備急千金要方》第一卷,是中醫學典籍中,論述醫德的一篇極重要文獻,為習醫者所必讀。《大醫精誠》論述了有關醫德的兩個問題:
  1. 第一是 精,亦即要求醫者要有精湛的醫術,認為醫道是「至精至微之事」,習醫之人必須「博極醫源,精勤不倦」。
  2. 第二是 誠,亦即要求醫者要有高尚的品德修養,以「見彼苦惱,若己有之」感同身受的心,策發「大慈惻隱之心」,進而發願立誓「普救含靈之苦」,且不得「自逞俊快,邀射名譽」、「恃己所長,經略財物」。
如果您對該篇全文有意學習, 請見 維基文庫-備急千金要方-大醫精誠篇第二

可能是老魚讀起了中醫學典籍, 也開始背起了許多名詞和要句選, 下面這張是老魚在邊讀典籍邊整理好的圖表, 我用它來理解中醫學談的經絡關係外, 最重要的是這張內容是老魚在本週對自已嚴格要求在記憶與背誦用的範圍, 分享給同是中醫學自習者的您:
(能理解中醫之理很重要, 但若能熟記更易用於技, 熟能生巧之道.)

(點圖放大後再收藏)


2010-07-05

[雲端計算] Cassandra 應用實例[轉譯]

本篇同樣是篇老魚轉譯而來的相關系列文選, 但老魚除了校譯和排版外, 加上了個人實作過程中的理解說明混於其中, 建議您閱讀本文前, 應當俱備的知識範圍:
  1. 曾玩過 Twitter 介面操作的經驗.
  2. 對 Cassandra 的基本管理與操作能力, 已對其 Data Model 有著初級理解, 當然相關的組態配置檔的位置和編輯能力是要俱備地.
  3. 對關聯型資料庫系統開發與 E-R Model 初步的應用經驗.
  4. 對程式設計能力有熱愛的研究精神.

如果您有輿趣, 可別錯過了本篇原文網址的討論串與後續原作者的新文章. 老魚希望有心的您可以好好的閱讀它, 當然如果能配合實裝 Cassandra 與裝載本實例的教材, 您將更加瞭解它. 世上沒有完美的IT系統, 但它可使您精進學習IT甚至突破創新!老魚一慣的習性用“紅筆字”, 劃上了自己認為的閱讀重點, 供各位參考, 看完本篇如果您有興趣深入, 可以再閱讀老魚先前 Blog 所整理的相關文章(按學習順序排列):

原文: http://www.rackspacecloud.com/blog/2010/05/12/cassandra-by-example/# 
原作者:Eric Evan, http://blog.sym-link.com/
原文發佈日期:May 12, 2010
簡體中文譯者:王旭
http://wangxu.me/blog/ , @gnawux), http://wangxu.me/blog/?p=383
翻譯時間:2010年5月15,25,26日
正體中文校譯:郭朝益, http://oss-tw.blogspot.com/

[雲端計算] Cassandra 應用實例[轉譯]

近來 Cassandra 備受矚目,很多人正在評估是否可以應用 Cassandra。由於這群人有著更積極的求知速度,相對的,我們的開發專案所提供的說明文檔就顯的過於粗淺了。在這些文檔中,最不足的是為有關聯型資料庫基礎的人解釋有關 Cassandra 資料模型的部份。

Cassandra 資料模型實際和傳統的資料庫差異非常大,足夠讓人眩暈,而且很多誤解都需要修正。有些人把這個資料模型描述成存放 map 的 map,或對於 super column 的應用場景,視為是存放 map 的 map 的 map。這些解釋經常用類似 JSON 標記的視覺輔助展示方法來進行佐證。其他人則把列族(column family, cf)看做是係數表,還有人把 column family 看作是存放列物件的集合容器。甚至有人有時把列(column)看成是三元組。我覺得所有這些解釋都不夠好。

問題在於很難去用推類比擬的手法來確切解釋一個新的東西,而且如果比較的不準確的話常常把人搞糊塗。我仍然期望有人能解釋清楚這個資料模型,但同時我覺得確切的例子可能更容易說明白一些。

Twitter


儘管 Twitter 本身就是 Cassandra 的一個實際的應用場景,它仍然是一個不錯的教學實例,因為它眾所周知而且易於抽象。在例子中,和很多網站一樣,每個使用者都有一份使用者資料(顯示名稱、密碼、email等),這些資訊鏈接到朋友(譯註:使用者 follow 的人)和 follower(譯註:follow使用者的人)。此外,如果沒有那些短 tweets 的話也就不是 twitter 了,tweet 每條 140 個字符,它們都關聯著諸如時間戳記和唯一的 id 等諸如此的元資料,這個 id 我們可以從 URL 裡看到。

現在我們在一個關聯資料庫裡來直接進行建模,我們首先需要一個表來存放使用者。
CREATE TABLE user (
    id INTEGER PRIMARY KEY,
    username VARCHAR(64),
    password VARCHAR(64)
);

我們還需要兩張表來存儲一對多的 follow 關聯。
CREATE TABLE followers (
    user INTEGER REFERENCES user(id),
    follower INTEGER REFERENCES user(id)
);
 
CREATE TABLE following (
    user INTEGER REFERENCES user(id),
    followed INTEGER REFERENCES user(id)
);

顯然,我們還需要表來存儲 tweets。
CREATE TABLE tweets (
    id INTEGER,
    user INTEGER REFERENCES user(id),
    body VARCHAR(140),
    timestamp TIMESTAMP
);
由於僅僅是個例子,我已經極大簡化了情況,但僅僅是這個極度簡化的模型,也還有很多需要做的工作。例如,要以可行的方法達到資料歸一化就需要一個外部鍵(FK)值的約束限制,而因為我們需要從多張表 join 資訊,我們需要對任意值建索引,以保證其高效。

但是讓一個分散式系統正常工作相當有挑戰性,幾乎不可能不做任何折衷。對 Cassandra 來說也是如此,而且這也是為什麼上述資料模型對我們來說是無法工作的的原因。對於入門者,沒有可供參考的完整性,缺乏次索引使得 join 很難進行,所以,你必須反歸一化。另一方面,你被迫思考你要進行的查詢的方式和期望結果,因為這差不多就是資料模型看起來的樣子。

Twissandra


那麼如何把上述模型翻譯到 Cassandra 中呢?十分幸運,我們只需要看看 Twissandra,這是 Eric Florenzano 寫的一個 Twitter 的簡化版克隆版,來作為例子。那麼讓我們來使用 Twitter 和 Twissandra 作為例子來看看 Cassandra 的資料模型是如何地。

程式範例下載(Git, Python 要求)
git clone git://github.com/ericflo/twissandra.git

Schema (架構網要)

Cassandra 是一種無 schema 的資料存儲方式,但為你的應用做一些特定的組態配置還是必的。Twissandra 給出了一個可以工作的 Cassandra 組態配置,不過研究一下關於資料模型方面的組態配置還是物超所值的。
Keyspaces (鍵值空間)
Keyspaces 是 Cassandra 中最頂層的命名空間。在未來版本的 Cassandra 中,將可以動態創建 keyspace,正如在 RDBMS 中創建資料庫一樣,但是對於 0.6 和以前的版本,這些都在主要組態配置檔中定義,如:

 <Keyspaces>
  <Keyspace Name="Twissandra">
  ...
  Keyspace>
Keyspaces>




Column Families, CF (列族)
對於每個 keyspace,都可以有一個或多個列族(column family, cf)。column family 是用於關聯類型相近的記錄的命名空間。Cassandra 在寫入作業時,在一個 column family 內部允許有記錄(record)級的原子性,對它們進行查詢非常高效。這些特性十分重要,在進行你的資料建模前必須記牢,其它細節我們會在下面討論到。和 keyspace 類似,列族也在主要組態配置文件中定義,雖然在將來的版本中你將可以在系統運行期間就可創建列族,正像在RDBMS 中創建資料表一樣。

<Keyspaces>
  <Keyspace Name="Twissandra">
    <ColumnFamily CompareWith="UTF8Type"  Name="User"/>
    <ColumnFamily CompareWith="BytesType" Name="Username"/>
    <ColumnFamily CompareWith="BytesType" Name="Friends"/>
    <ColumnFamily CompareWith="BytesType" Name="Followers"/>
    <ColumnFamily CompareWith="UTF8Type"  Name="Tweet"/>
    <ColumnFamily CompareWith="LongType"  Name="Userline"/>
    <ColumnFamily CompareWith="LongType"  Name="Timeline"/>
  Keyspace>
Keyspaces>

需要指出的是,上面的組態配置片段中,指定名字的時候同時指定了一個比較者類型。這凸顯了 Cassandra 和傳統資料庫的又一個重大不同,記錄按照設計的順序存儲,在之後不能輕易改變。
這些列族(CF)都是什麼?
一下子看到所有的七個 Twissandra 列族(column family, cf)是做何用途地可能不那麼直觀,所以,我們來逐個仔細看一下:
  • User
    • User 用於儲存使用者資訊,大致相當於本文最上面描述的使用者資料表。cf 中的每條記錄以UUID 為鍵(key)值,並且包含使用者名稱和密碼列。
  • Username
    • 在 User 列族中查詢一個使用者需要知道使用者的鍵值,但從使用者名稱怎麼找到這個 UUID 鍵值呢?在上面描述的 SQL 關聯式資料庫裡的話,我們就在 User 表裡來一個匹配使用者名的SELECT 語句(WHERE username = 'jericevans')就行了。但這對於 Cassandra 來說卻不可能。
    • 首先,關聯式資料庫可以順序地掃瞄全表來進行這樣一個 SELECT,但由於記錄是基於鍵值分佈在 Cassandra 叢集中的,這個匹配將可能會在多個節點上進行,可能是很多節點。而且,即使是資料就在一個節點上,仍然有一個原因會讓這一作業遠沒有關聯式資料庫效率高,因為關聯式資料庫可以對 username 列有索引(index)。前面提到過,Cassandra 在當前是不支持第二索引的。
    • 解決方案就是:建立一個我們自己的反向索引,進行使用者名稱到 UUID 鍵值的映射,這就是Username CF 的用途。
  • Friends
  • Followers
    • Friends 和 Follower CF 可以回答這些問題:使用者X follow 了哪些人? 誰 follow 了使用者X? 這兩個 CF 的鍵值都是這個唯一的使用者 ID,其中包含了哪些有 follow 關聯的使用者以及它們創建的時間。
  • Tweet
    • Tweet CF 用於存放所有的 tweets。這個列族以每個 tweet 的 UUID 為鍵值,還包含了使用者id,tweet 內容以及 tweet 時間等有關的列。
  • Userline
    • 這是屬於每個使用者的時間軸線。記錄的鍵值是使用者的 ID,其他的列中,包含有一個數字時間戳記到 Tweet CF 中的 tweet ID 的映射(map)。
  • Timeline
    • 最後,Timeline CF 類似於 Userline,只是這裡存儲著每個使用者的朋友的 tweet 的時間軸線視圖(View)。
有了上面這些 CF,現在我們可以來看一些常用的作業都是如何發生的。

把這些列族(CF)放在一起來試一下

添加一個新使用者
首先,新使用者需要一個方法來註冊一個帳戶,當他們註冊的時候,組要將他們增加到 Cassandra 資料庫中去。對於 Twissandra,我們來看看裡面的內容:(Client 實作以 Python - Pycassa 為例)

username = 'jericevans'
password = '**********'
useruuid = str(uuid())
 
columns = {'id': useruuid, 'username': username, 'password': password}
 
USER.insert(useruuid, columns)
USERNAME.insert(username, {'id': useruuid})

Twissandra 是用 Python 寫成的,使用 Pycassa 作為存取 Cassandra 的客戶端,上述大寫的 USER 和 USERNAME 是 pycassa.ColumnFamily 的實例,它們需要在使用之前的某個位置被分別初始化。

這裡說明一下,這不是從 Twissandra 裡原樣摘出來的。我讓他們更加簡單而且是自包含的。比如,在上面的例子中,如果沒有對使用者名和密碼的賦值的話,可能不那麼好理解,不過一個 web 應用只能從使用者註冊表單裡得到這些內容。

從這個例子中回來,有兩個不同的 Cassandra 寫入作業“insert( )”,第一個創建了一個使用者 CF,另一個更新了使用者名到使用者 UUID 鍵值的反向映射(map)表。在兩個例子中,參數都是用於查找記錄的鍵值,以及包含列名和值的 map。
Following 一個朋友
frienduuid = 'a4a70900-24e1-11df-8924-001ff3591711'
 
FRIENDS.insert(useruuid, {frienduuid: time.time()})
FOLLOWERS.insert(frienduuid, {useruuid: time.time()})

這裡我們再來兩個不同的 insert() 作業,這次是加入一個使用者到我們的朋友列表,並加入反向關聯:給被 follow 使用者增加一個 follower。
發出 Tweet
tweetuuid = str(uuid())
body = '@ericflo thanks for Twissandra, it helps!'
timestamp = long(time.time() * 1e6)
 
columns = {'id': tweetuuid, 'user_id': useruuid, 'body': body, '_ts': timestamp}
TWEET.insert(tweetuuid, columns)
 
columns = {struct.pack('>d'), timestamp: tweetuuid}
USERLINE.insert(useruuid, columns)
 
TIMELINE.insert(useruuid, columns)
for otheruuid in FOLLOWERS.get(useruuid, 5000):
    TIMELINE.insert(otheruuid, columns)

要存儲一條新的 tweet,我們需要使用一個新的 UUID 作為鍵值,在 Tweet 列族創建一個記錄,其中的列包含作者的使用者 ID,創建的時間,當然還有 tweet 的文本內容本身。

此外,使用者的 Userline 中也要加入 tweet 的時間和它的 id。如果這是使用者的第一條 tweet 的話,這個insert() 會產生一條新的紀錄,後面的只是為這條記錄增加新列。

最後要給發出 tweet 的使用者和其他 follower 的 timeline 列族添加這條 tweet 的 ID 和時間。

值得注意的一件事是,這裡,時間戳使用的是 64位元長整型變數,而當它成為一個列的名字的時候,它會被包裝為網絡位元組序的二進制值。這是因為 Userline 和 Timeline CF 使用了一個 LongType Comparator,允許我們使用數值區間指定查找指定範圍,所以它們被按照數值來存放起來。
接收一個使用者的 tweets
timeline = USERLINE.get(useruuid, column_reversed=True)
tweets = TWEET.multiget(timeline.values())

接收一個使用者的 tweet,首先從 Userline 獲取tweet ID 的一個列表,然後從 Tweet CF 通過 multiget()方法來讀取這些 tweet。得到的結果將是通過著數值表示的時間戳記逆序排列的,因為 Userline 使用了LongTyper comparator,並且 reversed 設置為了 True。
獲取一個使用者的時間線
start = request.GET.get('start')
limit = NUM_PER_PAGE
 
timeline = TIMELINE.get(useruuid, column_start=start,
column_count=limit, column_reversed=True)
tweets = TWEET.multiget(timeline.values())

和上一個例子類似,這次是從 Timeline 讀取 tweet ID,不過這次我們還使用了 start 和 limit 來控制讀取列的範圍。這樣有助於輸出結果的分頁。

那麼,下一步呢?

希望這篇足夠提供給你一個大致的概念。重複一下,我從程式碼中提取了一些例子,為了簡明起見,在撰寫本文時略去了一些作業,所以現在你可能是 check out 出 Twissandra 的原始碼並進行下一步深入研究的好時機了。有很多功能,諸如 retweet 和 lists,都還空著沒有實作,你可以作為一個練習的起點。如果你已經熟悉 Python 和 Django 的話,那你可以考慮實作一下這些方法。

Cassandra 的 wiki 包含了大量的資訊,而且還在不斷增多,還包括一個即時更新的眾人貢獻的 文章與投影片 的列表。

如果你喜歡 IRC 的話,你可以加入 irc.freenode.net 的 #cassandra 頻道,來和來自全球對 Cassandra 社群者們聊聯天,他們總是熱衷於提供協助和回答詢問的問題。如果你更青睞 email 的話,cassandra-user 郵件列表上也有很多可以提供協助的人。

熱門文章

大智若魚::人生處處是道場-站內SEO參考標籤雲