首页 > 解决方案 > 使用第三方服务填充和搜索 WordPress 帖子

问题描述

我使用第三方服务将帖子填充到我的 WordPress 网站中。来自服务的大部分信息存储为 WordPress 帖子属性(标题、内容、图像等),但其中一些信息存储为帖子元数据(每个帖子和其他元数据的服务唯一标识符)。这些服务提供半径搜索以查找在给定位置内匹配的帖子,并返回匹配帖子的 ID。我的目标是获取这些 ID 并从 WP 帖子返回分页结果集,以便所有内容都像 WP 站点中的任何其他搜索页面一样格式化。我有一个可行的实现,但速度很慢,我正在寻找有关如何加快速度的建议,或者不同的方法来实现我的目标。

我当前的实现对服务上所有匹配的帖子进行了分页循环(这可能返回 10 个结果或 1000 个结果)。然后我从该结果集中获取 ID 并将它们传递到 WP Query 以通过 ID 的元值来限制请求。来自服务的数据集越大,请求就越慢。我这样做是为了让我能够利用 WP 的分页。如果我只在分页结果中返回一个页面,WordPress 就不会知道还有更多的结果需要分页。任何有关如何使此过程更高效的建议或建议将不胜感激。

这是我到目前为止的代码。它目前有效,但如前所述,服务中的数据集越大,请求所需的时间就越长:

<?php

class Search {
    const SEARCH_PREFIX = 'test';
    protected static $api_params_whitelist = [
        'search',
        'near_zip',
        'near_city',
        'radius',
        'featured_only',
        'currently_listed_only',
        'registrable_only',
        'page',
        'per_page',
        'sort'
    ];

    public static function radius_search($query) {
        $field_prefix = Search::SEARCH_PREFIX;
        $search = $query->get($field_prefix . 'term');
        $location = $query->get($field_prefix . 'location');
        $radius = $query->get($field_prefix . 'radius');
        
        if (
            $query->is_main_query()
            && (strlen($location) > 0)
        ) {
            // Lookup result IDs for radius.
            if ($resultIds = self::get_result_ids($search, $location, $radius)) {
                $query->set( 'meta_query',  array(
                    // Search for the result id stored in `post_meta`.
                    array(
                        'key'     => 'id',
                        'value'   => $resultIds,
                        'compare' => 'IN',
                    ),
                ) );
            } else {
                // Force no results
                $query->set( 'post__in', array(0) );
            }
        } elseif ( strlen( $search ) > 0 ) {
            // Fallback to standard WP search w/o radius search
            $query->set( 's', $search );
        }
    }

    public static function add_query_vars_filter( $vars ) {
        $field_prefix = Search::SEARCH_PREFIX;

        $query_variables = [
            $field_prefix . 'term',
            $field_prefix . 'location',
            $field_prefix . 'radius'
        ];

        foreach ($query_variables as $var) {
            $vars[] = $var;
        }
        
        return $vars;
    }

    private static function get_api_handler() {
        $credentials = Synchronize::get_credentials();

        if( !isset( $credentials['subdomain'] ) ) {
            return false;
        }

        $api = new \My_Api( $credentials['subdomain'] );
        $api->setTimeoutInSeconds( 10 );

        return $api;
    }

    private static function get_result_ids($search, $location, $radius) {
        $api = self::get_api_handler();

        $page = 1;
        $per_page = 60;
        $results = [];

        $params = $_GET;
        $params['per_page'] = $per_page;

        $query_params = $api->getQueryParams( $params, Search::SEARCH_PREFIX, self::$api_params_whitelist );

        do {
            $query_params['page'] = $page;
            $query_params['fields'] = [
                'id'
            ];

            $results = $api->get( '/search', $query_params );
            $resultCount = count($results);

            if ($results && $resultCount > 0) {
                $results = array_merge($results, $results);
            }
            $page++;
        } while ($results && $resultCount > 0);
        
        if (count($results)) {
            return array_column($results, 'id');
        }

        return false;
    }
}

标签: phpwordpressapi

解决方案


推荐阅读