2014-01-18 4 views
2

Я создал модель User, у которой есть оценка и оценка столбцов. Я хотел бы периодически обновлять ранг всех пользователей в Пользователе, чтобы пользователь с наивысшим счетом имел ранг 1, второй самый высокий балл 2 и т. Д. В любом случае, для эффективного достижения этого в Flask-SQLAlchemy?Как я могу оценивать записи, используя sqlalchemy?

Спасибо!

Кстати, вот модель:

app = Flask(__name__) 
db = SQLAlchemy(app)   
class User(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    score = db.Column(db.Integer) 
    rank = db.Column(db.Integer) 
+0

Почему вы должны хранить это в базе данных, если получение звания всех пользователей может быть достигнуто в самом SQL запросе на большинстве СУБД. Какую базу данных вы используете? – van

ответ

0

Просто цикл на всех пользователей:

users = User.query.order_by(User.score._desc()).all() #fetch them all in one query 
for (rank, user) in enumerate(users): 
    user.rank = rank + 1 #plus 1 cause enumerate starts from zero 

db.session.commit() 
+0

Не полезно. Как насчет таблицы с тысячами пользователей? – SBillion

+0

@SBillion Возможно, не работает с большим набором данных, но «не полезно» - это ошибка. Мой ответ - это чистая sqlalchemy, поскольку OP не указал, какие rdbms он использует. Поэтому мы не можем предположить, что есть поддержка подзапросов (как большой ответ zzzeek выше). И в наши дни вы можете даже распределить задачу, подобную этой, с использованием многопроцессорных или очередей задач для рабочих без блокировки данных в тривиальном обновлении. –

3

Ну, насколько почему можно было бы сделать это, так что вы можете запросить " рангом "без необходимости выполнять совокупный запрос, который может быть более результативным. особенно если вы хотите увидеть «Что такое ранг для пользователя № 456?» без удара по каждой строке.

Самый эффективный способ сделать это - это одно ОБНОВЛЕНИЕ. Использование стандартного SQL, мы можем использовать коррелировала подзапрос, как это:

UPDATE user SET rank=(SELECT count(*) FROM user AS u1 WHERE u1.score > user.score) + 1 

Некоторые базы данных имеют расширения, такие как UPDATE..FROM PG, который у меня меньше опыта, возможно, если бы вы могли UPDATE..FROM с ЗЕЬЕСТ, что сразу получает ранг, используя функцию окна, которая была бы более эффективной, хотя я не совсем уверен.

В любом случае наш стандарт SQL с SQLAlchemy выглядит следующим образом:

from sqlalchemy.orm import aliased 
from sqlalchemy import func 
u1 = aliased(User) 
subq = session.query(func.count(u1.id)).filter(u1.score > User.score).as_scalar() 
session.query(User).update({"rank": subq + 1}, synchronize_session=False) 
+0

Как упоминал @zzzeek, ​​может быть более эффективный способ, если бэкэнд поддерживает функцию UPDATE..FROM и window. В случае PostgreSQL вы можете использовать 'ROW_NUMBER()' (проверьте это: http://www.postgresql.org/docs/9.3/static/functions-window.html). – yoloseem

Смежные вопросы