Intereting Posts
PHP -Sanitize значения массива Laravel: как использовать производные таблицы / подзапросы в построителе запросов laravel Как работает подобный_текст? PHP включает без вывода? Сохраните переменные PHP в текстовый файл PHP: как я могу заблокировать прямой доступ к URL-адресу для файла, но все-таки разрешить его загрузку вошедшим в систему пользователям? Ошибка отображения IE в файле prototype.js. 1597 Как избежать добавления одного и того же шаблона навигатора на каждую страницу .html Laravel 5 – ошибка синтаксиса Php-Artisan Mysql Real Escape String PHP-функция Добавление «\» в «Моя полевая запись» Одновременное выполнение нескольких скриптов PHP (проблема с циклом базы данных) PHP получает выбранные строки таблицы из флажков MYSQL Select Query с SUM () изменение URL страницы без обновления страницы Интерфейсы и наследование абстрактного класса, реализация в расширенных классах

Как мне создать эффективный контент-фильтр для определенных сообщений?

Я отметил этот пост как WordPress, но я не совсем уверен, что он специфичен для WordPress, поэтому я отправляю его на StackOverflow, а не в WPSE. Решение не обязательно должно быть специфичным для WordPress, просто PHP .

Сценарий
Я управляю веб-сайтом по рыбному хозяйству с помощью ряда Species Profiles и Glossary тропической рыбы.

Наш сайт ориентирован на наши профили. Они, как вы можете это назвать, хлеб и масло сайта.

Я надеюсь, что в каждом видовом профиле, в котором упоминается другой вид или глоссарий, я могу заменить эти слова ссылкой – например, вы увидите здесь . В идеале, мне также хотелось бы, чтобы это происходило в новостях, статьях и сообщениях в блогах.

У нас есть почти 1400 species profiles и 1700 glossary entries . Наши профили видов часто длинные и, по последним подсчетам, только наши виды видов numbered more than 1.7 million words информации.

Что я сейчас пытаюсь
В настоящее время у меня есть filter.php с функцией, которая, я считаю, делает то, что мне нужно. Код довольно длинный, и его можно найти здесь полностью.

Кроме того, в моем functions.php темы WordPress у меня есть следующее:

 # ============================================================================================== # [Filter] # # Every hour, using WP_Cron, `my_updated_posts` is checked. If there are new Post IDs in there, # it will run a filter on all of the post's content. The filter will search for Glossary terms # and scientific species names. If found, it will replace those names with links including a # pop-up. include "filter.php"; # ============================================================================================== # When saving a post (new or edited), check to make sure it isn't a revision then add its ID # to `my_updated_posts`. add_action( 'save_post', 'my_set_content_filter' ); function my_set_content_filter( $post_id ) { if ( !wp_is_post_revision( $post_id ) ) { $post_type = get_post_type( $post_id ); if ( $post_type == "species" || ( $post_type == "post" && in_category( "articles", $post_id ) ) || ( $post_type == "post" && in_category( "blogs", $post_id ) ) ) { //get the previous value $ids = get_option( 'my_updated_posts' ); //add new value if necessary if( !in_array( $post_id, $ids ) ) { $ids[] = $post_id; update_option( 'my_updated_posts', $ids ); } } } } # ============================================================================================== # Add the filter to WP_Cron. add_action( 'my_filter_posts_content', 'my_filter_content' ); if( !wp_next_scheduled( 'my_filter_posts_content' ) ) { wp_schedule_event( time(), 'hourly', 'my_filter_posts_content' ); } # ============================================================================================== # Run the filter. function my_filter_content() { //check to see if posts need to be parsed if ( !get_option( 'my_updated_posts' ) ) return false; //parse posts $ids = get_option( 'my_updated_posts' ); update_option( 'error_check', $ids ); foreach( $ids as $v ) { if ( get_post_status( $v ) == 'publish' ) run_filter( $v ); update_option( 'error_check', "filter has run at least once" ); } //make sure no values have been added while loop was running $id_recheck = get_option( 'my_updated_posts' ); my_close_out_filter( $ids, $id_recheck ); //once all options, including any added during the running of what could be a long cronjob are done, remove the value and close out delete_option( 'my_updated_posts' ); update_option( 'error_check', 'working m8' ); return true; } # ============================================================================================== # A "difference" function to make sure no new posts have been added to `my_updated_posts` whilst # the potentially time-consuming filter was running. function my_close_out_filter( $beginning_array, $end_array ) { $diff = array_diff( $beginning_array, $end_array ); if( !empty ( $diff ) ) { foreach( $diff as $v ) { run_filter( $v ); } } my_close_out_filter( $end_array, get_option( 'my_updated_posts' ) ); } 

То, как это работает, как (надеюсь), описывается комментариями кода, заключается в том, что каждый час WordPress управляет заданием cron (которое подобно ложному cron – работает с пользовательскими хитами, но это не имеет особого значения, поскольку время не является важный), который запускает фильтр, найденный выше.

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

Проблема…
В течение нескольких месяцев у меня возникали проблемы с надежной работой этого фильтра. Я не считаю, что проблема связана с самим фильтром, но с одной из функций, которые позволяют фильтровать, то есть задание cron, или функцию, которая выбирает, какие сообщения фильтруются, или функцию, которая подготавливает списки слов и т. Д. Для фильтр.

К сожалению, диагностировать проблему довольно сложно (что я вижу), благодаря чему она работает в фоновом режиме и только на почасовой основе. Я пытаюсь использовать функцию update_option WordPress (которая в основном записывает простое значение базы данных) для проверки ошибок, но мне не повезло – и, честно говоря, я довольно смущен относительно того, где проблема ,

Мы закончили тем, что веб-сайт работал без фильтра. Иногда это работает, иногда это не так. В результате у нас теперь имеется довольно много профилей видов, которые неправильно фильтруются.

Что мне понравится …
Я в основном ищу совет по наилучшему способу запускать этот фильтр.

Ответ на вопрос Cron? Я могу настроить файл .php который запускается каждый день, это не будет проблемой. Как определить, какие сообщения нужно отфильтровать? Какое влияние это окажет на сервер в момент его запуска?

В качестве альтернативы, это страница администратора WordPress? Если бы я знал, как это сделать, то что-то вроде строки страницы, использующей AJAX, которая позволяла мне выбирать столбы для запуска фильтра, была бы идеальной. Есть плагин под названием AJAX Regenerate Thumbnails который работает так, может быть, это будет наиболее эффективным?

Соображения

  • Размер базы данных / информации, которая затрагивается / читается / записывается
  • Какие сообщения отфильтрованы
  • Влияние фильтра на сервер; особенно учитывая, что я, кажется, не могу увеличить предел памяти WordPress за 32 Мб.
  • Является ли фактический фильтр эффективным, эффективным и надежным?

Это довольно сложный вопрос, и я неизбежно (поскольку я был отвлечен примерно 18 раз коллегами в этом процессе) не учитывал некоторые детали. Пожалуйста, не стесняйтесь исследовать меня для получения дополнительной информации.

Заранее спасибо,

Solutions Collecting From Web of "Как мне создать эффективный контент-фильтр для определенных сообщений?"

Сделайте это, когда профиль создан.

Попробуйте изменить весь процесс. Вместо проверки содержимого для слов проверьте слова для слов контента.

  1. Разбивать содержимое сообщения при вводе в слова (в пространстве)
  2. Устраните дубликаты, те, которые находятся под наименьшим размером слова в базе данных, те, которые имеют наибольший размер, и те, которые вы сохранили в списке общих слов.
  3. Проверяйте каждую таблицу, если некоторые из ваших таблиц содержат фразы с пробелами, выполните поиск% text%, в противном случае выполните прямое совпадение (намного быстрее) или даже создайте хеш-таблицу, если это действительно большая проблема. (Я бы сделал это как массив PHP и каким-то образом кешировал результат, не имея смысла изобретать колесо)
  4. Создайте свои ссылки с теперь значительно меньшими списками.

Вы должны быть в состоянии легко сохранить это менее 1 секунды, даже когда вы переходите на 100 000 слов, которые вы проверяете. Я сделал именно это, не кэшируя списки слов, для байесовского фильтра раньше.

С меньшим списком, даже если он жадный и собирает слова, которые не соответствуют «клоуну», он поймает «клоун-лоуч», в результате меньший список должен содержать от нескольких до нескольких десятков слов со ссылками. Который не займет времени вообще, чтобы найти и заменить над куском текста.

Вышеупомянутое не отражает вашу озабоченность более старыми профилями. Вы точно не знаете, сколько их есть, просто есть много текста и что он находится на 1400-331 (оба элемента). Это более старое содержимое, которое вы могли бы сделать, основываясь на популярности, если у вас есть информация. Или по дате введено, новее сначала. Независимо от того, лучший способ сделать это – написать скрипт, который приостанавливает ограничение времени на PHP и просто выполняет пакетный запуск загрузки / процесса / сохранения на всех постах. Если каждый занимает около 1 секунды (возможно, гораздо меньше, но хуже), вы говорите 3100 секунд, что составляет немногим меньше часа.