2017-12-29 18 views
0

フラスコベースのAPIアプリケーションをflask-sqlalchemyおよびPostgres DBで構築しています。SQLAlchemyオブジェクトコレクションへの外部データの追加

  • users DB内のテーブルには、各ユーザーのレコードが格納されます。この表のPKはusername(ここでは特別なものではありません)
  • performanceテーブルには、ユーザーのパフォーマンスが保持されます。この表のPKは日付です。このテーブルの各ユーザーには、usernameという名前の列があります。 (私は、この構造が理想的ではないと言う人もいるが、無関係の要件によって必要とされることもあることを知っている)。

例:

PK = "username", tablename = "users" 

| username | firstname | lastname | 
----------------------------------- 
| alice | Alice  | Johns | 
| bob  | Bob  | Speed | 


PK = "timestamp", tablename = "performance" 

| timestamp | alice | bob | 
----------------------------------- 
| 2017-11-2 | 1  | 5 | 
| 2017-11-3 | 6  | 9 | 

私はusersテーブルにアクセスするためにSQLAlchemyのを使用しています。

私は、Dateパラメータを受け取り、その日付のパフォーマンスを持つすべてのユーザーのコレクションを返すREST APIを作成します。

正しいSQLAlchemyクエリとは何ですか。パフォーマンス値はユーザーごとに個別に選択されません。

+0

では、各ユーザーのための列を持つテーブルが、待って?あるいは '(date、user_id、value)'のようなものを持っていることを意味しましたか? –

+0

各ユーザーの列を持つ時系列表(ユーザーの数は静的であり、変更されていません) – Miro

+0

質問を一から書き直しました。再オープンすることはできますか? tnx – Miro

答えて

0

スキーマを絶対に変更できない場合は、パフォーマンスデータをアンピボットしてユーザーと参加できます。リレーションシップのマッピングのサンプルはありません。

In [2]: class User(Base): 
    ...:  __tablename__ = "users" 
    ...:  username = Column(Unicode(255), primary_key=True) 
    ...:  firstname = Column(Unicode(255)) 
    ...:  lastname = Column(Unicode(255)) 
    ...:  

In [3]: class Performance(Base): 
    ...:  __tablename__ = "performance" 
    ...:  timestamp = Column(Date, primary_key=True) 
    ...:  # NOTE: this works **only** in a class body context, 
    ...:  # and your schema shouldn't be like this anyway. 
    ...:  for name in ['alice', 'bob']: 
    ...:   locals()[name] = Column(Integer, nullable=False) 
    ...:   

検査を使用してパフォーマンスデータを持つユーザー名を取得します。彼らのパフォーマンス値と

In [15]: from sqlalchemy.dialects import postgresql 
    ...: performance = session.query(
    ...:   func.unnest(postgresql.array(users)).label('username'), 
    ...:   func.unnest(postgresql.array(
    ...:    [getattr(Performance, name) 
    ...:    for name in users])).label('value')).\ 
    ...:  filter(Performance.timestamp == '2017-11-2').\ 
    ...:  subquery() 
    ...: 

参加ユーザー:

In [24]: session.query(User, performance.c.value).\ 
    ...:  join(performance, performance.c.username == User.username).\ 
    ...:  all() 
Out[24]: 
[(<__main__.User at 0x7f79eb5d2c88>, 1), 
(<__main__.User at 0x7f79eb5d2cf8>, 5)] 
- それをするだけの一方通行

In [11]: users = inspect(Performance).attrs.keys()[1:] 

In [12]: users 
Out[12]: ['alice', 'bob'] 

フォームunpivot query:あなたはまた、ユーザ名の静的なリストを保持でき


パフォーマンスデータが(timestamp, username, value)タプルとして保存されるようにスキーマを変更する場合、

In [2]: class User(Base): 
    ...:  __tablename__ = "users" 
    ...:  ... 
    ...:  performance = relationship("BetterPerformance") 
    ...: 

In [25]: class BetterPerformance(Base): 
    ...:  __tablename__ = "better_performance" 
    ...:  timestamp = Column(Date, primary_key=True) 
    ...:  username = Column(ForeignKey('users.username'), primary_key=True) 
    ...:  value = Column(Integer, nullable=False) 
    ...: 

In [13]: session.query(User, BetterPerformance.value).\ 
    ...:  join(User.performance).\ 
    ...:  filter(BetterPerformance.timestamp == '2017-11-2').\ 
    ...:  all() 
Out[13]: 
[(<__main__.User at 0x7f6ae3282c18>, 1), 
(<__main__.User at 0x7f6ae3282ba8>, 5)] 

かさえ:単純にこれを行うウルド

In [17]: session.query(User).\ 
    ...:  join(User.performance).\ 
    ...:  options(contains_eager(User.performance)).\ 
    ...:  filter(BetterPerformance.timestamp == '2017-11-2').\ 
    ...:  all() 
Out[17]: [<__main__.User at 0x7f6ae3282c18>, <__main__.User at 0x7f6ae3282ba8>] 

In [18]: [u.performance[0].value for u in _] 
Out[18]: [1, 5] 
関連する問題