Làm cách nào để truy vấn bài viết bằng khóa meta một phần?


9

Tôi có một chức năng lưu trữ trạng thái "thích" cho một bài đăng dưới dạng meta bài đăng. Tôi muốn liên kết "thích" với người dùng thích nó, vì vậy tôi đã thiết lập trường tùy chỉnh có tên "like_status_ {user_id}" (trong đó {user_id} là id của người dùng hiện đang đăng nhập) mà tôi lưu trữ dưới dạng 0 hoặc 1. Vì vậy, đối với một bài đăng có nhiều lượt "thích", sẽ có một vài giá trị meta trong db được thiết lập như thế này:

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

....và như thế.

Có khả năng hàng ngàn lượt thích trên một bài đăng cụ thể. Làm thế nào tôi có thể chạy một truy vấn cho thấy nếu người khác cũng thích bài đăng đó?

Tôi đã suy nghĩ một cái gì đó như thế này:

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

Tôi đang cố gắng gửi thông báo cho tất cả những người thích bài đăng khi có người khác thích bài đăng đó ... đại loại như "Này, người khác thích bài đăng đó bạn thích. Bạn nên đi xem thử!" Nhưng tôi cần một cách để tìm hiểu xem có ai khác thích bài đăng đó không và nếu có, họ sẽ là ai để tôi có thể thông báo cho họ.

Nếu không thể, bạn có thể đề xuất một cách tốt hơn để lưu trữ dữ liệu này dưới dạng post_meta trong khi vẫn giữ hiệu quả cập nhật nhanh chóng trạng thái như một người dùng trên một bài đăng không?

Câu trả lời:


6

Thật không may, bạn không thể thực hiện meta_queryviệc sử dụng LIKEso sánh về meta_keygiá trị khi sử dụng WP_Query. Tôi đã xuống con đường này ...

Thay vào đó, bạn có một vài tùy chọn khác nếu bạn muốn duy trì mối quan hệ như trạng thái như meta bài đăng chứ không phải meta người dùng và meta trong bảng tùy chỉnh.

lựa chọn 1

  • không yêu cầu sửa đổi lược đồ meta của bạn
  • sử dụng wpdblớp để thực hiện một truy vấn tùy chỉnh

Thí dụ:

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

});

Lưu ý: logic có thể được đơn giản hóa hơn nữa nếu bạn muốn.

Lựa chọn 2

  • yêu cầu bạn thay đổi lược đồ meta của bạn
  • yêu cầu bạn lưu trữ id người dùng làm giá trị meta
  • cho phép bạn sử dụng WP_Querycùng vớimeta_query

Tùy chọn 2 yêu cầu bạn thay đổi khóa meta của mình từ like_status_{user_id}một thứ phổ biến như like_statushoặc liked_by_user_idlần lượt thay vì lưu trữ giá trị 1so với khóa, thay vào đó, bạn lưu trữ id của người dùng làm giá trị.

//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
Bây giờ là ngày 5.1, hãy xem câu trả lời của tôi dưới đây
K. Tromp

@ K.Tromp Huzzah!
Adam

10

Thật khó để trả lời cụ thể câu hỏi của bạn. Phần đầu tiên là dễ dàng mặc dù. Gần đây tôi đã làm một cái gì đó tương tự trên stackoverflow

Các khóa meta được so sánh và khớp chính xác. WP_Querykhông có cách nào để điều chỉnh hành vi này với một tham số đơn giản, nhưng chúng ta luôn có thể tự giới thiệu một hành vi và sau đó điều chỉnh posts_wheremệnh đề để LIKEso sánh trên các khóa meta.

BỘ LỌC

Đây chỉ là một bộ lọc cơ bản, điều chỉnh nó khi cần thiết.

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

Như bạn có thể thấy, bộ lọc chỉ được kích hoạt khi chúng ta đặt tham số tùy chỉnh mới, wildcard_on_keythành true. Khi kiểm tra này, chúng ta chỉ cần thay đổi bộ =so sánh thành bộ LIKEso sánh

Chỉ cần một lưu ý về điều này, các LIKEso sánh vốn đã đắt hơn để chạy các so sánh khác

NHANH

Bạn chỉ có thể truy vấn các bài đăng của mình như sau để có được tất cả các bài đăng có khóa meta like_status_{user_id}

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

CÂU HỎI KHÁC

Các trường tùy chỉnh không có tác động đến hiệu suất, bạn có thể đọc bài viết của tôi về chủ đề này ở đây . Tuy nhiên tôi gặp rắc rối khi bạn nói rằng mỗi bài đăng có thể có hàng trăm hoặc hàng nghìn lượt thích. Điều này có thể ảnh hưởng đến bạn về hiệu suất nhận và lưu trữ một lượng lớn dữ liệu trường tùy chỉnh như vậy. Nó cũng có thể làm tắc nghẽn db của bạn với một lượng lớn dữ liệu trường tùy chỉnh không cần thiết khiến cho việc bảo trì khá khó khăn.

Tôi không phải là một fan hâm mộ lớn của việc lưu trữ dữ liệu tuần tự trong các trường tùy chỉnh vì người ta không thể tìm kiếm hoặc đặt hàng theo dữ liệu được tuần tự hóa. Tuy nhiên, tôi sẽ đề nghị lưu trữ tất cả ID người dùng trong một mảng dưới một trường tùy chỉnh. Bạn chỉ có thể cập nhật mảng với ID người dùng khi người dùng thích một bài đăng. Lấy dữ liệu trường tùy chỉnh và lặp qua mảng ID và làm điều gì đó với ID thật dễ dàng. Chỉ cần nhìn vàoget_post_meta()

Cập nhật một lĩnh vực tùy chỉnh cũng dễ dàng. Đối với điều đó, bạn sẽ cần xem xét update_post_meta(), tôi không biết cách bạn tạo các trường tùy chỉnh của mình, nhưng update_post_meta()chắc chắn là thứ bạn muốn sử dụng.

Nếu bạn cần gửi email hoặc thông báo đẩy khi một trường tùy chỉnh được cập nhật, bạn có sẵn các móc nối sau để làm việc. ( Xem update_metadata()để biết ngữ cảnh )

PHẦN KẾT LUẬN

Ngay trước khi tôi đăng bài này, một lần nữa, trước khi bạn đi theo lộ trình tuần tự, hãy đảm bảo rằng bạn sẽ không cần sắp xếp theo dữ liệu được sắp xếp hoặc tìm kiếm dữ liệu cụ thể bên trong dữ liệu được tuần tự hóa.


1
Cảm ơn bạn đã giải thích về hiệu suất post_meta! Siêu hữu ích.
codescribblr

Đây phải là câu trả lời được chấp nhận, tốt hơn hết là sử dụng các bộ lọc thay vì sử dụng các truy vấn tùy chỉnh. Ngoài ra, lưu ý nếu bạn đang sử dụng get_posts chứ không phải WP_Query, bạn cần chuyển qua booster_filters => false hoặc nó sẽ không kích hoạt bộ lọc. Để thực hiện THÍCH trên khóa meta, bạn cũng cần đặt% ở phía trước và phía sau khóa trong mảng tùy thuộc vào loại tìm kiếm bạn muốn thực hiện.
Earle Davies

Và bạn sẽ lọc nó như thế nào nếu bạn muốn truy vấn các bài đăng nhưng LOẠI TRỪ tất cả các bài đăng có khóa meta bài viết theo tiền tố? (ví dụ: loại trừ tất cả các bài đăng có meta bài đăng THÍCH 'my_prefix_'?
gordie

5

Kể từ wordpress 5.1, giờ đây có thể sử dụng truy vấn meta như: nhập mô tả hình ảnh ở đây


Việc thoát khỏi dấu gạch dưới dường như là một vấn đề với phương pháp này, nhưng nếu không, nó có vẻ khá tốt. Cảm ơn làm nổi bật.
Jake

2

Nếu sau này bạn muốn mở rộng điều này, với các số liệu thống kê, tính năng chi tiết hơn, v.v., thì một lựa chọn khác có thể là: (các) bảng tùy chỉnh

  • ưu điểm : Phù hợp với nhu cầu của bạn và có thể được lập chỉ mục để có hiệu suất tốt hơn.

  • Nhược điểm : Công việc nhiều hơn

Cũng có thể có một cách giải quyết bằng cách sử dụng phân loại tùy chỉnh, có thể mang lại hiệu năng truy vấn tốt hơn so với truy vấn meta, do cách các bảng cốt lõi được lập chỉ mục.

Tôi đang cố gắng gửi thông báo cho tất cả những người thích bài đăng khi có người khác thích bài đăng đó ... đại loại như "Này, người khác thích bài đăng đó bạn thích. Bạn nên đi xem thử!" Nhưng tôi cần một cách để tìm hiểu xem có ai khác thích bài đăng đó không và nếu có, họ sẽ là ai để tôi có thể thông báo cho họ.

Không chắc chắn loại thông báo bạn có ý nghĩa ở đây, nhưng điều này có thể nhanh chóng trở nên cồng kềnh.

Ví dụ : Một người dùng thích ~ 1000 bài đăng và mỗi bài đăng được ~ 1000 lượt thích, sau đó có 1M thông báo trong các đường ống, chỉ dành cho người dùng đó! Nếu đây là những thông báo qua email thì nhà cung cấp máy chủ có thể không vui và người dùng sẽ phát điên. Điều đó cũng có thể tốn kém với dịch vụ email của bên thứ 3.


Tôi thực sự chỉ gửi thông báo một lần cho mỗi người mỗi bài. Vì vậy, nó ít hơn âm thanh - mặc dù vẫn còn rất nhiều. Lý do tôi đang cố gắng sử dụng các bảng dựng sẵn là vì tôi muốn có thể sử dụng API WP REST tiêu chuẩn trong một ứng dụng thực tế với dữ liệu này.
codescribblr

-1

Theo tài liệu WP_Meta_Query, bạn có thể sử dụng compaređối số trong meta_queryđối số của WP_Query. Tuy nhiên, bạn chỉ có thể so sánh trên valuevà không phải keyvì vậy bạn có thể muốn nghĩ lại cách bạn cấu trúc này.

Một likeđối số sẽ như thế này:

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

$query = new WP_Query($arguments);

Cho rằng bạn không thể thực hiện tìm kiếm 'THÍCH' trên keyTôi khuyên bạn nên thêm các bài đăng thích trong meta người dùng và thực hiện tìm kiếm WP_User_Query cho những người dùng đã thích bài đăng đó:

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

$users = new WP_User_Query($arguments);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.