Как реализовать кэширование на стороне сервера для автозаполнения в приложении ZF2?

Сначала фактическое состояние: Есть приложение ZF2 с формой. Форма содержит несколько полей автозаполнения (реализовано на стороне интерфейса JQuery Автозаполнение).

Операторы SQL, стоящие за ним, выглядят так:

SELECT name FROM countries WHERE countries.name LIKE %en%
-> should find "Arg[en]tina", "Arm[en]ia", "B[en]in", "Turkm[en]istan" etc.
or
SELECT name FROM countries WHERE countries.continent_id = 2
-> should find "Afghanistan", "Armenia", "Azerbaijan" etc. (2 = Asia)
or
SELECT name FROM countries WHERE countries.continent_id = 2 AND countries.name LIKE %en%
-> should find "Arm[en]ia", "Turkm[en]istan" etc. (2 = Asia)

Конечно, это приводит к проблема, что база данных терзается множеством мелких запросов автозаполнения. Кэширование должно помочь — и я уже начал реализовывать Zend\Cache\Storage\Adapter\Apcuмеханизм кэширования Но потом я увидел следующую проблему: использование общего кеша вроде APCu Я не могу фильтровать результаты динамически. Таким образом, такой кеш, похоже, не работает для случая с автозаполнением.

Я уверен, что это общая проблема, и решение для этого уже есть.

Как реализовать механизм кэширования в приложении ZF2 для функции автозаполнения?

1

Решение

Здесь нет ничего общего с ZF2. Все дело в индивидуальном дизайне службы поиска и его проблемах.

Без надлежащего уровня кэширования и / или механизма полнотекстового поиска, создание реализации автозаполнения, такой, что было бы самоубийством для приложения. Вы можете легко выполнить десятки тысяч ненужных повторных запросов за очень короткое время.

В «идеальном» мире хорошая реализация автозаполнения использует механизм полнотекстового поиска, такой как Elasticsearch или же Apache Solr. И использует их Завершение предложения а также Suggester компоненты соответственно.

В любом случае простая функция автозаполнения все еще достижима, используя только кэш объектов и базу данных. Только вам нужен вспомогательный метод для создания правильного «ключа кеша» для каждой комбинации букв. Например:

   function createKeyByQuery($str)
{
return 'autocomplete-prefix-'.(string) $str;
}

и в вашем suggest() метод:

   public function suggest($keyword)
{
$key = $this->createKeyByQuery($keyword);
if($this->cache->hasItem($key)) {
return $this->cache->getItem($key);
}

// fetch form the database here
$data = $this->db->query();
$this->cache->setItem($key, $data);

return $data;
}

Если количество ваших фильтров не слишком велико, просто сделайте их частью ключа. В этом сценарии подпись метода предложить будет:

  public function suggest($keyword, array $filters = []);

и генератор ключей нуждается в обновлении:

   function createKeyByQuery($str, array $filters = [])
{
return 'autocomplete-prefix-' . (string) $str . md5(serialize($filters));
}

Это решение может не подходить для сложных / связанных с доменом данных, потому что оно имеет довольно большую проблему аннулирования. Например. Как бы вы нашли ключи кеша, в которых хранится «Аргентина» в полезной нагрузке?

Поскольку вы имеете дело только со списком стран и континентов в качестве фильтра, это должно решить проблему.

Для england ключевое слово и два разных фильтра с общим количеством 10 опций фильтра, будет 10x2x7 = 140 различных ключей кэша. Для одного фильтра с 5 опциями 5x1x7 = 37 различных ключей.

APCu — хороший выбор для этой реализации.

Надеюсь, поможет.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]