WordPress中高效筛选关联Product的Partner优化查询性能的方法
解决方案:高效获取有关联产品的合作伙伴
核心结论
给Partner添加存储关联Product数量的元字段确实是更高效的方案,能将原来的N次数据库查询(N为Partner数量)降到1次查询,大幅提升性能。此外也可以通过自定义SQL联合查询实现,无需额外维护元字段,两种方案各有优势,以下是具体实现:
方案一:通过元字段维护关联数量(性能最优)
1. 同步Product与Partner的关联数量
在Product保存、更新或删除时,自动更新对应Partner的关联产品计数:
// 保存/更新Product时同步Partner计数 add_action('save_post_product', 'sync_partner_product_count', 10, 3); function sync_partner_product_count($post_id, $post, $update) { // 跳过自动保存或修订版本 if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) { return; } // 获取当前Product关联的旧Partner ID(更新时需要处理) $old_partner_id = get_post_meta($post_id, 'partner', true); // 获取新的Partner ID $new_partner_id = isset($_POST['partner']) ? sanitize_text_field($_POST['partner']) : ''; // 处理旧关联:如果之前有Partner,计数减1 if ($old_partner_id && $old_partner_id !== $new_partner_id) { $current_count = get_post_meta($old_partner_id, 'product_count', true); $new_count = max(0, (int)$current_count - 1); update_post_meta($old_partner_id, 'product_count', $new_count); } // 处理新关联:如果有新Partner,计数加1 if ($new_partner_id) { $current_count = get_post_meta($new_partner_id, 'product_count', true); $new_count = (int)$current_count + 1; update_post_meta($new_partner_id, 'product_count', $new_count); } } // 删除Product时同步Partner计数 add_action('before_delete_post', 'decrement_partner_product_count'); function decrement_partner_product_count($post_id) { $post_type = get_post_type($post_id); if ($post_type !== 'product') { return; } $partner_id = get_post_meta($post_id, 'partner', true); if ($partner_id) { $current_count = get_post_meta($partner_id, 'product_count', true); $new_count = max(0, (int)$current_count - 1); update_post_meta($partner_id, 'product_count', $new_count); } }
2. 查询符合条件的Partner生成下拉框
直接查询带有product_count>0的Partner,一次查询即可生成下拉框:
// 查询有关联产品的Partner $args = array( 'post_type' => 'partner', 'post_status' => 'publish', 'posts_per_page' => -1, 'meta_query' => array( array( 'key' => 'product_count', 'value' => 0, 'compare' => '>', 'type' => 'numeric' ) ), 'orderby' => 'title', 'order' => 'ASC' ); $partner_query = new WP_Query($args); // 生成select下拉框 echo '<select name="partner_filter">'; echo '<option value="">选择合作伙伴</option>'; if ($partner_query->have_posts()) { while ($partner_query->have_posts()) { $partner_query->the_post(); $count = get_post_meta(get_the_ID(), 'product_count', true); echo '<option value="' . get_the_ID() . '">' . get_the_title() . ' (' . $count . '个产品)</option>'; } } wp_reset_postdata();
方案二:自定义SQL联合查询(无需额外元字段)
如果不想维护额外的元字段,可以通过一次SQL查询直接获取有关联Product的Partner及其数量:
global $wpdb; // 自定义SQL查询,注意表前缀会自动适配你的WP配置 $query = $wpdb->prepare(" SELECT p.ID, p.post_title, COUNT(p2.ID) AS product_count FROM {$wpdb->posts} p JOIN {$wpdb->postmeta} pm ON p.ID = pm.meta_value JOIN {$wpdb->posts} p2 ON pm.post_id = p2.ID WHERE p.post_type = 'partner' AND p.post_status = 'publish' AND pm.meta_key = 'partner' AND p2.post_type = 'product' AND p2.post_status = 'publish' GROUP BY p.ID, p.post_title HAVING product_count > 0 ORDER BY p.post_title ASC "); $partners = $wpdb->get_results($query); // 生成select下拉框 echo '<select name="partner_filter">'; echo '<option value="">选择合作伙伴</option>'; foreach ($partners as $partner) { echo '<option value="' . $partner->ID . '">' . esc_html($partner->post_title) . ' (' . $partner->product_count . '个产品)</option>'; } echo '</select>';
当前代码的优化提示
你当前的代码使用LIKE匹配Partner ID,如果存储的是纯数字ID,建议改为compare' => '=',LIKE会导致数据库索引失效,进一步降低查询性能;同时循环几百个Partner的方式会产生大量重复查询,必须避免。
内容的提问来源于stack exchange,提问作者Chris Pink
相关产品推荐
相关产品推荐

