2010-04-17 10 views
6

Estoy tratando de encontrar una forma eficaz de encontrar el rango de un objeto en la base de datos relacionado con él de Score. Mi solución ingenua se ve así:¿Cómo obtengo la posición de un resultado en la lista después de un pedido_por?

rank = 0 
for q in Model.objects.all().order_by('score'): 
    if q.name == 'searching_for_this' 
    return rank 
    rank += 1 

Debería ser posible para obtener la base de datos para hacer el filtrado, utilizando order_by:..

Model.objects.all() order_by ('puntuación') del filtro (name = 'searching_for_this')

Pero no parece ser una manera de recuperar el índice para el paso order_by después del filtro.

¿Hay una mejor manera de hacerlo? (Usando Python/Django y/o SQL prima.)

Mi siguiente pensamiento es comprobar la validez de cómputo ocupa de inserción pero que parece desordenado.

+0

algo como: 1. 'seleccione puntaje como base_resultado donde nombre = 'búsqueda_para_esto'' 2. seleccione cuenta (*) donde puntaje <= puntaje_resuelto' -> rango – jfs

Respuesta

7

no creo que se puede hacer esto en una consulta de base de datos utilizando Django ORM. Pero si no le molesta, me gustaría crear un método personalizado en un modelo:

from django.db.models import Count 

class Model(models.Model): 
    score = models.IntegerField() 
    ... 

    def ranking(self): 
     aggregate = Model.objects.filter(score__lt=self.score).aggregate(ranking=Count('score')) 
     return aggregate['ranking'] + 1 

A continuación, puede utilizar el "ranking" en cualquier lugar, como si fuera un campo normal:

print Model.objects.get(pk=1).ranking 
+0

Gracias, eso es exactamente lo que estaba buscando. –

+0

Gracias. Tenga en cuenta que en el ejemplo que dio, el orden era ascendente (en otras palabras, "la más baja sea la puntuación, mejor es la clasificación"), así que fui con él. Si un puntaje más alto realmente aumentara el ranking, debería cambiar "score__lt" por "score__gt". –

+2

Esto debe ser computacionalmente costosa, ya que se ejecute la consulta agregada clasificación para cada fila de 'Model.objects.all()' – mehmet

2

En "SQL puro" con un motor de base de datos de estándar (PostgreSql, SQL Server, Oracle, DB2, ...), puede usar la función estándar de SQL RANK, pero eso no es compatible con los populares pero motores no estándar como MySql y Sqlite, y (quizás debido a eso) Django no "muestra" esta funcionalidad a la aplicación.

+0

Ah, estoy probando en Sqlite antes de implementarlo en PGSQL. –

+2

@BobBob, si lo desea, puede ejecutar una pequeña instancia local de PostgreSql con fines de prueba; no es difícil ni oneroso. –

1

usar algo como esto:

obj = Model.objects.get(name='searching_for_this') 
rank = Model.objects.filter(score__gt=obj.score).count() 

filas Usted puede pre-cálculo y guardarla en modelo si se utilizan con frecuencia y afectan el rendimiento.

Cuestiones relacionadas