投稿者: koji

  • あるカテゴリーの公開投稿で使われている、あるタクソノミー下のタームの総数を数える

    公開リストの中で引用している書籍の総数を数えた。

    • 公開リストとは
      • post_type が post
      • post_status が publish
      • カテゴリー が list
    • 引用している書籍とは
      • asin タクソノミー 下にあるターム

    標準関数を組み合わせると次のような手順で取得できる。

    $q = new WP_Query( array(
    	'post_type'      => 'post',
    	'category_name'  => 'list',
    	'post_status'    => 'publish',
    	'posts_per_page' => -1,
    	'fields'         => 'ids',
    	'tax_query' => array( // 不要だが母集団を小さくするため
    		array( 'taxonomy' => 'asin',
    			'operator' => 'EXISTS' ),
        ),
    ) );
    
    // ids: 投稿に付けられたASINタームの総数(重複無し)
    $terms = wp_get_object_terms( $q->posts, 'asin', [ 'fields' => 'ids' ]  );
    $term_count = count( $terms );	
    
    // all_with_object_id: 投稿に付けられたASINタームの総数(重複あり、延べ引用数)
    $terms = wp_get_object_terms( $q->posts, 'asin', [ 'fields' => 'all_with_object_id' ]  );
    $term_count_total = count( $terms );

    ここで $term_count がASINターム数つまり本の数、$term_count_total が延べ引用数ということになる。

    ただ、2つの数字を得るために千の要素を超える配列を3つも経由するのはスマートでない気がするので、SQL文で取得することを試みた。

    asinタクソノミー下のタームが関連付けられている公開投稿を探し出し、その投稿がlistカテゴリ下にあることを確認しなければならない。

    データベース構造(WordPress Codex 日本語版)を見ながら愚直に INNER JOIN していった。このSQL文の結果と上の関数の結果が同じで、いくつか書籍を絞ってテストしてみても正しい結果が取得できたので、きちんと動いている模様。

    SELECT COUNT(DISTINCT t.term_id) AS total, COUNT(t.term_id) AS c_total
    FROM wp_terms AS t
    INNER JOIN wp_term_taxonomy AS tt ON t.term_id = tt.term_id AND tt.taxonomy = 'asin'
    INNER JOIN wp_term_relationships AS r ON tt.term_taxonomy_id = r.term_taxonomy_id
    INNER JOIN wp_posts AS p ON r.object_id = p.ID AND p.post_status = 'publish' AND p.post_type = 'post'
    INNER JOIN wp_term_relationships AS r2 ON p.ID = r2.object_id
    INNER JOIN wp_term_taxonomy AS tt2 ON r2.term_taxonomy_id = tt2.term_taxonomy_id AND tt2.taxonomy = 'category'
    INNER JOIN wp_terms AS t2 ON tt2.term_id = t2.term_id AND t2.name = 'list'

    備忘のため解説。

    1. ターム(本)の数を数える。一冊の本が複数の投稿に属していることがあるので、本の数 (total) と延べ引用数 (c_total すなわち cumulative total) を取得する。
    2. タームが保存されているのは wp_terms テーブル。
    3. asin タクソノミーに属するタームだけを抽出する。
    4. それらのタームが関連付けられている投稿を探し出すために、wp_term_relationships テーブルを経由する。
    5. タームが関連付けられている投稿のうち、投稿ステータスが公開かつ投稿タイプが投稿のものだけを抽出する。
    6. それらの投稿のカテゴリを探し出すために、wp_term_relationships テーブルを経由する。
    7. それらの投稿に関連付けられたタームのうち category タクソノミー下にあるものだけを抽出する。
    8. その category タクソノミー下のタームが list であるものだけを抽出する。

    下は、このSQL文を組み立てるときに頭の整理に使った表。個人的にはわかりやすく作れたのでこれも備忘のためにメモ。# 列の数字が上のSQL文の行番号に相当する。新しいテーブルを ON(太字のセル=その直上のセル) で JOIN したうえで、太字セルの右セルのAND句で絞り込んで……を重ねていくイメージ。

    #ASJOINANDJOINJOINANDJOINJOINANDJOINAND
    wp_termstterm_id
    3wp_term_taxonomyttterm_idtaxonomy = asinterm_taxonomy_id
    4wp_term_relationshipsrterm_taxonomy_idobject_id
    5wp_postspIDpost_status = publish
    AND
    post_type = post
    ID
    6wp_term_relationshipsr2object_idterm_taxonomy_id
    7wp_term_taxonomytt2term_taxonomy_idtaxonomy = categoryterm_id
    8wp_termst2term_idname = list

    ちなみに、絞り込み部分をすべて WHERE句にまとめても同じ結果が得られるがずいぶんわかりづらい。

    SELECT COUNT(DISTINCT t.term_id) AS total, COUNT(t.term_id) AS c_total
    FROM wp_terms AS t
    INNER JOIN wp_term_taxonomy AS tt ON t.term_id = tt.term_id
    INNER JOIN wp_term_relationships AS r ON tt.term_taxonomy_id = r.term_taxonomy_id
    INNER JOIN wp_posts AS p ON r.object_id = p.ID
    INNER JOIN wp_term_relationships AS r2 ON p.ID = r2.object_id
    INNER JOIN wp_term_taxonomy AS tt2 ON r2.term_taxonomy_id = tt2.term_taxonomy_id
    INNER JOIN wp_terms AS t2 ON tt2.term_id = t2.term_id
    WHERE tt.taxonomy = 'asin' AND p.post_status = 'publish' AND p.post_type = 'post' AND tt2.taxonomy = 'category' AND t2.name = 'list'
  • WordPress: add_action() に変数を渡す

    LOTDの配信メールをテキストとHTMLの両方を含むマルチパートにするために検索したところ、 phpmailer_init というアクションフックが見つかった。

    do_action_ref_array( 'phpmailer_init', PHPMailer $phpmailer )

    $phpmailer のAltBody メンバーにテキストをセットすればよいらしい。$phpmailer は参照渡しされるので、返り値を送れないアクションフックでもセットできる。

    ただ、アクションは外からの変数を受け取れない。

    $text_body = (組み立てたテキスト)
    add_action( 'phpmailer_init', 'lf_altbody', 10, 1 );
    function lf_altbody( $phpmailer ) {
        // $text_body をどうやって受け取る?
    }

    これは次のようにアクションを無名関数とすることで渡せることがわかった。

    $text_body = (組み立てたテキスト)
    add_action( 'phpmailer_init', function( $phpmailer ) use( $text_body ) {
        $phpmailer->AltBody = $text_body;
    }, 10, 1 );
  • 定期/定時処理

    定期処理

    仮に「最近読まれているリスト」を1時間ごとに更新するとする。通常は次のように transient の寿命を1時間としておけばよい。

    function lf_get_poplists() {
        if ( ! $lists = get_transient( 'LF_POPLISTS' ) {
    
            // リスト取得処理
            $lists = ...
    
            set_transient( 'LF_POPLISTS', $lists, HOUR_IN_SECONDS );
        }
        return $lists;
    }

    この更新を、ユーザーアクセスに依存せず定期的に実行するようにしてみた。上記のリスト取得処理部分を lf_set_poplists() という関数に切り出したうえで、1時間おきに実行するためにスケジュール登録する。

    // フック名+引数がキーとなるので array()も明示しておく
    if( ! wp_next_scheduled( 'lf_event_poplists', array() ) ) {
        // 第5引数を true にするために第4引数に array() を設定している
        if( ! $ret = wp_schedule_event( time(), 'hourly', 'lf_event_poplists', array(), true ) ) {
            // エラー処理
        }
    }
    
    // スケジュール登録したフックとアクションを関連づける
    add_action('lf_event_poplists', 'lf_set_poplists', 10, 0);
    
    // アクションの実行
    function lf_set_poplists() {
    
        // リスト取得処理
        $lists = ...
    
        set_transient( 'LF_POPLISTS', $lists );
    }
    • wp_schedule_event() がエラー時に WP_Error オブジェクトを返すようにするためには、第5引数を true にしなければならない(デフォルトは false)。となると第4引数も何かをセットしなければならず、デフォルト値の array() をセット。イベントを識別するキーはフックと引数なので、wp_next_scheduled() にも敢えて array() をセットした。
    • フック(上の例では ‘lf_event_poplists’)というものは、対応する do_action( ‘lf_event_poplists’ ) が必要なのだと思っていた。しかしスケジューラー内にフックを起動する機構があるので不要。
    • アクションに渡す引数は array() にくるむ必要がある。以下はサンプル。
    // 引数あり(引数の数が決まっている場合)
    if ( ! wp_next_scheduled( 'lf_event', array( 'a', 'b' ) ) ) {
        if ( ! $ret = wp_schedule_event( time(), 'hourly', 'lf_event', array( 'a', 'b' ), true ) ) {
            // エラー処理
        }
    }
    add_action( 'lf_event', 'lf_action', 10, 2 );
    function lf_action( $arg1, $arg2) {
    }
    
    // 引数あり(引数の数が決められない場合)
    if ( ! wp_next_scheduled( 'lf_event', array( array( 'a', 'b' ) ) ) ) {
        if ( ! $ret = wp_schedule_event( time(), 'hourly', 'lf_event', array( array( 'a','b ') ), true ) ) {
            // エラー処理
        }
    }
    add_action( 'lf_event', 'lf_action', 10, 1 );
    function lf_action( $arg ) {
    }

    定時処理

    LOTD(今日のリスト)を入れ替えるプログラムは毎日0:01に走らせている。現在はサーバーの cron から起動しているが、これを WordPress のスケジュールシステムに乗せるためには次のようにして起動時刻を指定する必要がある(実際に起動するのは、この指定時刻以降に wp_cron() が起動された時刻になる)。

    $etime = new DateTimeImmutable( 'tomorrow 0:01', wp_timezone() );
    if ( ! wp_next_scheduled( 'lf_event', array() ) ) {
        if ( ! $ret = wp_schedule_event( $etime->getTimeStamp(), 'daily', 'lf_event', array(), true ) ) {
        }
    }
  • タイプ、タイプフェイス、フォントの違い

    タイポグラフィの十戒」の引用元は『私の好きなタイプ 話したくなるフォントの話』。タイプとフォントはどう違うのか、理解したくて検索。

    タイプ印刷された文字。
    タイプフェイス書体(例: Garamond)。
    フォント活字(例: Garamond 12pt bold)。書体の実装。
    タイプ、タイプフェイス、フォントの違い

    活字の語義は活版印刷で使われる金属や鉛の棒だが、「活字中毒」のようにタイプの意味でも使われる。

  • タイポグラフィの十戒

    まえがき

    『存在するルールが、場合によってはいかに退屈で浅はかになるかを示そうと、グラフィック・デザイナーのポール・フェルトンは文章を書き、細工に凝った美しい本に仕上げた。(略)この本にフェルトンが記した、神の与え給う戒律がこれだ。』

    リスト

    あとがき

    まえがきを含めて、サイモン・ガーフィールド 『私の好きなタイプ 話したくなるフォントの話』(ビー・エヌ・エヌ新社、2020年)より。まえがきの「美しい本」とは “The Ten Commandments of Typography/Type Heresy”。どんな本かというと:

    この本を普通に手に取ると「The Ten Commandments of Typography』(タイポグラフィの十戒)という題が書いてある。しかし、上下を逆さにして裏返すと、そこには「Type Heresy」(書体異端論)という題が現れる。

    ということで、この十戒は壊すために建てた家のようなもの。

      • 複数成分ワーキングメモリモデル (バドリー)

        まえがき

        『複数成分ワーキングメモリモデルは、4つの成分システムを仮定しており、(1)注意制御機である中央実行系と3つの貯蔵システム、すなわち(2)視空間スケッチパッド、(3)音韻ループ、(4)より一般的に統合された貯蔵システムであるエピソード・バッファから構成される。』

        リスト

        あとがき

        まえがきを含めて、アラン・バドリー 『ワーキングメモリ 思考と行為の心理学的基盤』(誠信書房、2012)より。リストは本文各所からの要約・引用です。

        • 科学的探究の4つのパラダイム

          まえがき

          『我々はいま、「データ集約型科学」 (data-intensive science) に向けてアプローチ全体を考え直さなければならない。(略)我々は大量のデータを、解決すべき問題ではなく解決策の一部と見なしている。第四のパラダイムは、科学者たちや科学的探究の他の三つの方法に取って代わろうとしているわけではない。しかし、従来とは異なる一連のスキルが要求される。』

          リスト

          あとがき

          まえがきを含めて、トニー・ヘイ『科学の「第4のパラダイム」』(DIAMOND ハーバード・ビジネス・レビュー 2011年11月号 所収、参考文献1)より。

          ジョフリー・ウェスト 『スケール 下:生命、都市、経済をめぐる普遍的法則』(早川書房、2020年)を読んでいてこの論文を知りました。

          データ・マイニングの「新しさ」を訴えた一人が、WIRED誌の元編集長クリス・アンダーソン。彼が2008年にWIRED誌に載せた「理論の終焉:データ氾濫が科学的手法を廃れさせる」という記事が引用されています。

          膨大なデータの新たな有用性は、これらの数値を処理する統計ツールと共に世界を理解するまったく新しい方法をもたらした。相関性が因果関係の座を奪い、科学は理路整然としたモデル、統一理論なしで、あるいは実のところ数学的説明がまったくなくても進展できる。

          The new availability of huge amounts of data, along with the statistical tools to crunch these numbers, offers a whole new way of understanding the world. Correlation supersedes causation, and science can advance even without coherent models, unified theories, or really any mechanistic explanation at all.

          邦訳は『スケール 下』から。原文は “The End of Theory: The Data Deluge Makes the Scientific Method Obsolete” (WIRED) より。

          「相関性が因果関係の座を奪い(Correlation supersedes causation)」という表現が印象的。

          一方でウェスト自身は『ちがいは主に程度問題でしかない』と述べています。

          「データ革命」は、長い間使ってきた戦略を活用し有効にするための、非常に大きな可能性を与えてくれた。この意味で、これはパラダイム四・〇というよりは、パラダイム三・一に近い。

          参考文献

          (1) ヘイ, トニー. “データ集約型科学が人類の危機を救う 科学の 「第 4 のパラダイム」(Feature Articles 最先端のビッグ・アイデア 「破壊的」 経営論).” Diamond ハーバード・ビジネス・レビュー 36.11 (2011): 40-54.

          • 理解するための7つの方法

            まえがき

            『より深いレベルの理解を獲得するために7つの方法を活用することで、就学前の子どもたちから大学生に至るまで、以前にはまったく関心に入っていなかった細部やテーマを理解することができるようになったのです。』

            リスト

            あとがき

            まえがきを含めて、エリン・オリヴァー・キーン『理解するってどういうこと?: 「わかる」ための方法と「わかる」ことで得られる宝物』(新曜社、2014年)より。

            まえがきは「はじめに」からの引用です。リストは巻末資料Aの要約です。「理解するための方法」について列挙型の定義や活用方法しかなく、シンプルな定義がなされていないのが残念。

            「解釈する」という言葉が「推測する」「何が大切かを見極める」「修正しながら意味を捉える」と重複するように感じたので、原文を探してみました。

            • 関連づける Activating background knowledge to make connections between new and known
            • 質問する Questioning the text
            • イメージを描く Creating mental images
            • 推測する Drawing inferences
            • 何が大切かを見極める Determining importance
            • 解釈する Synthesizing information
            • 修正しながら意味を捉える Repairing understanding when meaning breaks down

            情報を統合するといった意味合いのようです。

            • ブルシット・ジョブの主要五類型

              まえがき

              『ブルシット・ジョブとは、被雇用者本人でさえ、その存在を正当化しがたいほど、完璧に無意味で、不必要で、有害でもある有償の雇用の形態である。とはいえ、その雇用条件の一環として、本人は、そうではないと取り繕わなければならないように感じている。』

              リスト

              あとがき

              まえがきを含めて、デヴィッド・グレーバー 『ブルシット・ジョブ――クソどうでもいい仕事の理論』(岩波書店、2020年)より。

              まえがきは第1章「ブルシット・ジョブとは何か?」の結論に相当する文章の引用です。リストは第2章「どんな種類のブルシット・ジョブがあるのか?」からの抜き書き(一部編集)です。

              それぞれの類型を象徴する職業が添えられればよかったのですが、少々面倒だったので端折ってしまいました。

              すこしわかりづらい「脅し屋」について例を挙げると、企業の顧問弁護士、ロビイスト、広報専門家、テレマーケターなど。これらは誰かを脅したり操ったりするためにつくり出された仕事で、あたかも他国が軍隊を擁しているからという理由で国家が軍隊を必要とするのに似ていると説明されています。

              • 情報セキュリティのCIA

                まえがき

                『情報セキュリティは、JIS Q 27000(すなわちISO/IEC 27000)によって、情報の機密性、完全性、可用性を維持することと定義されている。』

                リスト

                あとがき

                まえがきは「情報セキュリティ」(Wikipedia 日本語版)より。リストは特定非営利活動法人日本セキュリティ監査協会 『改訂三版 情報セキュリティ内部監査の教科書』(インプレスR&D、2017年)からの引用です。Wikipedia にも定義が書かれていますが、Integrity の意味合いを酌んでいるうえに平易なことばで書かれている書籍の文言を引用しました。

                Information security” (Wikipedia) で CIA という acronym を見かけて和訳を探しました。