サポート » 使い方全般 » meta_valueでソート

  • 解決済 tomoya_22

    (@tomoya_22)


    質問です。
    http://ja.forums.wordpress.org/topic/11306
    を参考にソートを実現したく思っています。
    しかし上記だと投稿件数が多くなると表示速度が落ちたりと使えません。

    例えば
    カスタムフィールドのmeta_keyがexampleとし
    meta_valueにsize、color、stockがシリアライズ化され格納されているとします。

    var_dump
    get_post_meta($post->ID, 'example', true);
    とした場合

    array(3) {
      [0]=>
      array(3) {
        ["size"]=>
        string(1) "S"
        ["color"]=>
        string(3) "red"
        ["stock"]=>
        string(1) "1"
      }
      [1]=>
      array(3) {
        ["size"]=>
        string(1) "M"
        ["color"]=>
        string(5) "black"
        ["stock"]=>
        string(1) "2"
      }
      [2]=>
      array(3) {
        ["size"]=>
        string(1) "L"
        ["color"]=>
        string(5) "white"
        ["stock"]=>
        string(1) "3"
      }
    }

    となります。
    このstockで記事をソートする場合、どのようなコードを書けば良いのでしょうか?
    色々調べたのですがシリアライズされたmeta_valueの値でソートする方法が見つかりません。
    よろしくお願いします。

7件の返信を表示中 - 1 - 7件目 (全7件中)
  • 端的に言えば設計ミスの類になると思います。

    現状ではシリアライズ化されたデータでのorder by句はつかえません
    wordpressから離れればできなくはありませんがサブクエリで抜き出してから並べ替えるか
    とりあえず対象の投稿を取得してphpでの並べ替えになると思います。
    ただ、投稿件数が多くなると云々という条件が付くので
    速度的にもどうかと思います。

    速度の面やこれから増える可能性のことを考えますと
    できるのであれば別に分けた状態で動作するよう作り変えておくべきかと思います。

    トピック投稿者 tomoya_22

    (@tomoya_22)

    回答ありがとうございます。
    なるほど。
    現状では不可能なのですね。
    シリアライズでの保存方法は変更ができないので(あるプラグインを使用している為)
    stockのみ抜出し、
    新しくmeta_keyを作成し(update_post_metaを使用)一旦そこに入れ込んでからソートした方が現実的でしょうか。
    只、5000件の記事があった場合、5000件分のmeta_keyを作成してしまう為、
    この方法だとデータベースの肥大化が避けられないのでは?と思います。

    http://ja.forums.wordpress.org/topic/11306
    を少しいじってみたので見て頂けますでしょうか?

    $cat_id = get_query_var('cat');
    $posts_per = get_option('posts_per_page');
    $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
    $array_get = get_posts(array('paged'=>$paged,'posts_per_page' =>$posts_per,'orderby'=>'ID','order'=>'DESC','cat'=>$cat_id,'meta_key' => 'example'));
    foreach( $array_get as $post ) {
    $meta = get_post_meta($post->ID, 'example', true);
    $example_1[] = array('size' => $meta['size'],'color' => $meta['color'],'stock' => $meta['stock'],);
    $stock[] = $meta['stock'];
    }
    array_multisort( $price, SORT_DESC ,SORT_NUMERIC, $example_1 );
    //$example_2 = ($paged - 1) * $posts_per;
    //$example_1 = array_slice($example_1, $example_2, $posts_per);
    foreach( $example_1 as $example_3 ) {
    $stock_2 = $example_3['size'];
    echo '<br />'.$stock_2.'<br />';
    }

    get_posts内を変更し(numberposts除外など)、$example_2と$example_1(array_slice)をコメントアウトしました。
    この状態ですとソートが1ページ毎となり記事全体ではソートを行いません。
    (ページ送りなどはできます)
    また、表示速度などの問題は解決します。
    この状態から記事全体をソートする方法はないでしょうか?
    よろしくお願いします。

    トピック投稿者 tomoya_22

    (@tomoya_22)

    訂正
    array_multisort( $stock, SORT_DESC ,SORT_NUMERIC, $example_1 );
    です。

    どちらにせよ全ての記事を取得してソートする必要があります。
    あげていただいたコードのようにphpのネイティブ関数であれば
    ある程度は速度は出ると思いますが、そのページを表示するたびに
    5000件のソートをかけるというのは現実的ではなさそうですね。

    5,000件として1記事5つのカスタムフィールドがあったとしても
    25,000件程度ですので

    >新しくmeta_keyを作成し(update_post_metaを使用)一旦そこに入れ込んでからソートした方が現実的でしょうか。

    こちらの方法のほうがまだ現実的かと思います。

    件数が100,000件、500,000件などになる場合であればそもそもwordpressやMySQL
    を別のものに考える必要がるかと思います。

    追記です。
    どうしても速度が気になるということであれば
    >新しくmeta_keyを作成し(update_post_metaを使用)一旦そこに入れ込んでからソートした方が現実的でしょうか。

    これに加えて初めに
    wpdbクラスを使用して
    post
    postmeta
    をつなげて最低限のものを取得するようにして
    ページングによってLIMITをかけます。
    その後、10件なりのIDをwordpressのwp_queryなどで拾ってやれば
    結構な件数までは大丈夫かと思います。

    モデレーター gatespace

    (@gatespace)

    横からすいません。
    作り直すのであれば、最初の投稿にある「color」「Size」あたりはカスタムタクソノミー(カスタム分類)にした方がいいかもしれません。

    ※根本的な設計の部分ですので、あくまで「こういう方法もあったよ」程度でお納めください

    トピック投稿者 tomoya_22

    (@tomoya_22)

    jdbbさん
    gatespaceさん
    回答ありがとうございます。
    そうですね。
    最初からカスタム分類でできれば簡単に事は進むのですが今回はかなり難解です。
    一旦全ての記事を取得しforeachしても表示速度の低下が起こり、
    一旦全ての記事を取得しarray_sliceでページ分割して
    foreach(表示速度などは解消)しても記事全体でソートしてくれず1ページ毎になってしまい希望通りにならなくかなり難しいです。(>_<)
    もう少し調べて試行錯誤したいと思います。
    ありがとうございました。

7件の返信を表示中 - 1 - 7件目 (全7件中)
  • トピック「meta_valueでソート」には新たに返信することはできません。