ฉันจะค้นหาโพสต์ด้วยคีย์เมตาบางส่วนได้อย่างไร


9

ฉันมีฟังก์ชั่นที่จัดเก็บสถานะ "ชอบ" สำหรับโพสต์เป็นโพสต์เมตา ฉันต้องการเชื่อมโยงว่า "ชอบ" กับผู้ใช้ที่ชอบดังนั้นฉันตั้งค่าฟิลด์ที่กำหนดเองที่เรียกว่า "like_status_ {user_id}" (โดยที่ {user_id} เป็นรหัสของผู้ใช้ที่เข้าสู่ระบบในปัจจุบัน) ซึ่งฉันเก็บเป็น 0 หรือ 1. ดังนั้นสำหรับโพสต์ที่มี "ไลค์" หลายรายการจะมีค่าเมตาหลายค่าในฐานข้อมูลที่ตั้งค่าดังนี้:

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

.... และอื่น ๆ

มีจำนวนไลค์ในโพสต์ที่เฉพาะเจาะจง ฉันจะเรียกใช้คิวรีที่แสดงให้เห็นได้อย่างไรถ้ามีคนอื่นชอบโพสต์นั้น

ฉันกำลังคิดบางอย่างเช่นนี้:

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

ฉันพยายามที่จะส่งการแจ้งเตือนไปยังทุกคนที่ชอบโพสต์เมื่อมีคนชอบโพสต์นั้น ... บางอย่างเช่น "เฮ้คนอื่นชอบโพสต์ที่คุณชอบคุณควรไปตรวจสอบมัน!" แต่ฉันต้องการวิธีการตรวจสอบว่ามีคนชอบโพสต์นั้นหรือไม่และถ้าเป็นเช่นนั้นพวกเขาจะเป็นใครฉันจึงสามารถแจ้งให้พวกเขาทราบ

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

คำตอบ:


6

แต่น่าเสียดายที่คุณไม่สามารถดำเนินการmeta_queryโดยใช้LIKEการเปรียบเทียบในค่าเมื่อใช้meta_key WP_Queryฉันลงไปที่ถนนเส้นนี้แล้ว ...

แต่คุณมีตัวเลือกอื่น ๆ อีกสองสามอย่างถ้าคุณต้องการรักษาไว้ซึ่งความสัมพันธ์สถานะเช่นเดียวกับโพสต์เมตาและไม่ใช่เมตาผู้ใช้และหรือเมตาในตารางที่กำหนดเอง

ตัวเลือกที่ 1

  • ไม่ต้องแก้ไข meta schema ของคุณ
  • ใช้wpdbคลาสเพื่อทำการค้นหาแบบกำหนดเอง

ตัวอย่าง:

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

});

หมายเหตุ: ลอจิกสามารถทำให้ง่ายขึ้นอีกหากคุณต้องการ

ตัวเลือก 2

  • คุณต้องเปลี่ยนเมตาสคีมาของคุณ
  • คุณต้องเก็บ ID ผู้ใช้เป็นค่าเมตา
  • ให้คุณใช้งานWP_Queryร่วมกับmeta_query

ตัวเลือกที่ 2 กำหนดให้คุณเปลี่ยนเมตาคีย์ของคุณlike_status_{user_id}เป็นสิ่งที่เป็นสากลเช่นlike_statusหรือliked_by_user_idที่ไหน1ก็ตามแทนที่จะเก็บค่าเทียบกับคีย์คุณจะต้องเก็บรหัสผู้ใช้เป็นค่าแทน

//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
ตอนนี้ 5.1 ได้ดูคำตอบของฉันด้านล่างนี้
K. Tromp

@ K.Tromp Huzzah!
อดัม

โปรดอัปเดตคำตอบที่ยอมรับเพื่อสะท้อนความสามารถ WP ล่าสุดหรือคำตอบของ @ K.Tromp ที่ทำเครื่องหมายเป็นคำตอบล่าสุด
zumek

10

เป็นการยากที่จะตอบคำถามของคุณอย่างเป็นรูปธรรม ส่วนแรกนั้นง่ายแม้ว่า ฉันเพิ่งทำสิ่งที่คล้ายกันใน stackoverflow

คีย์ Meta ถูกเปรียบเทียบและตรงกันทั้งหมด WP_Queryไม่มีวิธีในการปรับพฤติกรรมนี้ด้วยพารามิเตอร์ง่าย ๆ แต่เราสามารถแนะนำตัวเราเองแล้วปรับposts_whereข้อเพื่อทำการLIKEเปรียบเทียบกับคีย์เมตา

ตัวกรอง

นี่เป็นเพียงตัวกรองพื้นฐานปรับตามต้องการ

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

ในขณะที่คุณสามารถดูตัวกรองจะถูกยิงก็ต่อเมื่อเราตั้งค่าพารามิเตอร์ที่กำหนดเองใหม่ของเราไปwildcard_on_key trueเมื่อตรวจสอบแล้วเราเพียงเปลี่ยนเครื่องมือ=เปรียบเทียบเป็นเครื่องมือLIKEเปรียบเทียบ

เพียงแค่ทราบเกี่ยวกับสิ่งนี้LIKEการเปรียบเทียบมีราคาแพงกว่ามากเมื่อเปรียบเทียบกัน

คำถาม

คุณสามารถค้นหาโพสต์ของคุณตามเพื่อรับโพสต์ทั้งหมดด้วยเมตาคีย์ like_status_{user_id}

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

คำถามอื่น ๆ

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

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

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

หากคุณต้องการส่งอีเมลหรือการแจ้งเตือนแบบพุชเมื่อมีการอัปเดตฟิลด์ที่กำหนดเองคุณจะสามารถขอใช้งานต่อไปนี้ได้ ( ดูupdate_metadata()บริบท )

สรุปผลการศึกษา

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


1
ขอบคุณสำหรับคำอธิบายเกี่ยวกับประสิทธิภาพของ post_meta! สุดยอดประโยชน์
codescribblr

นี่ควรเป็นคำตอบที่ยอมรับได้ดีกว่าเสมอในการใช้ตัวกรองมากกว่าใช้การสืบค้นแบบกำหนดเอง นอกจากนี้โปรดทราบว่าคุณกำลังใช้ get_posts มากกว่า WP_Query คุณต้องผ่าน suppress_filters => false มิเช่นนั้นจะไม่เรียกตัวกรอง ในการดำเนินการ LIKE บนคีย์เมตาคุณต้องใส่% ด้านหน้าและด้านหลังคีย์ในอาเรย์โดยขึ้นอยู่กับประเภทของการค้นหาที่คุณต้องการทำ
Earle Davies

และวิธีการที่คุณจะกรองถ้าคุณต้องการสอบถามโพสต์ แต่ไม่รวมการโพสต์ทั้งหมดที่มีคีย์โพสต์เมตาโดยคำนำหน้า? (เช่นยกเว้นการโพสต์ทั้งหมดที่มีโพสต์ meta LIKE 'my_prefix_'?
gordie

6

ตั้งแต่ wordpress 5.1 ตอนนี้คุณสามารถใช้ meta query เช่น: ป้อนคำอธิบายรูปภาพที่นี่


การหลีกเลี่ยงการขีดเส้นใต้ดูเหมือนว่าจะมีปัญหากับวิธีนี้ แต่อย่างอื่นมันก็ดูดีทีเดียว ขอบคุณที่เน้น
Jake

2

หากภายหลังคุณต้องการขยายสิ่งนี้ด้วยสถิติรายละเอียดเพิ่มเติมฟีเจอร์ ฯลฯ แล้วยังมีทางเลือกอื่น: ตารางที่กำหนดเอง

  • ข้อดี : ปรับแต่งตามความต้องการของคุณและสามารถจัดทำดัชนีเพื่อประสิทธิภาพที่ดีขึ้น

  • ข้อด้อย : ทำงานได้มากขึ้น

อาจมีวิธีแก้ปัญหาด้วยการใช้ taxonomy ที่กำหนดเองซึ่งอาจให้ประสิทธิภาพการสืบค้นที่ดีกว่าการสืบค้น post meta เนื่องจากวิธีการทำดัชนีตารางหลัก

ฉันพยายามที่จะส่งการแจ้งเตือนไปยังทุกคนที่ชอบโพสต์เมื่อมีคนชอบโพสต์นั้น ... บางอย่างเช่น "เฮ้คนอื่นชอบโพสต์ที่คุณชอบคุณควรไปตรวจสอบมัน!" แต่ฉันต้องการวิธีการตรวจสอบว่ามีคนชอบโพสต์นั้นหรือไม่และถ้าเป็นเช่นนั้นพวกเขาจะเป็นใครฉันจึงสามารถแจ้งให้พวกเขาทราบ

ไม่แน่ใจว่าการแจ้งเตือนแบบไหนที่คุณหมายถึงที่นี่ แต่สิ่งนี้อาจใหญ่โตอย่างรวดเร็ว

ตัวอย่าง : ผู้ใช้ที่ชอบ ~ 1,000 โพสต์และแต่ละโพสต์ได้รับ ~ 1,000 ไลค์จากนั้นมีการแจ้งเตือน 1M ในไพพ์สำหรับผู้ใช้นั้นเท่านั้น! หากสิ่งเหล่านี้เป็นการแจ้งเตือนทางอีเมลผู้ให้บริการโฮสต์อาจไม่พอใจและผู้ใช้จะคลั่งไคล้ ซึ่งอาจมีราคาแพงเมื่อใช้บริการอีเมลบุคคลที่สาม


ฉันส่งการแจ้งเตือนเพียงครั้งเดียวต่อคนต่อโพสต์ ดังนั้นมันจึงน้อยกว่าเสียง - แม้ว่าจะยังมีเยอะ เหตุผลที่ฉันพยายามใช้ตารางในตัวคือฉันต้องการใช้ WP REST API มาตรฐานตามท้องถนนในแอปจริงด้วยข้อมูลนี้
codescribblr

-1

ตามเอกสารWP_Meta_Queryคุณสามารถใช้compareอาร์กิวเมนต์ในmeta_queryอาร์กิวเมนต์ของ WP_Query อย่างไรก็ตามคุณสามารถเปรียบเทียบได้เท่านั้นvalueไม่ใช่keyเพื่อที่คุณอาจต้องการคิดใหม่ว่าโครงสร้างนี้เป็นอย่างไร

likeอาร์กิวเมนต์จะมีลักษณะเช่นนี้

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

$query = new WP_Query($arguments);

ระบุว่าคุณไม่สามารถค้นหา 'LIKE' ในkeyฉันขอแนะนำให้คุณเพิ่มโพสต์ที่ชอบในเมตาของผู้ใช้และทำการค้นหาWP_User_Queryสำหรับผู้ใช้ที่ชอบโพสต์นั้น:

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

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