Kısmi meta anahtarıyla gönderileri nasıl sorgularım?


9

Post meta olarak bir yazı için "like" durumunu depolayan bir işlevi var. Ben "gibi" onu sevdim kullanıcı ile ilişkilendirmek istiyorum, bu yüzden 0 gibi sakladığım "like_status_ {user_id}" (burada {user_id} şu anda oturum açmış olan kullanıcının kimliği) adlı özel bir alan kurmak veya 1. Bu yüzden birkaç "beğeniler" içeren bir yazı için db'de şu şekilde ayarlanmış birkaç meta değer olacaktır:

'meta_key' = 'like_status_0'
'meta_value' = 1
'meta_key' = 'like_status_2'
'meta_value' = 1
'meta_key' = 'like_status_34'
'meta_value' = 1

....ve bunun gibi.

Belirli bir gönderide potansiyel olarak binlerce beğeni vardır. Başkasının da bu gönderiyi beğenip beğenmediğini gösteren bir sorguyu nasıl çalıştırabilirim?

Ben böyle bir şey düşünüyordum:

$query = new WP_Query(array(
    'meta_key' => 'like_status_{user_id}',
    'meta_value' => 1,
));

Birisi bu gönderiyi beğendiğinde bir gönderiyi seven herkese bir bildirim göndermeye çalışıyorum ... "Hey, başka biri beğendiğiniz gönderiyi beğendi. Bunu kontrol etmelisin!" Ama başka kimsenin bu gönderiyi beğenip beğenmediğini öğrenmek için bir yola ihtiyacım var, eğer öyleyse, onları kimin bilgilendireceğini bilebilirdim.

Mümkün değilse, tek bir kullanıcının benzer durumunu bir yayında hızlı bir şekilde güncellemenin verimliliğini korurken, bu verileri post_meta olarak depolamanın daha iyi bir yolunu önerebilir misiniz?

Yanıtlar:


6

Maalesef meta_querykullanırken değer LIKEüzerinde bir karşılaştırma yapamazsınız . Bu yoldandım ...meta_keyWP_Query

Bunun yerine, özel bir tabloda kullanıcı meta ve / veya meta değil, post meta gibi durum ilişkilerini korumak istiyorsanız birkaç seçeneğiniz vardır.

seçenek 1

  • meta şemanızda değişiklik yapılmasını gerektirmez
  • wpdbözel bir sorgu gerçekleştirmek için sınıfı kullanır

Misal:

//when a user likes a post...
$current_user_id = get_current_user_id();
add_post_meta($current_user_id, "like_status_{$current_user_id}", 1, false);

//later in the request...
global $wpdb;

$results = $wpdb->get_results(
    "
    SELECT meta_key 
    FROM {$wpdb->prefix}postmeta 
    WHERE meta_key 
    LIKE 'like_status_%'
    ",
    ARRAY_N
);

$results = array_map(function($value){

    return (int) str_replace('like_status_', '', $value[0]);

}, $results);

array_walk($results, function($notify_user_id, $key){

    //apply to all users except the user who just liked the post
    if ( $notify_user_id !== $current_user_id ) {
        //notify logic here...           
    }

});

Not: İsterseniz mantık daha da basitleştirilebilir.

seçenek 2

  • meta şemanızı değiştirmenizi gerektirir
  • kullanıcı kimliğini meta değeri olarak depolamanızı gerektirir
  • WP_Queryile birlikte kullanmanıza izin verirmeta_query

Seçenek 2, meta anahtarınızı anahtara veya değerine göre like_status_{user_id}evrensel bir şeye değiştirmenizi gerektirir, bunun yerine anahtara karşı değerini depolamak yerine, kullanıcının kimliğini değer olarak depolarsınız.like_statusliked_by_user_id1

//when a user likes a post...
$current_user_id = get_current_user_id();
add_post_meta($current_user_id, "liked_by_user_id", $current_user_id, false);

//later in the request
$args = array(
    'post_type'  => 'post', //or a post type of your choosing
    'posts_per_page' => -1,
    'meta_query' => array(
        array(
            'key' => 'liked_by_user_id',
            'value' => 0,
            'type' => 'numeric'
            'compare' => '>'
        )
    )
);

$query = new WP_Query($args);   

array_walk($query->posts, function($post, $key){

    $user_ids = get_post_meta($post->ID, 'liked_by_user_id');

    array_walk($user_ids, function($notify_user_id, $key){

        //notify all users except the user who just like the post
        if ( $notify_user_id !== $current_user_id ) {

            //notify logic here...
            //get user e.g. $user = get_user_by('id', $notify_user_id);

        }

    });

});

1
Şu an 5.1'den beri aşağıdaki cevabım var
K. Tromp

@ K.Tromp Huzzah!
Adam

Lütfen kabul edilen cevabı en son WP kabiliyetini yansıtacak şekilde güncelleyin veya @ K.Tromp'un en güncel cevap olarak işaretlenmiş cevabı güncelleyin
zumek

10

Sorunuza somut olarak cevap vermek oldukça zordur. İlk kısım kolay. Geçenlerde stackoverflow'da benzer bir şey yaptım

Meta anahtarlar karşılaştırılır ve tam olarak eşleşir. WP_Querybasit bir parametre ile bu davranışı ayarlamak için hiçbir yolu var, ama biz her zaman kendimizi tanıtmak ve sonra meta anahtarları posts_wherebir LIKEkarşılaştırma yapmak için yan tümcesi ayarlayabilirsiniz .

FİLTRE

Bu sadece temel bir filtredir, gerektiği gibi ayarlayın.

add_filter( 'posts_where', function ( $where, \WP_Query $q )
{ 
    // Check for our custom query var
    if ( true !== $q->get( 'wildcard_on_key' ) )
        return $where;

    // Lets filter the clause
    $where = str_replace( 'meta_key =', 'meta_key LIKE', $where );

    return $where;
}, 10, 2 );

Gördüğünüz gibi biz yeni özel parametreyi ayarladığınızda, filtre yalnızca ateşlenir wildcard_on_keyiçin true. Bu kontroller, biz sadece değiştirdiğinizde =için karşılaştırıcı LIKEkarşılaştırıcı

Bu konuda sadece bir not, LIKEkarşılaştırmaları çalıştırmak için doğal olarak daha pahalıdır

SORGU

Meta anahtarları olan tüm yayınları almak için yayınlarınızı aşağıdaki gibi sorgulayabilirsiniz like_status_{user_id}

$args = [
    'wildcard_on_key' => true,
    'meta_query'      => [
        [
            'key'   => 'like_status_',
            'value' => 1,
        ]
    ]
];
$query = new WP_Query( $args );

DİĞER SORU

Özel alanların performans üzerinde etkisi yoktur, bu konudaki yazımı buradan okuyabilirsiniz . Ancak, her yazının yüzlerce veya binlerce beğeni alabileceğini söylemeniz beni rahatsız ediyor. Bu, bu kadar çok sayıda özel alan verisini elde etmek ve önbelleğe almak için sizi etkileyebilir. Ayrıca, db'nizi, bakımını oldukça zorlaştıran gereksiz miktarda özel alan verileriyle tıkayabilir.

Ben serileştirilmiş veri ile arama veya sipariş olamaz gibi serileştirilmiş veri özel alanlarda depolamak çok büyük bir hayranı değilim. Ancak tüm kullanıcı kimlikleri tek bir özel alan altında bir dizide depolamak öneririz. Bir kullanıcı yayını sevdiğinde diziyi kullanıcı kimliğiyle güncelleyebilirsiniz. Özel alan verilerini almak ve kimlik dizisi üzerinde döngü yapmak ve kimliklerle bir şeyler yapmak kolaydır. Sadece bir göz atget_post_meta()

Özel bir alanı güncellemek de kolaydır. Bunun için, update_post_meta()özel alanlarınızı nasıl oluşturduğunuzu bilmiyorum, ama update_post_meta()kesinlikle kullanmak istediğiniz bir şey var.

Özel bir alan güncellendiğinde e-posta veya push bildirimleri göndermeniz gerekiyorsa, aşağıdaki kancalarla çalışabilirsiniz. ( Bağlam için bakınızupdate_metadata() )

SONUÇ

Bunu göndermeden hemen önce, serileştirilmiş rotaya gitmeden önce, sıralanan verilere göre sıralamanıza veya serileştirilmiş veriler içindeki belirli verileri aramanıza gerek kalmayacağından emin olun.


1
Post_meta performansıyla ilgili açıklamanız için teşekkür ederiz! Süper kullanışlı.
codescribblr

Bu kabul edilen cevap olmalıdır, özel sorgular kullanmak yerine filtreleri kullanmak her zaman daha iyidir. Ayrıca, WP_Query yerine get_posts kullanıyorsanız, suppress_filters => false iletmeniz gerektiğini veya filtrenin tetiklenmeyeceğini unutmayın. Meta anahtarda LIKE yapmak için, hangi arama türünü yapmak istediğinize bağlı olarak% değerini dizideki anahtarın önüne ve arkasına koymanız gerekir.
Earle Davies

Mesajları sorgulamak, ancak ön ek olarak bir meta meta anahtarına sahip tüm yayınları HARİÇ ETMEK istersen nasıl filtreleyebilirsin? .? (örneğin bir post meta LIKE 'my_prefix_' sahip tüm mesajları dışlamak
bir keyif aldık

6

WordPress 5.1'den beri artık meta sorgusu kullanmak mümkün: resim açıklamasını buraya girin


Alt çizgilerin kaçması bu yöntemle ilgili bir sorun gibi görünüyor, ancak aksi takdirde oldukça iyi görünüyor. Vurgulayarak teşekkürler.
Jake

2

Daha sonra bunu daha ayrıntılı istatistikler, özellikler vb. İle genişletmek istiyorsanız, başka bir alternatif olabilir: özel tablolar

  • Artıları : İhtiyaçlarınıza göre uyarlanmıştır ve daha iyi performans için dizine eklenebilir .

  • eksileri : Daha fazla iş

Ayrıca, çekirdek tabloların nasıl dizine eklendiğinden, meta meta sonrası sorgulardan daha iyi sorgu performansı sağlayabilecek özel bir sınıflandırma kullanarak geçici bir çözüm olabilir.

Birisi bu gönderiyi beğendiğinde bir gönderiyi seven herkese bir bildirim göndermeye çalışıyorum ... "Hey, başka biri beğendiğiniz gönderiyi beğendi. Bunu kontrol etmelisin!" Ama başka kimsenin bu gönderiyi beğenip beğenmediğini öğrenmek için bir yola ihtiyacım var, eğer öyleyse, onları kimin bilgilendireceğini bilebilirdim.

Burada ne tür bildirimler kastettiğinizden emin değilim, ancak bu hızla hantal olabilir.

Örnek : ~ 1000 gönderiyi seven ve her gönderi ~ 1000 beğenme alan bir kullanıcı, borularda 1M bildirimleri var, sadece bu kullanıcı için! Bunlar e-posta bildirimleri ise, ana makine sağlayıcısı mutlu olmayabilir ve kullanıcı çıldırır. Bu, üçüncü taraf bir e-posta hizmetiyle de pahalı olabilir.


Aslında bildirimleri her kişi için yalnızca bir kez gönderiyorum. Yani göründüğünden daha az - yine de çok fazla. Yerleşik tabloları kullanmaya çalışmamın nedeni, bu verilerle gerçek bir uygulamada standart WP REST API'sini yolda kullanabilmek istiyorum.
codescribblr

-1

Başına WP_Meta_Query belgelerinde kullanabileceğiniz compareiçinde argüman meta_queryWP_Query argüman. Ancak, yalnızca üzerinde karşılaştırabilirsiniz valuedeğil keysen isteyebilirsiniz böylece bu yapısı nasıl yeniden düşünüyorum.

Bir likeargüman şöyle görünür:

$arguments = array(
    'meta_query' => array(
        array(
            'key' => 'foo',
            'value' => 'ba',
            'compare' => 'LIKE'
        )
    )
);

$query = new WP_Query($arguments);

keyKullanıcı metauna beğendiğiniz yayınları eklemenizi ve bu yayını beğenen kullanıcılar için bir WP_User_Query araması yapmanızı öneririm 'LIKE' araması yapamayacağınız göz önüne alındığında :

$arguments = array(
    'meta_query' => array(
        array(
            'key' => 'liked_post',
            'value' => '<post_id>'
        )
    )
);

$users = new WP_User_Query($arguments);
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.