Мога ли лесно да отменя 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 по подразбиране използва главни букви при обработката на данни, които не са чувствителни към малки и главни букви. Тъй като другите са агностици, изглежда Django е решил да зададе по подразбиране UPPER, за да покрие всички бази.

Другото впечатление, което получих от разглеждането на изходния код, беше, че няма да се придвижвате с UPPER. Това е буквално навсякъде, а не само когато действително правите заявки в базата данни. Разширението на низ upper на Python също се използва доста често.

Бих казал, че най-добрият ви залог е просто да създадете индекс с 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