Подтвердить что ты не робот

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

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

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

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

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

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

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

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

# ==============================================================================================
# [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 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, или функцию, которая выбирает, какие сообщения фильтруются, или функцию, которая подготавливает списки слов и т.д. Для фильтр.

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

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

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

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

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

Соображения

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

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

Спасибо заранее,

4b9b3361

Ответ 1

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

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

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

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

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

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