2017-09-22 5 views
0

Je travaille sur un site d'enchères de jeux vidéo pour acheter/vendre des objets en jeu. Je souhaite pouvoir interroger le tableau des enchères et les trier selon les enchères les plus «chaudes». Ceci est basé sur le nombre d'offres/heure placées sur une vente aux enchères.Demande de commande par nombre de relations un-à-plusieurs par heure - SQLAlchemy

Voici le modèle d'enchères:

class Auctions(db.Model): 
    id = db.Column(db.Integer, primary_key=True, index=True) 
    posted = db.Column(db.DateTime()) 
    end = db.Column(db.DateTime()) 
    ... 

    bids = db.relationship('Bids', backref='auctions', lazy='dynamic', order_by='desc(Bids.amount)', cascade="all, delete-orphan") 

Voici le modèle Enchères:

class Bids(db.Model): 
    id = db.Column(db.Integer, primary_key=True, index=True) 
    bidder_id = db.Column(db.Integer, db.ForeignKey('user.id'), index=True) 
    auction_id = db.Column(db.Integer, db.ForeignKey('auctions.id'), index=True) 
    amount = db.Column(db.Integer) 
    posted = db.Column(db.DateTime()) 

Je suis en mesure de les trier par le montant des offres comme ceci:

hot_stmt = db.session.query(models.Bids.auction_id, func.count('*').label('bid_count')).group_by(models.Bids.auction_id).subquery() 
hot = db.session.query(models.Auctions, hot_stmt.c.bid_count).outerjoin(hot_stmt, (models.Auctions.id == hot_stmt.c.auction_id)).order_by(hot_stmt.c.bid_count.desc()).limit(5) 

Je peux calculer et énumérer des offres/heure avec ceci:

for auc, count in hot: 
    time_delta = datetime.utcnow() - auc.posted 
    auc_hours = time_delta.seconds/60/60 
    print(auc.id, count/auc_hours) 

Comment puis-je trier la requête par enchères/heure afin que la requête renvoie les 5 enchères les plus chaudes?

Répondre

1

Une approche utile est de créer un dictionnaire avec des ventes aux enchères que les clés et les offres/h en tant que valeurs:

d = {} 
for auc, count in hot: 
    time_delta = datetime.utcnow() - auc.posted 
    auc_hours = time_delta.seconds/60/60 
    d[auc] = count/auc_hours 

Faire une liste des enchères:

aucs = [auc for auc, count in hot] 

Trier la liste aucs basée sur les valeurs (utilisez le mot-clé reverse pour placer les valeurs les plus élevées au début de la liste, puisque la fonction sort est la plus basse à la plus élevée par défaut):

aucs.sort(key=d.get, reverse=True) 
+0

Merci pour la réponse! Je n'étais pas clair dans mon message original. Je veux que la requête retourne les 5 meilleures ventes aux enchères, donc la commande doit être faite avec SQLAlchemy afin que je puisse simplement limiter la requête pour obtenir le top 5. Cela fonctionnerait si je demandais juste la table des enchères pour tous ventes aux enchères actuelles, puis trier de cette façon, je suis juste inquiet de la performance. – triggdev

+1

Je suis pratiquement certain que la fonction 'list.sort' est écrite en C et est assez rapide. Il serait facile d'essayer de voir si la performance est acceptable. –

+0

Je suis principalement préoccupé par la charge de la base de données. Je ne connais pas grand-chose à la différence de performance entre les deux. Je pense que renvoyer plus de 1000 résultats, puis trier/découper serait plus lent que de renvoyer 5 résultats dans une requête déjà triée. – triggdev