2013-03-17 2 views
7

В this вопрос был решен проблему обратной LIKE операции в SQL, например, если имя поля «Питер Джонсон», мы могли бы найти такой запрос:Джанго обратном содержит/icontains

select name from user where "Mr. Peter Johnson" like CONCAT('%', name, '%') 

Есть любой способ сделать такую ​​вещь в Django Q объект (я строю большой запрос, поэтому использование необработанного SQL-запроса не будет рациональным)?

ответ

2

К сожалению, ORM Django не имеет ничего встроенного для обратных LIKE. Но предложение .extra() может сделать его немного легче, чем сырой запрос.

я использовал что-то вроде этого:

qs.extra(
    where=['''%s LIKE %s.%s'''], 
    params=(
     "string to match", 
     FooModel._meta.db_table, 
     "bar_field", 
    ), 
) 

Проблемы с кодом выше, что

1) он не работает с SQLite бэкэнда в таком виде («синтаксическая ошибка рядом», он работает с именами таблиц/столбцов, жестко закодированными в запросе ... что не всегда безопасно и всегда уродливо);

и 2) он требует FooModel.bar_field иметь данные %in like style%, так что вы не можете соответствовать произвольные строки (это может быть исправлено с помощью запроса, как %s LIKE CONCAT("%", %s.%s, "%"), но это будет сделать это СУБД конкретного, что не очень хорошо).

Обратный LIKE сам должен, вероятно, работать с любой основной СУБД, но я тестировал его только на sqlite и postgres.

Может кто-то должен обобщить мое решение и создать повторно, СУБД агностик приложение со специальным подклассы QuerySet/менеджер/Q-объекта для этой конкретной задачи ...

-1
output = MyModel.objects.filter(Q(name__contains="Mr. Peter Johnson")) 
+0

Он будет генерировать обычный запрос 'LIKE', а не обратный. –

1

Если вы находитесь на последней версии Django (1.10 или новее) и используя Postgres, ORM может справиться с этим. Check out the docs.

trigram_similar поиск поможет вам то, что вы ищете:

qs = MyModel.objects.filter(name__trigram_similar='Mr. Peter Johnson') 

Не забудьте включить этот поиск, включив расширение pg_tgrm. Вы можете сделать это с помощью django migration.

И вы должны добавить 'django.contrib.postgres' в настройку INSTALLED_APPS.

Смежные вопросы