Como DecimalField
é armazenado como string
durante a indexação, ele não produz os resultados esperados ao usar order_by
.
Em vez de ordenar por valor numérico, ele classifica os dados em ordem alfabética.
Problema relacionado no back-end Xapian aqui: https://github.com/notanumber/xapian-haystack/issues/84
Talvez a melhor maneira de resolver isso (rapidamente) seja atualizar a documentação DecimalField
para indicar que order_by
não é suportado.
A longo prazo, uma mensagem de nível de AVISO poderia ser gerada quando a operação order_by
fosse tentada em um DecimalField
. Por motivos de desempenho, a verificação do tipo de campo só pode ser feita quando o site está no modo DEBUG
.
Uma solução alternativa para isso é armazenar o conteúdo de um campo decimal como um número inteiro. Por exemplo, se eu tiver um modelo denominado MeuModelo com um campo Decimal denominado preço, poderia multiplicá-lo pelo número de casas decimais e armazenar como um inteiro.
class MyIndex(SearchIndex):
...
price = IntegerField(model_attr='price')
def prepare_price(self, obj):
return int(obj.price * Decimal('100'))
Isso parece funcionar para elasticsearch, mas não para solr.
O bug aparentemente se aplica ao Whoosh também.
Consultas de intervalo também falham em elasticsearch.
+1
Eu encontrei esse mesmo problema usando o SolrBackend. Estamos classificando por um campo que contém um número entre 0,0 - 1,0, representando um algoritmo de pontuação complexo. Ao classificar por string, isso significa que os elementos com uma pontuação muito pequena são classificados acima daqueles com pontuações maiores, por exemplo, 9e-08
Justamente, uma solução alternativa óbvia é usar um campo flutuante em vez disso (realmente não importa para meus propósitos).
Isso é muito ruim. Se não vai ser corrigido, mas apenas documentado como "order_by não funciona", então acho que devemos descontinuar o tipo de campo ou ter um aviso claro na lista de tipos de campo, porque seria fácil de usar por erro e lento para reparar se você tiver um grande banco de dados.
também não funciona para elasticsearch
: +1:
@JoeJasinski muito obrigado, sua resposta me ajudou
Uma solução alternativa para isso é armazenar o conteúdo de um campo decimal como um número inteiro. Por exemplo, se eu tiver um modelo denominado MeuModelo com um campo Decimal denominado preço, poderia multiplicá-lo pelo número de casas decimais e armazenar como um inteiro.
class MyIndex(SearchIndex): ... price = IntegerField(model_attr='price') def prepare_price(self, obj): return int(obj.price * Decimal('100'))
E então?
MyIndex.objects.all().order_by('prepare_price')
? Direito?
Comentários muito úteis
Uma solução alternativa para isso é armazenar o conteúdo de um campo decimal como um número inteiro. Por exemplo, se eu tiver um modelo denominado MeuModelo com um campo Decimal denominado preço, poderia multiplicá-lo pelo número de casas decimais e armazenar como um inteiro.