読者です 読者をやめる 読者になる 読者になる

dackdive's blog

新米webエンジニアによる技術ブログ。JavaScript(React), Salesforce, Python など

follow us in feedly

Google App Engine Python Tutorialのメモ(3)

Google App Engine Python

前々回前回に続いて第3回。

(追記)その他のメモ

Chapter 6 Using the Datastore

  • GAEのデータストアはHigh Replication Datastore(HRD)と呼ばれ、Paxos algorithmというアルゴリズムを採用している(らしい)

データストアはキーバリューストア(KVS)で、その中で使われるキー(key)とかエンティティ(entity)という用語は
以下に示すようにRDBMSと比較すると理解しやすい。
(表はこちらの動画(公式)から引用。また、こちらの記事も参考になります)

Datastore RDBMS
Category of object Kind Table
One entry/object Entity Row
Unique identifier of data entry Key Primary Key
Individual data Property Field
  • エンティティは他のエンティティを親とした親子関係を持つことができる。親(または親の親、親の親の...)をancestors、子(または子の子、子の子の...)はdescendantsと呼ぶ。

  • その他、エンティティグループの話がつらつらと書かれているっぽいけどいったん読み飛ばす

  • エンティティグループとトランザクションについてはこちらの記事がわかりやすい(記事で扱っているサンプルコードはJava

Google App Engine ~ エンティティグループとトランザクション | R-Labs

コード

長いので分けて書く

Storing the Submitted Greetings

モデル定義部分

class Greeting(ndb.Model):
    """Models an individual Guestbook entry."""
    author = ndb.UserProperty()
    content = ndb.StringProperty(indexed=False)
    date = ndb.DateTimeProperty(auto_now_add=True)

indexを作成したくない場合は明示的に(indexed=False)を書く。
これは、クエリに使用しないプロパティなどに用いる。

データストアへの保存処理

class Guestbook(webapp2.RequestHandler):
    def post(self):
        # We set the same parent key on the 'Greeting' to ensure each Greeting
        # is in the same entity group. Queries across the single entity group
        # will be consistent. However, the write rate to a single entity group
        # should be limited to ~1/second.
        guestbook_name = self.request.get('guestbook_name',
                                          DEFAULT_GUESTBOOK_NAME)
        greeting = Greeting(parent=guestbook_key(guestbook_name))

        if users.get_current_user():
            greeting.author = users.get_current_user()

        greeting.content = self.request.get('content')
        greeting.put()

        query_params = {'guestbook_name': guestbook_name}
        self.redirect('/?' + urllib.urlencode(query_params))

guestbook_nameをparent keyとしてGreetingをデータストアに格納 (正確には、クエリパラメータ(URLの?guestbook_name=xxxで渡された文字列)を引数として
guestbook_keyメソッドを呼び出し、Keyクラスを生成。
そのKeyオブジェクトをparent keyとしている)

There's no need to create the Guestbook entity before setting it to be the parent of another entity.

GuestbookというエンティティはGreetingの親として利用されているんだけども、
Guestbookは他のエンティティの親としてセットされるまで作成する必要はない。

In this example, the parent is used as a placeholder for transaction and consistency purposes.

この例では、親は単にトランザクションと一貫性(consistensy, ACID属性とかで出てくるやつ?)のためのプレースホルダーとして利用されている。
より詳細な情報はTransactionsのページへ。

Retrieving Submitted Greetings

データの取得

greetings_query = Greeting.query(
    ancestor=guestbook_key(guestbook_name)).order(-Greeting.date)
greetings = greetings_query.fetch(10)

..., data is queried one of two ways: Either via Datastore queries, or using an SQL-like query language called GQL. To access the full range of Datastore query capabilities, we recommend using Datastore queries over GQL.

データのクエリ方法にはDatastore queriesGQLの2種類がある。
データストアクエリ(として提供されている)機能をフル活用するためには、Datastore queriesをおすすめする。

インデックスについて

Every query in the App Engine Datastore is computed from one or more indexes—tables that map ordered property values to entity keys. This is how App Engine is able to serve results quickly regardless of the size of your application's Datastore.

すべてのクエリはインデックスindexesをもとに計算される。インデックスはソート済みの特定のプロパティとキーによるテーブルである(合ってる?)。
完全な推測ですが、アプリケーション内で使用するすべてのクエリについてインデックステーブルを作成しておくので、
結果としてGAEのデータストアのパフォーマンスはデータの量によらないってことなのかな。

Many queries can be computed from the builtin indexes, but for queries that are more complex the Datastore requires a custom index. Without a custom index, the Datastore can't execute these queries efficiently.

複雑なクエリはカスタムインデックスを作成する必要があるよ、とのこと。

For example, our guest book application above filters by guestbook and orders by date, using an ancestor query and a sort order. This requires a custom index to be specified in your application's index.yaml file. You can edit this file manually or, as noted in the warning box earlier on this page, you can take care of it automatically by running the queries in your application locally. Once the index is defined in index.yaml, uploading your application will also upload your custom index information.

例として、今回のアプリケーションではguestbookによるフィルタとdateによるソートを行っている。
で、この場合もカスタムインデックスを作成する必要があり、それはindex.yamlというファイルに記述されている。

indexes:
- kind: Greeting
  ancestor: yes
  properties:
  - name: date
    direction: desc

これは手動で記述することもできるけど、ローカルでアプリを実行すると自動的に記述される。

以上ここまで。
データストアは仕組みを完全に理解しようとすると大変そう。