部分的なメタキーで投稿をクエリするにはどうすればよいですか?


9

投稿の「いいね」ステータスを投稿メタとして保存する機能があります。その「いいね」を好きなユーザーに関連付けたいので、「like_status_ {user_id}」というカスタムフィールドを設定します({user_id}は現在ログインしているユーザーのIDです)。これを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として保存するより良い方法を提案できますか?

回答:


6

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

代わりに、カスタムテーブルのユーザーメタやメタではなく、投稿メタなどのステータス関係を維持したい場合は、他にいくつかのオプションがあります。

オプション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_statusまたはliked_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);

        }

    });

});

1
それは、5.1からの私の答えを以下に示しています
K. Tromp

@ K.Tromp Huzzah!
Adam

10

あなたの質問に具体的に答えることはかなり難しいです。ただし、最初の部分は簡単です。私は最近、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_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 );

その他の質問

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

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

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

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

結論

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


1
post_metaのパフォーマンスについて説明していただきありがとうございます。超便利です。
codescribblr 2016年

これは受け入れられる答えであるはずです。カスタムクエリを使用するよりも、常にフィルタを使用する方が良いです。また、WP_Queryではなくget_postsを使用している場合は、suppress_filters => falseを通過させる必要があります。そうしないと、フィルターがトリガーされません。メタキーでLIKEを実行するには、実行する同様の検索の種類に応じて、配列内のキーの前後に%を配置する必要もあります。
Earle Davies

そして、投稿をクエリしたいが、投稿メタキーを持つすべての投稿をプレフィックスで除外する場合、どのようにフィルタリングしますか?(例:投稿メタLIKE 'my_prefix_'を持つすべての投稿を除外しますか?
gordie

5

WordPress 5.1以降、次のようなメタクエリを使用できるようになりました。 ここに画像の説明を入力してください


アンダースコアのエスケープはこのメソッドの問題のようですが、それ以外の場合は、かなり見栄えがします。ハイライトありがとうございます。
ジェイク

2

後で、より詳細な統計、機能などを使用してこれを拡張する場合、さらに別の方法として、カスタムテーブルを使用できます。

  • 長所:ニーズに合わせて調整され、インデックス付けてパフォーマンスを向上せることができます。

  • 短所:より多くの作業

コアテーブルのインデックス付け方法が原因で、カスタム分類法を使用した回避策があり、ポストメタクエリよりもクエリのパフォーマンスが向上する可能性があります。

他の誰かがその投稿を気に入ったときに、「ねえ、あなたが気に入った投稿を他の誰かが気に入ったので、ぜひチェックしてみてください!」のような通知をプッシュしようとしています。しかし、私は他の誰かがその投稿を気に入っているかどうか、そうであれば誰がそうするかを知る方法が必要です。

ここでどのような通知を意味するのかはわかりませんが、これはすぐに大きくなる可能性があります。

:ユーザーが〜1000件の投稿を好きで、各投稿が〜1000件のいいね!を取得した場合、パイプには100万通の通知があり、そのユーザーのみが通知されます!これらが電子メール通知である場合、ホストプロバイダーは満足できず、ユーザーは夢中になります。サードパーティのメールサービスを利用する場合も、費用がかかる可能性があります。


私は実際には通知を1人の投稿につき1回だけ送信しています。だから、それは思ったよりも少ないです-それでもまだたくさんです。組み込みのテーブルを使用しようとしているのは、実際のアプリでこのデータを使用して、将来、標準のWP REST APIを使用できるようにしたいからです。
codescribblr 2016年

-1

WP_Meta_Queryのドキュメントに従ってWP_Querycompare引数で引数を使用できますmeta_query。ただし、比較できるのはでのみなのでvaluekeyこれをどのように構造化するかを再考する必要があります。

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.