1

AdWordsアカウントとローカルデータベースをSqlalchemyで同期するスクリプトを書いています。Adwords APIのオブジェクト階層をたどっているので、最初のテーブルは「キャンペーン」で、2番目のテーブルは「アドグループ」です。

これが私が2つを定義する方法です:

class Campaign(Base):

__tablename__ = 'aw_campaigns'

id = Column(Integer, primary_key=True)
name = Column(String(99))
impressions = Column(Integer)
serving_status = Column(String(99))
start_date = Column(String(99))
status = Column(String(99))

def __init__(self, id, name, impressions, serving_status, start_date, status):
    self.id = id
    self.name = name
    self.impressions = impressions
    self.serving_status = serving_status
    self.start_date = start_date
    self.status = status

class Adgroup(Base):

__tablename__ = 'aw_adgroups'

id = Column(Integer, primary_key=True)  # , primary_key=True
name = Column(String(99))
camp_id = Column(Integer, ForeignKey('aw_campaigns.id'))  # , ForeignKey('aw_campaigns.id')
camp_name = Column(String(99))
ctr = Column(Float)
cost = Column(Float)
impressions = Column(Integer)
clicks = Column(Integer)
status = Column(String(99))

def __init__(self, id, name, camp_id, camp_name, ctr, cost, impressions, clicks, status):
    self.id = id
    self.name = name
    self.camp_id = camp_id
    self.camp_name = camp_name
    self.ctr = ctr
    self.cost = cost
    self.impressions = impressions
    self.clicks = clicks
    self.status = status

APIをクエリしてから、Adgroupテーブルの行のオブジェクトのリストを作成します。

adgr_query = 'SELECT CampaignId, CampaignName, Clicks, Cost, Impressions, Ctr, Id, KeywordMaxCpc, Name, Settings, Status'
adgr_page = ad_group_serv.Query(adgr_query)[0]['entries']

adgr_ins = [Adgroup(i['id'],
            i['name'],
            i['campaignId'],
            i['campaignName'],
            i['stats']['ctr'],
            i['stats']['cost']['microAmount'],
            i['stats']['impressions'],
            i['stats']['clicks'],
            i['status']) for i in adgr_page if int(i['id']) not in adgr_exist]

しかし、コミットするとエラーが発生します。

 (IntegrityError) (1062, "Duplicate entry '2147483647' for key 'PRIMARY'")

問題は、その値がどこから来ているのかわからないことです。

'2147483647' in [i['id'] for i in adgr_page]
>>> False
'2147483647' in str(adgr_page)
>>> False

私は本当にこれに固執しています。

4

1 に答える 1

1

どこかに整数オーバーフローがあるようです。

症状:2147483647は2**31-1です-数値の格納に32ビットが使用されたことを示します。

AdGroup.Idフィールドのタイプはxsd:longで、長さは64ビットです。

Python自体には整数値のサイズに制限はありませんが、データベースにはそのような制限がある場合があります。

簡単な解決策:

BigInteger sqltype typeを使用してみてくださいid = Column(BigInteger, primary_key=True)。これは、camp_idとAdWords APIからの残りのxsd:long値に同じです。SQLAlchemyがデータベース固有の長整数列タイプを選択する可能性があります。または、idの型としてString(64)を使用できます。ただし、この場合、主キーを生成するために追加の手順が必要になります。

AdWords APIへのクエリで返されるエントリはいくつですか?2 ** 32レコード以上ありますか?私はそれを疑っています-あなたのデータベースが最大4200百万のレコードを処理できる可能性は低いです。

解決策2-長期

外部ソースに対する主キーの整合性を信頼せず、自動インクリメントを使用して主キーを生成するためにデータベースに依存し、データベースで生成された主キーに基づいて外部キーの母集団を処理するためにSQLAlchemyに依存することをお勧めします。

class Adgroup(Base):
    __tablename__ = 'aw_adgroups'
    id = Column(Integer, Sequence('adgroup_seq'), primary_key=True)  # , primary_key=True
    adGroupId = Column(String(64)) 
    campaignId = Column(Integer,ForeignKey('aw_campaigns.id'))
    campaign = relationship("Campaign", backref = "adgroup")
    ...

class Campaign(Base):
    __tablename__ = 'aw_campaigns'
    id = Column(Integer, Sequence('adgroup_seq'), primary_key=True)
    campaignId = Column(String(64))
    ...

また、campaignIdとadGroupIdで検索する必要があるようです。そのため、これらにインデックスを追加できます。

次に、キャンペーンオブジェクトとAdGroupオブジェクトを作成し、それらの間に関係を追加します。コードは、使用する関係のタイプ(1対多または多対多)によって異なります。詳細については、 sqlalchemyリレーションシップマニュアルを確認してください。

ag = AdGroup(**kwargs)
camp = Campaign(**kwargs)
ag.campaign = camp
session.add(ag)
于 2013-02-07T19:41:30.253 に答える