web-dev-qa-db-ja.com

部分メタキーで投稿を検索するにはどうすればよいですか。

投稿の「いいね」のステータスを投稿メタとして保存する機能があります。私はそれを気に入ったユーザーと "like"を関連付けたいので、 "like_status_ {user_id}"({user_id}は現在ログインしているユーザーのID)というカスタムフィールドを0または0として保存します。 1.いくつかの「いいね」を含む投稿の場合、dbには次のように設定された複数のメタ値があります。

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

他の誰かがその投稿を気に入ったときにその投稿を気に入った人全員に通知を送信しようとしています...「他の誰かがあなたが気に入った投稿が好きでした。ぜひチェックしてください」しかし、私は他の誰かがその投稿を気に入っているかどうか、そしてもしそうであれば誰になるかを知るための方法が必要です。

それが不可能な場合は、1人のユーザーのような投稿のステータスをすばやく更新する効率を維持しながら、このデータをpost_metaとして格納するためのより良い方法を提案できますか?

8
codescribblr

残念ながら、meta_queryを使用しているときは、meta_key値に対してLIKE比較を使用してWP_Queryを実行することはできません。私はこの道を下りてきた….

代わりに、カスタムテーブルのユーザーメタやメタではなく、ポストメタとして同様のステータス関係を維持する場合は、他に2つのオプションがあります。

オプション1

  • メタスキーマを変更する必要はありません
  • カスタムクエリを実行するために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_statusliked_by_user_idなどの汎用的なものに変更する必要があります。この場合、キーに対して1の値を格納する代わりに、代わりにユーザーのIDを値として格納します。

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

        }

    });

});
6
userabuser

あなたの質問に具体的に答えることは非常に困難です。しかし最初の部分は簡単です。私は最近何かをしました stackoverflowに似ています

メタキーは比較され、完全に一致します。 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_keytrueに設定したときにのみ起動されます。これをチェックアウトするとき、=コンパレータをLIKEコンパレータに変更するだけです。

ちょっと注意してください、LIKE比較は他の比較を実行するために本質的により高価です。

質問

次のように投稿を照会するだけで、メタキーを含むすべての投稿を取得できますlike_status_{user_id}

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

その他の質問

カスタムフィールドはパフォーマンスに影響を与えません。この件に関する私の投稿を読むことができます ここ 。しかし、私はあなたが各記事が何百または何千ものいいねを持つことができると言うことによって悩んでいます。これは、このような大量のカスタムフィールドデータを取得してキャッシュするパフォーマンスに影響を与える可能性があります。データベースを大量の不要なカスタムフィールドデータで詰まらせる可能性があるため、保守が非常に困難になります。

シリアル化されたデータで検索や注文をすることはできないため、カスタム化されたフィールドにシリアル化されたデータを格納することはあまり好きではありません。ただし、1つのカスタムフィールドの下にすべてのユーザーIDを配列で格納することをお勧めします。ユーザーが投稿を好む場合は、単にユーザーIDで配列を更新するだけです。カスタムフィールドデータを取得し、IDの配列をループしてIDを使って何かをするのは簡単です。 get_post_meta()を見てください。

カスタムフィールドを更新することも簡単です。そのためには、 update_post_meta() を調べる必要があります。カスタムフィールドの作成方法はわかりませんが、update_post_meta()は間違いなく使用したいものです。

カスタムフィールドが更新されたときに電子メールまたはプッシュ通知を送信する必要がある場合は、次のフックを使用して作業できます。 ( コンテキストについては update_metadata() を参照

結論

この記事を投稿する直前に、シリアル化された経路に進む前に、並べ替えられたデータで並べ替えたり、シリアル化されたデータ内の特定のデータを検索する必要がないことを確認します。

10
Pieter Goosen

後でもっと詳細な統計、機能などでこれを拡張したい場合は、さらに別の方法があります。 カスタムテーブル

  • pros :あなたのニーズに合わせたもので、 indexed にするとパフォーマンスが向上します。

  • 短所 :もっと作業

カスタム分類法を使用した回避策もあるかもしれません。コアテーブルがどのようにインデックス付けされているかによって、ポストメタクエリよりもクエリパフォーマンスが向上する可能性があります。

他の誰かがその投稿を気に入ったときにその投稿を気に入った人全員に通知を送信しようとしています...「他の誰かがあなたが気に入った投稿が好きでした。ぜひチェックしてください」しかし、私は他の誰かがその投稿を気に入っているかどうか、そしてもしそうであれば誰になるかを知るための方法が必要です。

あなたがここでどんな通知を意味しているのかわからないが、これはすぐに大きくなる可能性がある。

:〜1000の投稿が好きで、各投稿が〜1000のお気に入りがあるユーザー。その場合、パイプ内に1Mの通知があります。これらが電子メール通知である場合、ホストプロバイダは満足していない可能性があり、ユーザーは夢中になります。それはまた第三者の電子メールサービスと高価かもしれません。

2
birgire

WordPress 5.1以降、今では以下のようなメタクエリを使用することが可能です。 enter image description here

1
K. Tromp

WP_Meta_Query のドキュメントによれば、WP_Queryのmeta_query引数にcompare引数を使用することができます。ただし、比較できるのはvalueではなくkeyなので、これをどのように構成するかを再考することをお勧めします。

like引数は次のようになります。

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

$query = new WP_Query($arguments);

keyで 'LIKE'検索を実行できないことを考えれば、ユーザーメタにお気に入りの投稿を追加し、その投稿が気に入ったユーザーを WP_User_Query 検索することをお勧めします。

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

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