1

次のような2つのORMクラスがあります。

class Road(Base):

  __tablename__ = "road"

  id = Column(Integer, primary_key=True)

  @hybrid_method
  def total_traffic(self, days):
      today_date = datetime.datetime.now().date()
      future_date = today_date+datetime.timedelta(days)
      return sum([traffic.volume 
                  for traffic in self.traffic
                  if traffic.date >= today_date and traffic.date < future_date])

  @total_traffic.expression
  def total_traffic(cls, days):
      today_date = datetime.datetime.now().date()
      future_date = today_date+datetime.timedelta(days)
      return select([func.sum(RoadTraffic.volume)]).\
          where(RoadTraffic.road_id == cls.id).\
          where(RoadTraffic.date >= today_date).\
          where(RoadTraffic.date < future_date).\
          label("total_traffic")


class RoadTraffic(Base):

  __tablename__ = "road_traffic"

  id = Column(Integer, primary_key=True)
  volume = Column(Integer)
  date = Column(Date, nullable=False)
  road_id = Column(Integer, ForeignKey('road.id'), nullable=False)
  road = relationship("Road", backref=backref('traffic'))

これは機能的には素晴らしいことですが、完全なデータ セットですべてのトラフィック データを取得してローカルで合計するのは、joinedload を使用しても少し時間がかかります (本番環境では 4 秒)。次のように、Roads と一緒に total_traffic を選択できます。

  roads_with_traffic = db.query(Orn, Orn.total_traffic(7)).all()

しかし、純粋な Road リストではなく、これを受け取るようにビューを変更する必要があります。

関連オブジェクトで選択した total_traffic をキャッシュする規則はありますか?

4

1 に答える 1

0

現時点で私がこれについて行った方法は次のとおりです。

class Road(Base):

  __tablename__ = "road"

  id = Column(Integer, primary_key=True)

  def __init__(self):
    self.traffic_cache = {}

  @orm.reconstructor
  def init_on_load(self):
    self.traffic_cache = {}

  @hybrid_method
  def total_traffic(self, days):
      if days in self.traffic_cache:
        return self.traffic_cache[days]
      today_date = datetime.datetime.now().date()
      future_date = today_date+datetime.timedelta(days)
      return sum([traffic.volume 
                  for traffic in self.traffic
                  if traffic.date >= today_date and traffic.date < future_date])

  @total_traffic.expression
  def total_traffic(cls, days):
      today_date = datetime.datetime.now().date()
      future_date = today_date+datetime.timedelta(days)
      return select([func.sum(RoadTraffic.volume)]).\
          where(RoadTraffic.road_id == cls.id).\
          where(RoadTraffic.date >= today_date).\
          where(RoadTraffic.date < future_date).\
          label("total_traffic")

Road オブジェクトを次のように更新します。

roads_with_traffic = db.query(Road, Road.total_traffic(7)).all()
for road, traffic in roads_with_traffic:
  road.traffic_cache[7] = traffic

これは問題ありませんが、これを何らかの方法でクラス内に移動するとよいでしょう。

于 2012-12-20T00:32:53.460 に答える