2009年6月18日 星期四

資料計數器

Datastore API 的限制


在使用 Datastore API 時有個限制,就是每作一次 query ,最多能存取到的資料數量為 1000 筆(註1),也因為這個限制,所以也不能直接使用 Query 物件下的 count() 方法來計算資料數量。

舉例來說,如果要設計一個網路商店,每一件商品是一個 Product entity,假如網站中的商品數量超過 1000 筆,那這樣的程式碼:
from google.appengine.ext import db

class Product(db.Model):
...
# product 各欄位

...
query = Product.all()
number_of_products = query.count()

並不會幫你統計出究竟有多少 Product entity,因為 query 的結果最多就是 1000 筆資料。

手動記錄


為了解決這樣的問題,其實可以自己定義一個「計數器」的資料,用來統計究竟有多少資料,於是立刻可以寫出這樣的 data model:
from google.appengine.ext import db

class Counter(db.Model):
count = db.IntegerProperty(required=True, default=0)

有了這樣的資料模型,便能夠用來統計網站中任何資料的數量。我們可以經由不同的 key_name 來區分出不同的計數器,根據上述的例子,便可以在新增 Product 時,在計數器上加1以便統計。
# 新增 product 的程式片段...
...
p = Product(........) # 新增 product entity
p.put()

# 根據 key_name 取得 counter
counter = Counter.get_by_key_name('product_counter')
if counter is None:
# 如果 counter 不存在,則建立一個新的,別忘了指定 key_name
counter = Counter(key_name='product_counter')

counter.count += 1
counter.put()

以此類推,當要刪除一個或多個 Product entities 時,也要同步更新對應的計數器資料,以保持資料數量的一致性(consistency)。



  1. 之後會介紹如何讀出超過1000筆的資料

2 則留言:

  1. 您好,看你的文章真是讓我獲益良多。我在做這類計數器時通常都是設定一個 name 的屬性,然後用 query 的方式來取得紀錄,沒試過用 get_by_key_name 的方式,感覺上這樣應該會比 query 來的快一些,不知道你有沒有作過相關的比較?
    另外,因為計數器常常會被取出來使用,因此我會把它佈置在 memcache 中,對此你有沒有相關的最佳實踐?

    回覆刪除
  2. @shian
    用 get_by_key_name 一定會比 query 來得快,不過我沒有針對此特別做實驗所以此刻無法提供您比較數據 ^^"

    而 memcache 的搭配..我已經打算在之後的文章寫了,在這裡被您小小地破了梗 XD

    回覆刪除