2016-11-09 40 views
0

ホテル料金の一覧をフィルタリングするクエリを作成しようとしています。私は、今日から将来へのホテル予約を表示したいだけです。私が作成したクエリは以下の通りですが、結果をフィルタリングしません。私は間違って何をしていますか?背景についてはSqlalchemy日付でフィルタ

hotels = db.session.query(Hotel).\ 
    join(Location).\ 
    join(Rate).\ 
    filter(Location.city == city).\ 
    filter(Rate.arrive > datetime.utcnow()) 

、私のモデルは次のようになります。

class Location(Base): 
    __tablename__ = 'locations' 

    id = Column(Integer, primary_key=True) 
    city = Column(String(50), nullable=False, unique=True) 

    hotels = relationship('Hotel', back_populates='location') 


class Hotel(Base): 
    __tablename__ = 'hotels' 

    id = Column(Integer, primary_key=True) 
    name = Column(String(100), nullable=False, unique=True) 
    phone_number = Column(String(20)) 
    parking_fee = Column(String(10)) 
    location_id = Column(Integer, ForeignKey('locations.id'), nullable=False) 

    location = relationship('Location', back_populates='hotels') 
    rates = relationship('Rate', back_populates='hotel', order_by='Rate.arrive') 


class Rate(Base): 
    __tablename__ = 'rates' 

    id = Column(Integer, primary_key=True) 
    price = Column(Numeric(6, 2)) 
    arrive = Column(Date, nullable=False) 
    link = Column(String(500), nullable=False) 
    updated = Column(DateTime, default=datetime.datetime.utcnow, nullable=False) 
    hotel_id = Column(Integer, ForeignKey('hotels.id'), nullable=False) 

    hotel = relationship('Hotel', back_populates='rates') 

編集:

Date: Friday, Sep 9 

Rate: 299.25 

Date: Sunday, Sep 11 

Rate: 261.75 

Date: Monday, Sep 12 

Rate: 261.75 

Date: Tuesday, Sep 13 

Rate: 261.75 

Date: Sunday, Sep 18 

除去フィルター(Rate.arrive> datetime.utcnow(:ここに は、いくつかのサンプルデータであり、 ))はデータを変更しません。クエリを実行するたびに同じ結果が出力されます。

+0

contains_eagerを使用していますか?あなたは 'filter(Rate.arrive> datetime.utcnow()'を削除した場合と同じですか?または結果が空ですか?*サンプルデータと期待されるクエリ結果は助けになります* – van

+0

サンプルデータを追加しました。 – Casey

+0

あなたのクエリは 'Hotel'インスタンスを返し、クエリのロジックは次のようになります:* **少なくとも**がある興味のある都市のホテルを返します* datetime.datetime.utcnow()の後に少なくとも1つの* Rateがある場合、ホテルが返されます。これはあなたが望むものではありませんか? – van

答えて

1

オプションをゼロにすると、ホテルを読み込んだ後にレートのフィルタを適用することになりますが、追加のクエリが生成され、望ましくありません。

は、後に使用されるフィルタを定義します。

city = 'mumbai' 
arrive = datetime.date.today() 

オプション-1:最初の照会への関心の負荷Rate

query = (
    session.query(Hotel, Rate) # this query will return pairs (Hotel, Rate) 
    .join(Location) 
    .join(Rate) 
    .filter(Location.city == city) 
    .filter(Rate.arrive > arrive) 
) 

# one could use the results directly as (Hotel, Rate) pairs 
# but we can also convert to the format: {hotel: rates} 
from collections import defaultdict 
hotels_list = defaultdict(list) 
for h, r in hotels: 
    hotels_list[h].append(r) 

# and print: 
for hotel, rates in hotels_list.items(): 
    print('', hotel) 
    for rate in rates: 
     print(' ', rate) 

オプション-2:トリック関係Hotel.rates

ここでは0

私たちは、あなたがクエリを実行するとき、あなたは何の結果を得るのですか

hotels = (
    session.query(Hotel) 
    .join(Location) 
    .join(Rate) 
    .options(contains_eager(Hotel.rates)) # this is the key 
    .filter(Location.city == city) 
    .filter(Rate.arrive > arrive) 
) 


for hotel in hotels: 
    print('', hotel) 
    for rate in hotel.rates: # this now contains only sub-list, so be careful 
     print(' ', rate) 
+0

ハレルヤありがとう!私はcontains_eagerメソッドを使いました。今私はもっとドキュメントを読む必要があるので、何が起こっているのか十分に理解することができます。 – Casey

+0

'contains_eager'を使うことによって、' sqlalchemy'が基本的に*すべての*関係をロードしたと考えることができます。したがって、あなたはそれを使用することに注意する必要があります。しかし、使い方は非常にエレガントで、私は時々それをします。 – van