Peewee, как избежать n + 1 запросов с отношением многие ко многим ко многим - PullRequest
0 голосов
/ 21 февраля 2019

У меня есть модель с отношением «многие ко многим ко многим» (2 промежуточные таблицы для 3 вовлеченных объектов)

Это выглядит так:

Project -> (project_tag) -> Tag -> (intent_tag) -> Intent

Я хочу получить X Intent, и для каждого Intent все теги и все проекты.

С помощью prefetch() я могу сделатьэто с 2 запросами (вместо сотен, которые могут быть сделаны автоматически), для простого отношения many-to-many, но я не нахожу, как сделать это с еще одним отношением -to-many ...

Iпробовал так много вещей, например, одну:

    intent_query = Intent.select().paginate(1, 4)
    intent_tag_query = IntentTag.select(IntentTag, Tag, Intent, ProjectTag, Project) \
        .join(Intent) \
        .switch(IntentTag) \
        .join(Tag) \
        .join(ProjectTag).join(Project) \
        .where(IntentTag.intent.in_(intent_query))

    combo_query = prefetch(intent_query, intent_tag_query)
    result = []
    for res in combo_query:
        intent_dict = model_to_dict(res)
        intent_dict['intent_tags'] = []
        for intent_tags in res.intent_tags:
            intent_tags_dict = model_to_dict(intent_tags)
            intent_tags_dict['project_tags'] = []
            for project_tags in intent_tags.tag.project_tags:
                intent_tags_dict['project_tags'].append(model_to_dict(project_tags))
            intent_dict['intent_tags'].append(intent_tags_dict)
        result.append(intent_dict)

При предварительной загрузке я получил 2 запроса;он не идеален, один запрос содержит другой как подзапрос, поэтому он выполняется 2 раза, но это не слишком дорого, поэтому я могу принять это ...

Но с циклом "project_tags" каждый ходвыполняет еще 2 запроса для получения данных от project_tag и project, но эти данные уже доступны в первом intent_tag_query с join(): /

Надеюсь, мой вопрос ясен, ямогу предоставить больше данных, если это может быть полезно, я не вставляю модели напрямую, потому что я думал, что это может испортить чтение из этого поста, но я могу, если хотите:)

Спасибо!

...