ใช้ WP_Query เพื่อค้นหาหลายหมวดหมู่กับโพสต์ที่ จำกัด ต่อหมวด


10

ฉันมี 3 หมวดหมู่พร้อมกับการโพสต์ 15 รายการฉันต้องการทำแบบสอบถามหนึ่งรายการให้กับฐานข้อมูลที่นำเสนอเพียง 5 โพสต์แรกสำหรับแต่ละหมวดหมู่ฉันจะทำอย่างไร

$q = new WP_Query(array( 'post__in' => array(2,4,8), 'posts_per_page' => **FIRST_5_OF_EACH_CAT** ));

ในกรณีที่ไม่สามารถทำได้มีประสิทธิภาพมากขึ้นรับโพสต์ทั้งหมดสำหรับหมวดหมู่ผู้ปกครองและวนรอบพวกเขาหรือการสร้าง 3 แบบสอบถามที่แตกต่างกันอย่างไร


คุณต้องการให้สั่งซื้ออย่างไร
MikeSchinkel

เผยแพร่เมื่อเร็ว ๆ นี้ .. ดังนั้นล่าสุด 5 หมวดหมู่ A, สิ่งล่าสุดของหมวด B ฯลฯ ..
Amit

ตกลงดูคำตอบของฉันด้านล่าง
MikeSchinkel

คำตอบ:


16

สิ่งที่คุณต้องการเป็นไปได้ แต่จะทำให้คุณต้องเจาะลึกลงไปในSQL ที่ฉันต้องการหลีกเลี่ยงเมื่อใดก็ตามที่เป็นไปได้ (ไม่ใช่เพราะฉันไม่รู้ฉันเป็นนักพัฒนา SQL ขั้นสูง แต่เนื่องจากใน WordPress คุณต้องการใช้ API เมื่อทำได้เพื่อลดปัญหาความเข้ากันได้ในอนาคตที่เกี่ยวข้องกับการเปลี่ยนแปลงโครงสร้างฐานข้อมูลที่อาจเกิดขึ้นในอนาคต)

SQL ที่มีตัวUNIONดำเนินการเป็นไปได้

การใช้ SQL สิ่งที่คุณต้องการเป็นUNIONผู้ประกอบการในการค้นหาของคุณบางอย่างเช่นสมมตินี้ทากหมวดหมู่ของคุณมี"category-1", "category-1"และ"category-3":

SELECT * FROM wp_posts WHERE ID IN (
  SELECT tr.object_id
  FROM wp_terms t 
  INNER JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
  INNER JOIN wp_term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
  WHERE tt.taxonomy='category' AND t.slug='category-1'
  LIMIT 5

  UNION

  SELECT tr.object_id
  FROM wp_terms t 
  INNER JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
  INNER JOIN wp_term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
  WHERE tt.taxonomy='category' AND t.slug='category-2'
  LIMIT 5

  UNION

  SELECT tr.object_id
  FROM wp_terms t 
  INNER JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
  INNER JOIN wp_term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
  WHERE tt.taxonomy='category' AND t.slug='category-3'
  LIMIT 5
)

คุณสามารถใช้ SQL UNION กับposts_joinตัวกรองได้

การใช้ด้านบนคุณสามารถโทรออกได้โดยตรงหรือคุณสามารถใช้posts_joinตะขอตัวกรองดังนี้ หมายเหตุฉันใช้PHP heredocเพื่อให้แน่ใจว่าSQL;จะล้างซ้าย นอกจากนี้โปรดทราบว่าฉันใช้ var ส่วนกลางเพื่อให้คุณสามารถกำหนดหมวดหมู่ภายนอก hook ได้โดยแสดงทากหมวดหมู่ในอาร์เรย์ คุณสามารถใส่รหัสนี้ในปลั๊กอินหรือในfunctions.phpไฟล์ธีมของคุณ:

<?php
global $top_5_for_each_category_join;
$top_5_for_each_category_join = array('category-1','category-2','category-3');
add_filter('posts_join','top_5_for_each_category_join',10,2);
function top_5_for_each_category_join($join,$query) {
  global $top_5_for_each_category_join;
  $unioned_selects = array();
  foreach($top_5_for_each_category_join as $category) {
    $unioned_selects[] =<<<SQL
SELECT object_id
FROM wp_terms t
INNER JOIN wp_term_taxonomy tt ON t.term_id = tt.term_id
INNER JOIN wp_term_relationships tr ON tt.term_taxonomy_id = tr.term_taxonomy_id
WHERE tt.taxonomy='category' AND t.slug='{$category}'
LIMIT 5
SQL;
  }
  $unioned_selects = implode("\n\nUNION\n\n",$unioned_selects);
  return $join . " INNER JOIN ($unioned_selects) categories ON wp_posts.ID=categories.object_id " ;
}

แต่อาจมีผลข้างเคียง

แน่นอนว่าการใช้ hooks การแก้ไขแบบสอบถามอย่างเช่นposts_joinจะเชิญผลข้างเคียงในการที่พวกเขากระทำทั่วโลกเกี่ยวกับการค้นหาและดังนั้นคุณมักจะต้องห่อการปรับเปลี่ยนของคุณในการifที่จะใช้มันเมื่อจำเป็นเท่านั้นและเกณฑ์การทดสอบอะไรจะยุ่งยาก

มุ่งเน้นที่การเพิ่มประสิทธิภาพแทนหรือไม่

อย่างไรก็ตามฉันคิดว่าคำถามของคุณเป็นเรื่องเกี่ยวกับการเพิ่มประสิทธิภาพมากกว่าเกี่ยวกับความสามารถในการทำแบบสอบถาม 5 ครั้ง 3 ด้านบนใช่มั้ย หากเป็นเช่นนั้นอาจมีตัวเลือกอื่น ๆ ที่ใช้ WordPress API หรือไม่

ดีกว่าการใช้ Transients API สำหรับการแคชหรือไม่

ฉันคิดว่าโพสต์ของคุณจะไม่เปลี่ยนแปลงอย่างนั้นใช่ไหม? เกิดอะไรขึ้นถ้าคุณยอมรับสาม (3) แบบสอบถามตีเป็นระยะ ๆ แล้วแคชผลโดยใช้Transients API ? คุณจะได้รหัสที่สามารถบำรุงรักษาได้และประสิทธิภาพที่ยอดเยี่ยม ดีกว่าUNIONแบบสอบถามข้างต้นเล็กน้อยเนื่องจาก WordPress จะจัดเก็บรายการโพสต์เป็นอาร์เรย์ลำดับในหนึ่งระเบียนของwp_optionsตาราง

คุณสามารถนำตัวอย่างต่อไปนี้และวางลงในรูทเว็บไซต์ของคุณtest.phpเพื่อทดสอบ:

<?php

$timeout = 4; // 4 hours
$categories = array('category-1','category-2','category-3');

include "wp-load.php";
$category_posts = get_transient('top5_posts_per_category');
if (!is_array($category_posts) || count($category_posts)==0) {
  echo "Hello Every {$timeout} hours!";
  $category_posts = array();
  foreach($categories as $category) {
    $posts = get_posts("post_type=post&numberposts=5&taxonomy=category&term={$category}");
    foreach($posts as $post) {
      $category_posts[$post->ID] = $post;
    }
  }
  set_transient('top5_posts_per_category',$category_posts,60*60*$timeout);
}
header('Content-Type:text/plain');
print_r($category_posts);

สรุป

ในขณะที่ใช่คุณสามารถทำสิ่งที่คุณขอใช้UNIONแบบสอบถามSQL และposts_joinตัวกรองเบ็ดคุณน่าจะดีกว่าเสนอใช้แคชกับTransients APIแทน

หวังว่าจะช่วยได้ไหม


2
การแคชผ่านผู้ใช้ชั่วคราวเป็นสิ่งที่ดีในการลดผลกระทบต่อไซต์
hakre

1
@ ไมค์ความคิดที่ดีในการใช้ Transients
Chris_O

@ ไมค์ถ้าฉันอาศัยอยู่ในทวีปของคุณฉันจะเรียนกับคุณ! ขอบคุณอีกครั้ง!
Amit

@Amit: ฮ่า ๆ ! :-)
MikeSchinkel

1
คุณสามารถบันทึกชั่วคราวได้ไม่ จำกัด และล้างมันใน save_post หรือไม่ มีตัวอย่างที่ดี (โดยใช้ edit_term hook) ใน codex
helgatheviking

1

WP_Query()ไม่รองรับบางอย่างเช่นFirst X สำหรับแมวแต่ละตัว แทนที่จะWP_Query()ใช้get_posts()ในแต่ละหมวดหมู่ของคุณดังนั้นให้พูดสามครั้ง:

<?php
$posts      = array():
$categories = array(2,4,8);
foreach($categories as $cat) {
  $posts[] = get_posts('numberposts=5&offset=1&category='.$cat);
}
?>

$posts ตอนนี้มีห้าบทความแรกสำหรับแต่ละหมวดหมู่


นั่นไม่ใช่เพลงฮิตถึง db หรือเปล่า? ฉันอยากรู้ว่าคุณสามารถทำได้ใน 1 ครั้งเพราะฉันคิดว่ามันมีประสิทธิภาพมากกว่า
Amit

นั่นคือสิ่งที่ฐานข้อมูลมีไว้ใช่มั้ย สอบถามข้อมูลจากมัน db ถูกสร้างขึ้นมาสำหรับสิ่งต่าง ๆ มันอาจจะเร็วกว่าแล้วเรียกใช้คิวรี SQL ที่ซับซ้อนที่คุณต้องการ อย่ากลัวที่จะใช้สิ่งของ ถ้าเว็บไซต์ของคุณพังให้รายงานที่นี่
hakre

อืมมมเข้าใจแล้วฉันไม่รู้มากเกี่ยวกับประสิทธิภาพของ php / mysql / db (ต้องการอ่านเพิ่มเติม) แน่ใจว่าการเข้าชมน้อยกว่าจะดีกว่าและแยกวิเคราะห์ผลลัพธ์ด้วยตัวเอง
Amit

1
ดีจริงโดยทั่วไปมากขึ้นและน้อยลงน้อย แต่ลองทดสอบก่อน ซอฟต์แวร์ของคุณ "แย่ลง" ยิ่งมีโอกาสในการเพิ่มประสิทธิภาพมากขึ้นเท่านั้น ดังนั้นเรียนรู้ที่ดีขึ้นด้วยการทำเพราะในที่สุดคุณจะเขียนซอฟต์แวร์ได้ดีขึ้นเร็วขึ้นและเขียนซอฟต์แวร์ได้เร็วขึ้น
hakre

0

ฉันไม่รู้วิธีรับห้าโพสต์แรกสำหรับแต่ละหมวดหมู่ในการค้นหาเดียว หากคุณเคยมีเพียง 45 โพสต์การกดปุ่มฐานข้อมูลหนึ่งครั้งและการโพสต์ห้าโพสต์สำหรับแต่ละหมวดหมู่อาจเป็นวิธีที่มีประสิทธิภาพที่สุด การกดฐานข้อมูลสามครั้งและรวมผลลัพธ์เข้าด้วยกันไม่ใช่เรื่องเลวร้ายอะไร

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.