Могу ли я легко переопределить Django ORM 'iexact', чтобы использовать LOWER() вместо UPPER()?

Использование Django 1.3x.

В настоящее время у меня есть очень, очень большой и очень, очень активный набор данных Postgres, в котором есть важный столбец, проиндексированный как lower(column).

Я только что понял, что некоторые общие запросы были довольно медленными, потому что Django ORM генерирует запрос для поля как blah = UPPER(column), когда я использую iexact для сопоставления с этим полем.

Есть ли простой способ заставить ORM использовать вместо этого lower() или мне нужно перейти к чистому SQL для этого?

Спасибо!

[побочный вопрос для комментариев: есть ли упущенная веская причина использовать upper() в индексе, а не lower()?]


person anonymous coward    schedule 26.01.2012    source источник


Ответы (2)


Интересная ситуация здесь. Раньше я никогда не переставал думать об этом. Похоже, что использование UPPER для iexact поиска было введено еще в редакции 8536 в ответ на билет 3575, почти три года назад. До этого Django использовал ILIKE для таких типов поиска.

Я просмотрел внутренний код, и единственное, что я могу найти, что указывает на какую-либо причину для UPPER против LOWER, похоже, заключается в том, что Oracle по умолчанию использует верхний регистр при обработке данных без учета регистра. Так как остальные агностики, кажется, Джанго решил по умолчанию использовать UPPER, чтобы охватить все базы.

Другое впечатление, которое у меня сложилось при просмотре исходного кода, заключалось в том, что вы не сможете обойтись без UPPER. Это буквально повсюду, а не только при фактическом запросе базы данных. Расширение строки Python upper также используется довольно часто.

Я бы сказал, что лучше всего просто создать индекс с upper(column) или вместо него, и пойти выпить.

person Chris Pratt    schedule 26.01.2012
comment
Крис, спасибо за ответ! Я тоже наткнулся на эти билеты, но не видел серьезного обсуждения того, почему он вдруг изменился на upper(). Ваше понимание бита Oracle - самое большее, что я слышал. На самом деле это простой запрос, поэтому я полагаю, что здесь я просто использую .raw(). Спасибо большое! - person anonymous coward; 27.01.2012

Попробуйте .extra(), прежде чем переходить к .raw()

MyModel.objects.extra(where=["lower(mycol)=%s"], params=['foo'])
person user    schedule 17.01.2015