Kategori Başına Sınırlı Gönderi ile Birden Çok Kategoriyi Sorgulamak için WP_Query mi Kullanıyorsunuz?


10

Her 15 yazı ile 3 kategori var, ben her kategori için sadece 5 ilk mesaj getiren db bir sorgu yapmak istiyorum, nasıl yapabilirim?

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

Mümkün değilse, üst kategori için tüm yayınları almak ve bunlardan döngü oluşturmak veya 3 farklı sorgu oluşturmak daha verimli ne olur?


Onların nasıl sipariş edilmesini istersiniz?
MikeSchinkel

kısa süre önce yayınlandı .. A kategorisinde en son 5, B kategorisinde en son şeyler vs ..
Amit

Tamam, aşağıdaki cevabımı gör
MikeSchinkel

Yanıtlar:


16

İstediğiniz şey mümkün, ancak mümkün olduğunca kaçınmak istediğim SQL'e girmenizi gerektirecek (bilmiyorum, çünkü gelişmiş bir SQL geliştiricisiyim, ancak WordPress'te mümkün olduğunca API kullanmak istiyorsunuz gelecekteki olası veritabanı yapısı değişiklikleriyle ilgili gelecekteki uyumluluk sorunlarını en aza indirmek.)

UNIONOperatörlü SQL Bir Olasılıktır

Bir ihtiyacım olan SQL kullanmak için UNION, sorgunuzdaki operatör bu kategori salyangozlar varsayarak böyle bir şey vardır "category-1", "category-1"ve "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'u bir posts_joinFiltre ile kullanabilirsiniz

Yukarıdakileri kullanarak sadece doğrudan arama yapabilir veya aşağıdaki gibi bir posts_joinfiltre kancası kullanabilirsiniz ; not Ben bir PHP yorumlu kullanıyorum bu yüzden SQL;sol floş olduğundan emin olun . Ayrıca, bir dizideki kategori sümüklü böcekleri listeleyerek, kanca dışındaki kategorileri tanımlamanıza izin vermek için genel bir değişken kullandığımı unutmayın. Bu kodu bir eklentiye veya temanızın functions.phpdosyasına koyabilirsiniz :

<?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 " ;
}

Ama Yan Etkiler Olabilir

Tabii ki sorgu değiştirme kancalarını posts_joinher zaman olduğu gibi kullanmak, yan etkileri davet eder ve küresel olarak sorgulara etki eder ve bu nedenle değişikliklerinizi genellikle ifyalnızca gerektiğinde kullanan ve test etmek için hangi ölçütlerin zor olabileceği bir şekilde sarmanız gerekir .

Bunun yerine Optimizasyona mı odaklanıyorsunuz?

Ancak, sorunuzun en iyi 5 zaman 3 sorgusu yapabilmekten daha fazla optimizasyonla ilgili olduğunu varsayalım , değil mi? Durum buysa, WordPress API'sini kullanan başka seçenekler de olabilir mi?

Geçici Önbellek API'sı Önbellek için Daha İyi?

Gönderilerinizin bu kadar sık ​​değişmeyeceğini düşünüyorum, değil mi? Üç (3) sorguyu isabetli olarak periyodik olarak kabul ederseniz ve sonuçları Geçici Geçişler API'sını kullanarak önbelleğe alırsanız ne olur ? Sürdürülebilir kod ve mükemmel performans elde edersiniz; UNIONWordPress, yazı listelerini wp_optionstablonun bir kaydında serileştirilmiş bir dizi olarak saklayacağından yukarıdaki sorgudan biraz daha iyidir .

Bunu test.phptest etmek için aşağıdaki örneği alıp web sitenizin kök dizinine bırakabilirsiniz :

<?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);

özet

Evet olsa da, bir SQL UNIONsorgusu ve posts_joinfiltre kancası kullanarak istediğinizi yapabilirsiniz, bunun yerine Transients API ile önbelleğe almayı kullanarak muhtemelen daha iyi teklif verebilirsiniz .

Bu yardımcı olur umarım?


2
Geçici geçişler yoluyla önbellekleme, sitedeki etkiyi azaltmak için iyi bir şeydir.
hakre

1
@ Geçişler'i kullanmak için harika bir fikir.
Chris_O

@Mike, eğer kıtada yaşıyor olsaydım seninle dersler alırdım! Tekrar teşekkürler!
Amit

@Amit: LOL! :-)
MikeSchinkel

1
Ayrıca geçici süreyi süresiz olarak kaydedip daha sonra save_post'ta yıkayabilir misiniz? kodeksinde iyi bir örnek var (edit_term hook kullanarak)
helgatheviking

1

WP_Query()Her Kedi İçin İlk X gibi bir şeyi desteklemez . Bunun yerine, kategorilerinizin her birinde üç kez söylemek için WP_Query()kullanabilirsiniz get_posts():

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

$posts artık her kategori için ilk beş gönderiyi içeriyor.


db için 3 hit değil mi? Bunu 1 vuruşta yapabilir misin bilmek istedim çünkü daha verimli olduğunu düşündüm.
Amit

Peki db bunun için, değil mi? ondan veri sorgula. db böyle şeyler için yapılır. muhtemelen sormak karmaşık bir sql sorgusu çalıştırmak daha hızlıdır. şeyleri kullanmaktan korkmayın. sitenizi bozarsa, buraya bildirin.
hakre

mm .. anladım, php / mysql / db verimliliği hakkında daha fazla şey bilmiyorum (daha fazla okumak istiyorum), daha az hit daha iyi olduğundan emin oldum ve sonra sonucu kendim ayrıştırmak.
Amit

1
iyi, doğru, genellikle daha fazla ve daha az daha az. Ama önce deneyin ve test edin. Yazılımınız "ne kadar kötü" ise, optimizasyon için o kadar fazla potansiyele sahiptir. Böylece daha iyi öğrenebilirsiniz, çünkü sonunda daha iyi yazılımı daha hızlı ve daha iyi yazılımı daha hızlı yazacaksınız.
hakre

0

Tek bir sorguda kategorilerin her biri için ilk beş mesaj almanın bir yolunu bilmiyorum. Şimdiye kadar sadece 45 yayın alacaksanız, veritabanına bir kez vurmak ve her kategori için beş yayınınızı almak muhtemelen en etkili yaklaşımdır. Veritabanına üç kez vurmak ve sonuçları birleştirmek kötü bir şey değildir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.