Debido a que DecimalField
se almacena como string
cuando se indexa, no produce los resultados esperados cuando se usa order_by
.
En lugar de ordenar por valor numérico, ordena los datos alfabéticamente.
Problema relacionado en el backend de Xapian aquí: https://github.com/notanumber/xapian-haystack/issues/84
Quizás la mejor manera de abordar (rápidamente) esto sería actualizar la documentación DecimalField
para indicar que order_by
no es compatible.
A largo plazo, podría aparecer un mensaje de ADVERTENCIA en el registro de nivel cuando se intente la operación order_by
en un DecimalField
. Por motivos de rendimiento, la verificación del tipo de campo solo se puede realizar cuando el sitio está en modo DEBUG
.
Una solución para esto es almacenar el contenido de un campo decimal como un número entero. Por ejemplo, si tengo un modelo llamado MyModel con un campo decimal llamado precio, podría multiplicarlo por el número de lugares decimales y almacenarlo como un número entero.
class MyIndex(SearchIndex):
...
price = IntegerField(model_attr='price')
def prepare_price(self, obj):
return int(obj.price * Decimal('100'))
Esto parece funcionar para elasticsearch pero no para solr.
El error aparentemente también se aplica a Whoosh.
Las consultas de rango también fallan en elasticsearch.
+1
Me encontré con este mismo problema usando SolrBackend. Estamos ordenando por un campo que contiene un número entre 0.0 - 1.0 que representa un algoritmo de puntuación complejo. Al ordenar por cadena, eso significa que los elementos con una puntuación muy pequeña se ordenan por encima de aquellos con puntuaciones más altas, por ejemplo, 9e-08
En realidad, una solución obvia es usar un campo flotante en su lugar (realmente no importa para mis propósitos).
Esto es bastante malo. Si no se va a arreglar, pero simplemente se documenta como "order_by no funciona", entonces creo que deberíamos desaprobar el tipo de campo o tener una advertencia clara en la lista de tipos de campo, porque sería fácil de usar por error, y la reparación es lenta si tiene una base de datos grande.
tampoco funciona para elasticsearch
: +1:
@JoeJasinski muchas gracias, tu respuesta me ayudó
Una solución para esto es almacenar el contenido de un campo decimal como un número entero. Por ejemplo, si tengo un modelo llamado MyModel con un campo decimal llamado precio, podría multiplicarlo por el número de lugares decimales y almacenarlo como un número entero.
class MyIndex(SearchIndex): ... price = IntegerField(model_attr='price') def prepare_price(self, obj): return int(obj.price * Decimal('100'))
¿Y luego?
MyIndex.objects.all().order_by('prepare_price')
? ¿Derecha?
Comentario más útil
Una solución para esto es almacenar el contenido de un campo decimal como un número entero. Por ejemplo, si tengo un modelo llamado MyModel con un campo decimal llamado precio, podría multiplicarlo por el número de lugares decimales y almacenarlo como un número entero.