Если бы обновить это:
Мы нашли способ создания необходимых операторов Postgres путем регистрации функции SQL с помощью ILIKE, в нашем обычае Hibernate Диалект.
Пример с ILIKE:
//Postgres Constants Operators
public class PostgresOperators {
private static final String NS = PostgresOperators.class.getName();
public static final Operator<Boolean> ILIKE = new OperatorImpl<>(NS, "ILIKE");
}
//Custom JPQLTemplates
public class PostgresTemplates extends HQLTemplates {
public static final PostgresTemplates DEFAULT = new PostgresTemplates();
public PostgresTemplates() {
super();
add(PostgresOperators.ILIKE, "my_ilike({0},{1})");
}
}
Укажите JPQLTemplates при использовании jpaquery
new JPAQuery(entityManager, PostgresTemplates.DEFAULT);
теперь становится сложнее, мы не могли использовать ILIKE напрямую, есть проблема с "ILIKE" ключевое слово уже зарегистрировано, поэтому мы сделали функцию ilike и зарегистрировали ее в настраиваемом диалоговом режиме спящего режима.
Наш application.yml задающий:
#SEE JPA http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
spring.data.jpa:com.example.customDialect.config.database.ExtendedPostgresDialect
Тогда
public class ExtendedPostgresDialect extends org.hibernate.dialect.PostgreSQL82Dialect {
public ExtendedPostgresDialect() {
super();
registerFunction("my_ilike", new PostgreSQLIlikeFunction());
}
}
Мы пытались использовать registerKeyword ("ILIKE"), не работал, мы остались с нашей функцией и следующее реализация.
public class PostgreSQLIlikeFunction implements SQLFunction {
@Override
public Type getReturnType(Type columnType, Mapping mapping)
throws QueryException {
return new BooleanType();
}
@SuppressWarnings("unchecked")
@Override
public String render(Type firstArgumentType, List args, SessionFactoryImplementor factory) throws QueryException {
if (args.size() != 2) {
throw new IllegalArgumentException(
"The function must be passed 2 arguments");
}
String str1 = (String) args.get(0);
String str2 = (String) args.get(1);
return str1 + " ilike " + str2;
}
@Override
public boolean hasArguments() {
return true;
}
@Override
public boolean hasParenthesesIfNoArguments() {
return false;
}
}
Это в значительной степени это, теперь мы можем использовать ILIKE следующим образом:
BooleanOperation.create(PostgresOperators.ILIKE, expression1, expression2).isTrue()
Вы можете создать индекс на 'lower (firstname)', который должен использоваться запросом (но только если подстановочные знаки находятся в конце значения сравнения). Другим вариантом было бы создать индекс триграмм: http://www.depesz.com/index.php/2011/02/19/waiting-for-9-1-faster-likeilike/ –
Спасибо, он отвечает на мои первоначальные вопрос, хотя я считаю, что борюсь с другими проблемами. Мы уже используем индексы триграмм, но похоже, что Postgre не использует ожидаемый индекс. Я попытаюсь выяснить, можем ли мы удалить конфликтный индекс (используя btree на двух столбцах), иначе я немного не буду разбираться в этой проблеме. Я также пробовал использовать тип данных citext, но анализатор запросов показывает, что индекс не используется, и поиск указывает на эту проблему, с более низким индексом в качестве решения: http://dba.stackexchange.com/questions/105244/index- on-column-with-data-type-citext-not-used/105250 # 105250 –
Прочтите это: https://wiki.postgresql.org/wiki/Slow_Query_Questions, а затем добавьте недостающую информацию в свой вопрос. Это невозможно ответить без дополнительной информации (и: это либо Postgres, PostgreSQL, либо просто pg, но никогда не Postgre) –