Как получить лучшие n результатов по группе из пула идентификаторов в SQLAlchemy? - PullRequest
1 голос
/ 11 октября 2019

У меня есть две таблицы. 1-й представляет один article на строку , а 2-й представляет один news_cluster на строку массивом столбцом для всех articles_id на cluster ).

Мне нужно получить 19 лучших news_cluster, а затем получить 4 лучших статей для каждого news_cluster (порядок по l_score column).

В настоящее время я извлекаю все articles_id из всех 19 news_cluster с помощью SQLAlchemy, а затем сортирую их по news_cluster и l_score с помощью python:

all_news_obj = News.query.order_by(score).limit(19)
all_ids = sum([a_news.articles_id for a_news in all_news_obj], [])
all_articles = Articles.query.filter(Articles.id.in_(all_ids)).all()
articles_sorted = 4_best_l_score_sorted_by_cluster(all_articles)

Мне было интересноесли был более быстрый способ получить и отсортировать эти статьи, и я увидел, что вы можете группировать по кластерам (news_id) и получать верхние 4 l_score для каждой группы сэтот запрос psql:

SELECT ranked.* FROM 
(SELECT articles.*, rank() OVER (PARTITION BY news_id ORDER BY l_score DESC)
    FROM articles
    WHERE id = ANY(ARRAY[209146, 209140, 209154...])
) ranked
WHERE rank <=4

Так что может быть быстрее, если psql сначала обработает сортировку, но я понятия не имею, как реализовать этот запрос в SQLAlchemy.

1 Ответ

0 голосов
/ 11 октября 2019

На мой вопрос чаще всего отвечают здесь: Преобразование запроса ранга и раздела в SqlAlchemy

Мне просто нужно было адаптировать его к моей модели Articles и добавить фильтр для соответствия идентификаторам вall_ids_array:

subquery = db.session.query(
    Articles,
    func.rank().over(
        order_by=Articles.l_score.desc(),
        partition_by=Articles.news_id
    ).label('rank')
).filter(Articles.id.in_(all_ids_array)).subquery()

articles_sorted = db.session.query(subquery).filter(subquery.c.rank <= 4)

Я счастливый человек: это на 0,1 секунды быстрее, чем получать все статьи и сортировать их потом с помощью Python.

...