カテゴリー
ブログ

LOTD の仕組み

備忘録として、LOTD (Lisf Of The Day) の仕組みを記述する。

概要

公開されたリスト投稿から適切なリストランダムに選んでLOTDとし、1日に1回配信する。

詳細

公開されたリスト投稿

公開されたリスト投稿とは、次の条件をすべて満たす投稿(記事)。

  • 投稿タイプ: 投稿 (post)
  • カテゴリ: list
  • ステータス: 公開

適切なリスト

適切なリストとは、公開されたリスト投稿のなかで次の条件をすべて満たす投稿。

  • 書籍から作成されている
    • 書籍が引用されていないリストは自作リストやまとめリストなど配信向きでないものが多いと考えたため。
    • システム的には “ASIN” タクソノミーのタームが関連付けられているリスト。
  • これまでにLOTDになった回数が少ない
    • 多様なリストを配信させたいため。
    • システム的には、LOTDとして選ばれた回数を投稿のカスタムフィールド lotd_count に保存し、最小回数のリストから選択する。
  • 運営者が配信向きだと判断した
    • 上記の条件を満たしていても、配信向きでないと判断したリストは配信しないようにする。
    • システム的には、先の lotd_count カスタムフィールドに ‘999’ をセットする。

ランダムに選んで

上記の条件を満たすリスト投稿群を作成したうえで、ランダムに1つリストを選ぶ。ただし、LOTDとして適切かどうかを前日にチェックするため、翌日のLOTD候補を前日に決めておきたい。

調べてみると、PHP の rand 関数も MySQLの ORDER BY RAND 句も、シードを与えると、結果はシードに対して一意に定まることがわかった。そこで 20201231 のような日付を元にした情報をシードとして与えれば、母集団が変わらないかぎり、特定の日にどの投稿が選ばれるかを知ることができる。

以下、処理の概要。

1. まずは「公開されたリスト投稿」および「適切なリスト」の条件から、「これまでにLOTDになった回数が少ない」を除く条件を満たす投稿IDの配列を取得する。

(「ASINタクソノミーが付与されている投稿の中で、lotd_countタクソノミーの最小値を持つもの」が一回のget_posts()で 抽出できればよいのだが、その方法は見つからなかった)

また lotd_count が小さいものを配信対象にするため、meta_query 部分はロジック的には不要。ただ、lotd_count を 999 にセットすることによって配信対象から外すというルールを忘れないために付けておく。配信しない投稿が増えてくれば若干パフォーマンスにも寄与する。

$post_ids = get_posts( array(
	'post_type'      => 'post',
	'category_name'  => 'list',
	'post_status'    => 'publish',
	'posts_per_page' => -1, // 全投稿
	'fields'         => 'ids', // IDのみを返す
	'tax_query' => array( // ASIN が付与されている
		array(
			'taxonomy' => 'asin',
			'operator' => 'EXISTS',
		),
	),
	'meta_query' => array(
		array(
			'key'     => 'lotd_count',
			'value'   => '999',
			'compare' => '!=',
		),
	),
) );

2. 各投稿のLOTD配信カウントを取得し、その最小値を取得する。

// 母集団の各投稿の lotd_count を取得
$lotd_counts = array();
foreach( $post_ids as $id ) {
	$lotd_counts[] = get_post_meta( $id, 'lotd_count' );
}

// lotd_count の最小値を取得
$min_count = min( $lotd_counts );

3. 投稿IDの配列を再度走査し、LOTD配信カウントが最小のものだけからなる別の配列を生成する。

// 母集団の中で、lotd_count が最小値のものだけからなる配列を作成
$mini_post_ids = array();
foreach( $post_ids as $i => $id ) {
	if( $min_count == $lotd_counts[$i] ) {
    		$mini_post_ids[] = $id;
	}
}

4. 日付を元にしたシードから乱数を生成し、3で作成した配列から1要素を選ぶ。そのメンバーがLOTDの投稿IDとなる。

// $seed で乱数生成器を初期化
srand( 20201231 );

// 順序をランダムに取得
$idnum = rand( 0, count( $mini_post_ids ) );

// その順序番めのIDから投稿オブジェクトを作成
$lotd_post = get_post( $mini_post_ids[$idnum] );

LOTD

システム上、LOTD とは次の条件を満たす投稿。

  • カテゴリ: 今日のリスト

毎日 0:01 にバッチ処理を走らせ、「今日のリスト」カテゴリを空にしたうえで、上記のロジックで選んだリストを「今日のリスト」カテゴリに入れる。そしてカスタムフィールドに保存している配信カウンタをインクリメントしておく。

1日1回配信

メール

毎日 6:05 にバッチ処理を走らせ、LOTD を エックスサーバーのメーリングリストに投稿する。

Feed

WordPress の標準機能でカテゴリごとの feed が出力されるので、「今日のリスト」カテゴリのフィードが LOTD のフィードになる。

twitter

上記のFeedを delvr.it を利用して @listfreak にツイートさせる。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です