😒

[PynamoDB]ValueError:'range_key_condition'must be an instance of ...

2023/07/01に公開

はじめに


PynamoDBは、ORM(定義したデータモデルをデータベースと同期させる仕組み)のようにデータモデルをプログラムから操作することができます。
あと、比較的実装が楽だったboto3のリソースインタフェースを使っての実装も、AWS Python SDK(boto3)のリソース・インターフェースが改修凍結されましたとのことなので、boto3のクライアントインタフェースで実装してみたのですが、「型指定」等実装しにくさを感じました。
そんなことからPynamoDBを使ってみることにしました。
テーブルモデル定義から、アイテムの作成、アイテムの削除はサンプルコード通りすんなりと実装できたのですが、PynamoDBのQuery時キー指定方法が分からず、以下のエラーが発生してしまっていました。
エラー解消し、クエリもできるようになったので備忘として残します。

ダメなパターン1

class SampleModel(Model):
    class Meta:
        table_name = "sample"
        region = 'ap-northeast-1'
    userid = UnicodeAttribute(hash_key=True)
    todoid = UnicodeAttribute(range_key=True)
####
def query_sample(usrid,todoid)
    for item in SampleModel.query(userid,todoid):
class SampleModel(Model):
    class Meta:
        table_name = "sample"
        region = 'ap-northeast-1'
    userid = UnicodeAttribute(hash_key=True)
    todoid = UnicodeAttribute(range_key=True)
####
def query_sample(usrid,todoid)
    for item in SampleModel.query(userid, SampleModel.todoid.startswith('2')):

うーん。
https://pynamodb.readthedocs.io/en/latest/quickstart.html#querying
このあたりを見て書いているのだけど。

  • エラーログ
[ERROR] ValueError: 'range_key_condition' must be an instance of Condition
  • トレース
Traceback (most recent call last):
・・・
  File "/var/task/pynamodb/connection/base.py", line 1404, in _check_condition
    raise ValueError("'
{}
' must be an instance of Condition".format(name))
  • 該当ソース
PynamoDB/pynamodb/connection/base.py
def _check_condition(self, name, condition):
    if condition is not None:
        if not isinstance(condition, Condition):
            raise ValueError("'{}' must be an instance of Condition".format(name))

うーん。

OKパターン

色々試したのですが、Python pynamodb.models.Model() Examplesの#11を参考に実装してみたところrangeキーで絞り込まれたitemの取得ができました。

class SampleModel(Model):
    class Meta:
        table_name = "sample"
        region = 'ap-northeast-1'
    userid = UnicodeAttribute(hash_key=True)
    todoid = UnicodeAttribute(range_key=True)
####
def query_sample(usrid,todoid)
    for item in SampleModel.query(userid, range_key_condition=(SampleModel.todoid == todoid)):

まとめ

Condition Expressionsを使って条件指定が可能です。
pynamodbはboto3のラッパーライブラリなだけあって、簡単に使えるのですが、サンプルコードがあまり見当たらないので細かいことやろうと思うとしっかりとドキュメント呼んで使う必要がありそうですね。早く使いこなせるようになりたいものです。

参考

Discussion