簡體   English   中英

SQLAlchemy - 結合 group_by 和 func.count() 與joinedload()

[英]SQLAlchemy - combining group_by and func.count() with joinedload()

我想在基於關系過濾的查詢中使用加入的預先加載(用於加速),然后按一列的值對結果進行分組。

例如,這里有一個表:

PERSON | EMPLOYER | SALAD PREFERENCE
Alice  | bigCorp  | Ceasar
Bob    | evilCorp | Greek
Charlo | bigCorp  | Greek
Derek  | evilCorp | Caesar
...

這與 EMPLOYER 表有關系:

EMPLOYER | EVILNESS
bigCorp  | NOT_EVIL
evilCorp | SUPER_EVIL
...

我想了解為超級邪惡雇主工作的人喜歡沙拉的數量。

所以我想做一些類似的事情:

salad_preferences_with_counts = {
    salad: count for (salad, count) in
    session.query(
        Person.salad_preference, func.count(Person.salad_preference))
        .group_by(Person.salad_preference)
        .filter(
            Person.employer.evilness == Employer.Evilness.super_evil
        )
        .options(load_only(Person.salad_preference))
        .options(joinedload(Person.employer).load_only(Employer.evilness))
        .all()
}

生成:

{ "Caesar": 1, "Greek": 1 }

但是,在混合使用load_onlyjoinedload時,它失敗了:

sqlalchemy.exc.ArgumentError: Query has only expression-based entities, which do not apply to (column|relationship) property ("Person.salad_preference"|"Person.employer")

看起來發生這種情況的原因與with_entities()破壞joinedload()原因相同。 當然,當我取出load_only()joinedload() ,一切都運行良好。

有沒有辦法讓我仍然使用相同的group_byfunc.count邏輯來按沙拉偏好分組,同時仍然使用joinedload()進行性能優化? 或者這是不可能的,因為它打破了joinedload()的想法(它不應該影響查詢結果),或者它實際上不會產生任何性能優勢?

我對 SQLAlchemy 很陌生,所以我可能在這里遺漏了一些基本的東西。 如果你有一些“你為什么要這樣做”類型的問題,請告訴我,因為也可能是我完全錯誤的情況。

謝謝!

負載優化僅針對獲取到對象本身的內容。 它不會優化應用於查詢的filter() 此外,您的查詢僅要求標量,而不會加載完整的對象Person ,因此無需優化。 IE。 這只是標量的 2 元組Person.salad_preference, func.count(Person.salad_preference)

person = session.query(Person).options(load_only(Person.salad_preference)).first()
# Only this attribute was loaded, so we can access without triggering a query
person.salad_preference
# This attribute is not loaded, but will be loaded when we access it
person.employer
# We are only loading this value already, load_only does not make sense because there is no `person` object.
(person_salad_preference,) = session.query(Person.salad_preference).first()

我不確定你想用這個過濾器做什么。 您是否嘗試過濾與 Person.employer 的連接:

Person.employer.evilness == Employer.Evilness.super_evil

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM