Bagaimana cara meminta posting dengan kunci meta parsial?

9

Saya memiliki fungsi yang menyimpan status "suka" untuk pos sebagai pos meta. Saya ingin mengaitkan "suka" itu dengan pengguna yang menyukainya, jadi saya menyiapkan bidang khusus yang disebut "like_status_ {user_id}" (di mana {user_id} adalah id dari pengguna yang saat ini masuk) yang saya simpan sebagai 0 atau 1. Jadi untuk posting dengan beberapa "suka" akan ada beberapa nilai meta di db yang diatur seperti ini:

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

....dan seterusnya.

Ada ribuan kemungkinan suka pada posting tertentu. Bagaimana saya menjalankan kueri yang menunjukkan jika orang lain juga menyukai posting itu?

Saya sedang memikirkan sesuatu seperti ini:

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

Saya mencoba untuk mendorong pemberitahuan kepada semua orang yang menyukai posting ketika orang lain menyukai posting itu ... sesuatu seperti, "Hei, orang lain menyukai posting yang Anda sukai. Anda harus memeriksanya!" Tetapi saya perlu cara untuk mengetahui apakah ada orang lain yang menyukai pos itu dan jika demikian, siapa mereka sehingga saya bisa memberi tahu mereka.

Jika tidak memungkinkan, dapatkah Anda menyarankan cara yang lebih baik untuk menyimpan data ini sebagai post_meta sambil tetap menjaga efisiensi dengan cepat memperbarui status suka pengguna tunggal pada posting?

codescribblr
sumber

Jawaban:

6

Sayangnya Anda tidak dapat melakukan meta_querydengan menggunakan LIKEperbandingan pada meta_keynilai saat menggunakan WP_Query. Saya sudah menyusuri jalan ini ...

Alih-alih, Anda memiliki beberapa opsi lain jika Anda ingin mempertahankan hubungan status seperti sebagai meta pos dan bukan meta pengguna dan atau meta di tabel khusus.

Pilihan 1

  • tidak memerlukan modifikasi skema meta Anda
  • menggunakan wpdbkelas untuk melakukan kueri khusus

Contoh:

//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...           
    }

});

Catatan: logika bisa disederhanakan lebih lanjut jika Anda mau.

pilihan 2

  • mengharuskan Anda mengubah skema meta Anda
  • mengharuskan Anda menyimpan id pengguna sebagai nilai meta
  • memungkinkan Anda untuk menggunakannya WP_Querybersamameta_query

Opsi 2 mengharuskan Anda mengubah meta key Anda dari like_status_{user_id}sesuatu yang universal seperti like_statusatau liked_by_user_iddi mana pada gilirannya alih-alih menyimpan nilai 1terhadap kunci, Anda malah menyimpan id pengguna sebagai nilainya.

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

        }

    });

});
Adam
sumber
1
Sekarang karena 5.1 lihat jawaban saya di bawah ini
K. Tromp
@ K.Tromp Huzzah!
Adam
10

Cukup sulit untuk menjawab pertanyaan Anda secara konkret. Namun, bagian pertama mudah. Baru-baru ini saya melakukan sesuatu yang mirip pada stackoverflow

Kunci meta dibandingkan dan sama persis. WP_Querytidak memiliki cara untuk menyesuaikan perilaku ini dengan parameter sederhana, tetapi kami selalu dapat memperkenalkannya sendiri dan kemudian menyesuaikan posts_whereklausa untuk melakukan LIKEperbandingan pada kunci meta.

FILTER

Ini hanya filter dasar, sesuaikan sesuai kebutuhan.

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

Seperti yang Anda lihat, filter hanya diaktifkan ketika kami mengatur parameter khusus kami yang baru, wildcard_on_keymenjadi true. Ketika ini memeriksa, kami hanya mengubah =pembanding ke LIKEpembanding

Hanya catatan tentang ini, LIKEperbandingan secara inheren lebih mahal untuk menjalankan perbandingan lainnya

QUERY THE

Anda dapat dengan mudah meminta posting Anda sebagai berikut untuk mendapatkan semua posting dengan kunci meta like_status_{user_id}

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

PERTANYAAN LAIN

Bidang khusus tidak berdampak pada kinerja, Anda dapat membaca posting saya tentang subjek ini di sini . Namun saya merasa terganggu dengan Anda mengatakan bahwa setiap posting dapat memiliki ratusan atau ribuan suka. Ini dapat memberi Anda kinerja yang mendapatkan dan menyimpan banyak data lapangan khusus dalam jumlah besar. Ini juga dapat menyumbat db Anda dengan sejumlah besar data bidang khusus yang tidak perlu yang membuatnya cukup sulit untuk dipelihara.

Saya bukan penggemar yang sangat besar dalam menyimpan data serial di bidang kustom karena orang tidak dapat mencari atau memesan dengan data serial. Namun saya sarankan menyimpan semua ID pengguna dalam array di bawah satu bidang khusus. Anda cukup memperbarui array dengan ID pengguna ketika pengguna menyukai posting. Mendapatkan data bidang khusus dan mengulang larik ID dan melakukan sesuatu dengan ID itu mudah. Lihat sajaget_post_meta()

Memperbarui bidang khusus juga mudah. Untuk itu, Anda perlu melihat ke dalam update_post_meta(), saya tidak tahu bagaimana Anda membuat bidang khusus Anda, tetapi update_post_meta()pasti sesuatu yang ingin Anda gunakan.

Jika Anda perlu mengirim email atau pemberitahuan push ketika bidang khusus diperbarui, Anda memiliki kait berikut yang bisa digunakan. ( Lihat update_metadata()konteksnya )

KESIMPULAN

Tepat sebelum saya memposting ini, sekali lagi, sebelum Anda pergi rute serial, pastikan bahwa Anda tidak perlu mengurutkan berdasarkan data yang diurutkan atau mencari data tertentu di dalam data serial.

Pieter Goosen
sumber
1
Terima kasih atas penjelasan Anda tentang kinerja post_meta! Sangat berguna.
codescribblr
Ini harus menjadi jawaban yang diterima, selalu lebih baik menggunakan filter daripada menggunakan permintaan khusus. Juga, perhatikan jika Anda menggunakan get_posts daripada WP_Query Anda harus melewati suppress_filters => false atau itu tidak akan memicu filter. Untuk melakukan LIKE pada kunci meta, Anda juga harus meletakkan% di depan dan di belakang kunci dalam larik tergantung pada jenis pencarian yang ingin Anda lakukan.
Earle Davies
Dan bagaimana Anda memfilternya jika Anda ingin melakukan kueri terhadap posting, tetapi MENGECUALIKAN semua posting yang memiliki kunci meta posting dengan awalan? (mis. kecualikan semua posting yang memiliki meta posting SUKA 'my_prefix_'?
gordie
5

Sejak wordpress 5.1 sekarang dimungkinkan untuk menggunakan meta query seperti: masukkan deskripsi gambar di sini

K. Tromp
sumber
Melarikan diri dari garis bawah tampaknya menjadi masalah dengan metode ini, tetapi sebaliknya, terlihat cukup bagus. Terima kasih menyoroti.
Jake
2

Jika nanti Anda ingin memperpanjang ini, dengan statistik, fitur, dll yang lebih rinci, maka alternatif lain bisa berupa: tabel khusus

  • pro : Disesuaikan dengan kebutuhan Anda dan dapat diindeks untuk kinerja yang lebih baik.

  • kontra : Lebih banyak pekerjaan

Mungkin juga ada solusi menggunakan taksonomi kustom, yang bisa memberikan kinerja kueri yang lebih baik daripada mengirim meta queries, karena cara tabel inti diindeks.

Saya mencoba untuk mendorong pemberitahuan kepada semua orang yang menyukai posting ketika orang lain menyukai posting itu ... sesuatu seperti, "Hei, orang lain menyukai posting yang Anda sukai. Anda harus memeriksanya!" Tetapi saya perlu cara untuk mengetahui apakah ada orang lain yang menyukai pos itu dan jika demikian, siapa mereka sehingga saya bisa memberi tahu mereka.

Tidak yakin jenis pemberitahuan apa yang Anda maksud di sini, tetapi ini dapat dengan cepat menjadi besar.

Contoh : Seorang pengguna yang suka ~ 1000 posting dan setiap posting mendapat ~ 1000 suka, maka ada 1M notifikasi di pipa, hanya untuk pengguna itu! Jika ini pemberitahuan email maka penyedia host mungkin tidak senang dan pengguna akan menjadi gila. Itu mungkin juga mahal dengan layanan email pihak ke-3.

birgire
sumber
Saya sebenarnya hanya mengirim pemberitahuan satu kali per orang per posting. Jadi kurang dari kedengarannya - meskipun masih banyak. Alasan saya mencoba menggunakan tabel bawaan adalah karena saya ingin dapat menggunakan API WP REST standar di aplikasi yang sebenarnya dengan data ini.
codescribblr
-1

Per dokumentasi WP_Meta_Query Anda dapat menggunakan compareargumen dalam meta_queryargumen WP_Query. Namun, Anda hanya dapat membandingkan pada valuedan bukan keysehingga Anda mungkin ingin memikirkan kembali bagaimana Anda menyusun ini.

Sebuah likeArgumen akan terlihat seperti ini:

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

$query = new WP_Query($arguments);

Mengingat Anda tidak dapat melakukan pencarian 'LIKE' di keySaya sarankan Anda menambahkan posting yang disukai di meta pengguna dan melakukan pencarian WP_User_Query untuk pengguna yang menyukai posting itu:

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

$users = new WP_User_Query($arguments);
LonnyLot
sumber