AWS Lambdaのpythonで複数テーブル引いてきて検索するやつ作った

ちょっと融通の利く検索システムがほしかったので作成、
無謀にもpython3.6で挑戦、ここを参考にスタートしたのはいいものの
初心者の上あほなので調べながらやってたのでここまでで1週間位かかっている。


DynamoDBのテーブル構造は以下の通りです。
テーブル1のKEYで検索した結果を使ってテーブル2のPKを特定し
そして検索結果をJSONで返すというやつです。
テーブル1でカテゴリから商品コードを引いてきて、その商品コードと
Webから受け取ったパラメータで検索を行って検索結果を一覧で
表示するとかいう内容を想定しています。こうしておけば
VALUEの部分が可変でも対応できるので柔軟かなぁと考えてのことです。

テーブル1:
----------------------------------
KEY,VALUE
----------------------------------
テーブル2:
----------------------------------
VALUE[n],SEARCHKEY,VALUE
----------------------------------
※VALUE[n]はテーブル1のVALUEです。

イメージとしては[KEY]→テーブル1からVALUE取得
[VALUE[n]]+[SEARCHKEY]→テーブル2からVALUE取得


LambdaはWebのエディタで作るという無謀感が半端ない。メンテナンス性とか全く考慮なし。本当はこういうのでやるべきですが、使い方が分かりません。
どなたか親切な方、教えてください。
でお約束のソース共有

import logging
import json
import os
import re

import boto3
from boto3.dynamodb.conditions import Key

class InternalFunctionError(Exception):
  def __init__(self, code, messages):
      self.code = code
      self.messages = messages
  def __str__(self):
      exobj = {
          'error': {
              'code': self.code,
              'messages': self.messages
          }
      }
      return json.dumps(exobj)


def get_code(id,keyname,tablename):
  try:
      dynamodb = boto3.resource('dynamodb')
      table    = dynamodb.Table(tablename)
      response = table.get_item(
              Key={
                   keyname:id
              }
          )
      return response['Item']
  except Exception as e:
    LOGGER.error(traceback.format_exc())
    raise InternalFunctionError(
          500,[{'message': 'InternalServerError'}]  
    )


def get_item_val(id1,id2,key1,key2,tablename):
  try:
      dynamodb = boto3.resource('dynamodb')
      table    = dynamodb.Table(tablename)
      response = table.query(
        KeyConditionExpression=Key(key1).eq(id1) & Key(key2).eq(id2)
        )
      return response['Items']
  except Exception as e:
    LOGGER.error(traceback.format_exc())
    raise InternalFunctionError(
          500,[{'message': 'InternalServerError'}]  
    )

def lambda_handler(event, context):
  try:
    sk = '1010'
    ct = '4'
    t1 = os.getenv('TABLE_NAME1')
    k1 = os.getenv('KEY_NAME1')
    t2 = os.getenv('TABLE_NAME2')
    k21 = os.getenv('KEY_NAME21')
    k22 = os.getenv('KEY_NAME22')

    item = get_code(ct,k1,t1)
    result=[]
    for i_key,i_val in item.items():
      m = re.match(k1,i_key)
      if (m is None):
        item_content = get_item_val(i_val,sk,k21,k22,t2)
        if(len(item_content) is not 0):
          s=item_content[0]
          result.append(s)
    return result
  except Exception as e:
    LOGGER.error(traceback.format_exc())
    raise InternalFunctionError(
          500,[{'message': 'InternalServerError'}]  
    )


相変わらずエラー処理はザルみたいな感じで不安が残る。APIGateWayで500エラー
返したかったんでここ参考にソース少し修正したのとAPIGateway設定しました。
これだからダメなんですがな、とりあえずはskの部分とctのところはAPIGateWayから
値を受けて可変にさせる想定です。辞書型とLambdaが返してくるのがリストになっていてそこから値を取り出してまたリストに放り込むところが悩んだ悩んだ。

pythonってインデントでSyntaxチェックしたりで結構癖が強いですが
コード自体は初心者が書いても結構シンプルに読みやすくなるのでいいかも
しれないです。とりあえずSAMとかはきちんと勉強した方がいいカモなぁ

コメント

Otazoman さんの投稿…
ログを取っておきたかったので改修版をアップ
インサートはあっさりできるな。

import boto3
import json
import os
import re
from boto3.dynamodb.conditions import Key
import datetime
import time
import random


dynamodb = boto3.resource('dynamodb')

def insert_log(category,searchkey,logtablename):
try:
cd = datetime.datetime.now()
#KEY生成
t = time.time()
r=random.randint(1,10)
tkey = str(t) + str(r)

#print(createdate)

table = dynamodb.Table(logtablename)
response = table.put_item(
Item = {
'key-id': tkey,
'category': category,
'search-key':searchkey,
'createdate':str(cd)
}
)
return
except Exception as e:
print(e)
raise e

def get_code(id,keyname,tablename):
try:
table = dynamodb.Table(tablename)
response = table.get_item(
Key={
keyname:id
}
)
return response['Item']
except Exception as e:
print(e)
raise e

def get_item_val(id1,id2,key1,key2,tablename):
try:
table = dynamodb.Table(tablename)
response = table.query(
KeyConditionExpression=Key(key1).eq(id1) & Key(key2).eq(id2)
)
return response['Items']
except Exception as e:
print(e)
raise e

def lambda_handler(event, context):
try:
sk = '1010' #商品検索条件
ct = '4' #商品カテゴリ
t1 = os.getenv('TABLE_NAME1')
k1 = os.getenv('KEY_NAME1')
t2 = os.getenv('TABLE_NAME2')
k21 = os.getenv('KEY_NAME21')
k22 = os.getenv('KEY_NAME22')
lt = os.getenv('LOG_TABLE')

#検索条件をログレコードに書込み
putlog = insert_log(sk,ct,lt)

#商品コードを取得して検索結果を取得する
item = get_code(ct,k1,t1)
result=[]
for i_key,i_val in item.items():
m = re.match(k1,i_key)
if (m is None):
#商品コード+検索キーで検索
item_content = get_item_val(i_val,sk,k21,k22,t2)
if(len(item_content) is not 0):
#print(item_content)
s=item_content[0]
result.append(s)
return result
except Exception as e:
print(e)
raise e
nikkolayebba さんの投稿…
このコメントはブログの管理者によって削除されました。
moshrabbi121 さんの投稿…
このコメントはブログの管理者によって削除されました。

このブログの人気の投稿

証券外務員1種勉強(計算式暗記用メモ)

GASでGoogleDriveのサブフォルダとファイル一覧を出力する

マクロ経済学(IS-LM分析)