Make組ブログ

Python、Webアプリや製品・サービス開発についてhirokikyが書きます。

会社の説明動画をアバターと一緒に撮ったら再生数が50回から1000回になったという、Twitter的な話

アバターと一緒に撮ったら再生数が50回から1000回になった話

こんにちは。

会社説明を人間が一生懸命する動画は50回しか再生されなかったのに、アバターと話すおもしろ動画を撮ったら1000回も再生されました、という話です。

前提に違う点が多くありますので、単純に「アバターで撮影したら成果が20倍!」という話ではありません。ただ私的に面白かったので感じたことをメモした記事だと思ってください。

アバターと会話形式にした動画

とある会社説明の動画を作っているときに、「話の聞き役がほしいな」と思いました。せっかくVRやAI音声合成の技術が発達していますので、新技術で遊んだ動画が作れないかなと思い、試しに撮ったデモ を1000回も観ていただきました。

もともとは「こんなことしちゃう俺デュフフ」的なもので、ツイートする行為自体もちょっと痛々しいネタです。ネタに走れば良いというわけではありませんが、少し今回の反応を考える意味はありそうです。

もともとあった真面目な動画はあまり観られなかった

それ以前にYouTubeで投稿してツイートした動画は、50回ほど観ていただきました。

www.youtube.com

単純には比較できませんが、あまり伸びなかったのは事実です。

もちろん真剣に説明した長めの動画ですので、50回観ていただいただけでも非常にありがたいです。さらにYouTubeにアップロードしたものをツイートしたので、上記の動画と再生数だけを比べて良し悪しの判断はできません。

ただ、「新しく知ってもらいたい」という目的であれば、真面目なだけではダメなようです。

何が違ったのか? Twitter受けとは何か

アバターと会話する奇々怪々な動画は、Twitterという文脈で良かったということでしょうか。

以前、ある方に「SNSを眺めている人には、噛み砕いた流動食を口元まで持っていく」必要があると教えていただきました。ものの例えとして「それくらいの気持ちで発信しなさい」という意味合いです。たしかに今回の動画は「脳死でも楽しめるコンテンツ」ではありますし、見たいなと思わせる何かもあります。

取っ掛かりとして面白かったのは、会社やWebサービスではなく「アバターと会話する妙なお兄さん」 という部分です。さらに音声合成というのもあって、アバターメタバース音声合成に興味のある人が楽しんでくれた印象でした。

それでは「会社紹介になっていないだろう!」という心配もありますよね。そこで動画を観てくれた人に直接、感想を聞いておきました。その人が内容をハッキリと覚えていないのは事実でしたが、「こういう事業をやっているんだなぁ。AIを使ったWebサービスもできる時代なんだ」という印象は伝わったようでした。

もちろん会社やサービスの紹介という部分を疎かにしたり、面白さを求めて過激になったりするのは良くありません。そして仕事としてやるのであれば、より関心を持っていただいたり、具体的なアクションに繋がらないと意味はありません。

ともあれ、まず知ってもらう必要はありますし、ハードルを下げる何かは必要なようです。道化とまでは言いませんが、「楽しんでいただけますよ」という雰囲気は必要なようです。まぁ考えてみると、自分自身もTwitterでは面白いネタや体験談のマンガ、ニュースの速報を見がちな気がします。反応しやすいですからね。

立派に主張するような発見はとくにありませんが、真面目だけではウケないのがSNSという世界のようです。

おわりに

今回の動画自体がある種のデモですので、ちゃんとした動画はどこかでお見せできると思います。ぜひ @hirokikyをフォローしてください!

また、Shodoに興味を持っていただけた方は、無料から使えますのでぜひご利用ください。

shodo.ink

執筆:Kiyohara Hiroki (@hirokiky)Shodoで執筆されました

4年間、同じ服を着て気づいたこと

追記:結局、またさらに1年同じ服を着ていました

私の娘は2歳なのですが、父が黒いTシャツ以外を着ている姿を見たことがありません。

この4年間、同じ服をずっと着ていました。

今日はその4年間、同じ服を着て気づいた発見を皆さんにお伝えしようと思います

同じ服ってどういうレベルで?

事前に仕様の説明から入らせてください。

この4年は以下の服を着ていました:

  • 基本
    • 黒の無地クールネックTシャツ(ヘインズのプレミアムジャパンフィット)
    • ジーパン(EDWIN 402)
  • 上着
  • 温度調節用

僕に会ったことがある人は「あー」と納得いただけると思います。

ケンオールパーカーを着がち

2019年に書いた記事のスタイルから基本的に変わっていません。

どれくらい同じ服だったのか

完全に誰得の情報なので、読み飛ばしてOKです。同じ服を着る生活をしてみたい人は参考にしてください。

  • 黒のTシャツとジーパンは、ほぼ100%毎日着ていました。唯一スーツを着るときに白の下着を着ただけです
  • 型番の誤差として、Tシャツにはスリードッツのジョシュが8枚中2枚、ジーパンはアメリカンイーグルのスリムが5本中2本入っています
  • 黒ワイシャツやタートルネックなどは春や秋ごろに、Tシャツだけだと寒い日などに着ていました
  • 靴はM996からAllBirdsに途中で変わりました
  • 寝間着はイベントのTシャツなど比較的自由ですが、最近はグレーの無地スウェットを多く着ています
  • 下着については同じものを買い続けることが難しく、Amazonで似た黒の靴下やパンツをまとめて買っていま

意外とジョブズもゆるい

「同じ服を着る人」として有名なスティーブ・ジョブズマーク・ザッカーバーグもゆるいところがあります。

ザッカーバーグ氏はグレーのTシャツしか着ないと言われつつ、Metaへの社名変更発表時に黒のシャツを着ていたりします。スティーブ・ジョブズも実は靴の型番を変えていたり、休暇中に白いシャツや半ズボンをはいた写真が残っています(娘のエリンと金閣寺で撮った写真など)。

まぁそういった「同じ服を着ていると認識されている人たち」も本当に100%ずっと同じ服ではないので、僕も「同じ服を着ていた」と言って差し支えないと思います。

4年間、同じ服を着て気づいたこと

本題です。

こういった記事は良い点ばかり列挙しがちですので、今回はとくにマイナスの面も意識して紹介したいと思います。 4年間、同じ服を着て気づいたことを5つ聞いてください。

スーツは要る

断言しますが、スーツは要ります。

少なくとも、友だちの結婚式に行けるようなスーツは必要です。 他にも大事な商談のときや、銀行に行って会社の融資をお願いするときなど、スーツを着るべきときは現実に存在します。

スーツを着るべき場面を、セットアップやジャケットだけで誤魔化すのは少し難しいと思います。 「考えることを減らすため」に同じ服を着ているフシもあるので、「スーツでなくて良いだろうか?」と気になるほうが本末転倒です。

「絶対にどんな状況でも大丈夫な服」を着続けたい、と考えないほうが良いです

そんなものはありません。

ジーパンで結婚式にはいけませんし、スーツでプログラミングをしたくありません。先述したような季節用のワイシャツなどもそうで、あまり厳密に「絶対にこのTシャツとジャケットしか着ない!」とすると状況や気温にあわせられなくて、逆に考えることが増えます。

仮に「袖が着脱可能なセットアップ」と言えるものを用意しても、僕はあまり好きじゃありません。それはすでに「1つの服」ではないからです。であれば、状況や季節に応じた服を着たほうがシンプルです。生き方をシンプルにしようとして手段や振る舞いが複雑であれば意味はない、と考えています。

スーツを着る場面では、スーツを着るのがシンプルな生き方です。

着たい服を買えない苦しみはある

1ヶ月、プロテインだけ食べて生活してください。 食事から得られていた幸せの大きさに驚くと思います。

それと同じで、「着たい服を着る」という幸せは案外大きかったんだと気づきました 僕は欲しいTシャツがあっても「これは着られない」と諦める必要があります。

ふと買い物に行ったときやネットで見かけたとき、推しがグッズを出したときなどありますよね?ほとんどの場合、諦める必要があります。これが案外、寂しいものです

そういった日常の小さな喜びが減ってしまいます。ある意味では、その可能性を断つことで余計なことを考えずに済んでいると言えます。

公私の区別をつけにくい

意外な盲点なのですが、精神的に公私の区別をつけにくいです。

休日も平日も同じ服に着替えますので、「よし今日は仕事だぞ」というようなメリハリが生まれません。とくに最近は自宅で仕事をする機会も多いので、何らかの切り替えスイッチは欲しいものです。

人間には着ている服や周囲の状況から自分の気持ちや感情を調整する機能があるように思います。僕の場合は部屋を1つ仕事用にしていますが、同じ服を着て生活するのであれば何かしらの切り替えスイッチは用意したほうが良いです。

考えることは案外増える

「同じ服を着れば考える回数が減る」とも言い切れません

たしかに毎朝服について考えることは減ります。そこは楽です。ですが「同じ服を着る」という思想自体を考える機会は増えます。たとえば前述の通り服が買えないなと残念に思ったり、定期的に今の型番の服で良いか検討したり、このブログ記事を書いたりします(逆にめちゃくちゃ考えてるが!)。

だんだん慣れて考えることは減り、4年も経てばほぼゼロになりますが、最初の1年くらいは考えることが増えると思ってください。

服飾について一番考えない状態が何かと言うと、「着たい服を深く考えずに買って、毎朝何も考えずにあるものを着る状態」だと思います。つまり、普通でいることです。

とはいえ、僕はズボラなわりに「この着合わせで良かったかな?」と心配になったり、「今日はこの服で良かったかな」とずっと気になる人間なのです。「この服を着ているということは、こういう感情だと予想されるのではないか?」とまで考えることもありました。

そういった憂慮の余地がなくなったのは、同じ服を着ていて良かったことです。 ですが「同じ服を着ることについて考える」機会は、始めてから1年はとくに増えます。

「いつも最高の自分」ではない

ネットで同じ服を着ることについて調べると、利点として「いつも最高の自分でいられる」というような表現を目にします。

断言しますが、いつも最高の自分ではありません(たぶんこれを言う人はエアプ勢だと思います)。 「いつも、いつもの自分でしかない自分」が正しいと思います。

誰だって良いスーツを着ているときやドレスを着ているときが最高だと思います。それはそうですよね。他にもオシャレな服屋さんでマネキンが着ているセットを買うほうが、誰にとってもより良い状態だと思います。

バッチリした服をバッチリ着て最高と思っている人の姿:

スーツをバッチリ着たほうが最高なのは間違いない

良い服だね!と褒められることはなくなります。「同じ服を着ているね」と言われたことすらありません。おしゃれをしたいのであれば「同じ服を着るのがファッションだ」なんて思い違いをせずに、素直におしゃれをするほうが良いです。

ただ、自分の中で外さない、好きなスタイルで居られることは事実です。その状態に無思考でなれる、というのが良い点です。

同じ服を着る生活はおすすめできる?

おすすめできません

多くの人にはできません。

準備や制約がある一方、とくに内面的なメリットは大きいと感じられず、誰かから褒められることもありません。僕にとっては結構快適ですが、不自由があるのは事実です(むしろ不自由を選択している)。

もし「仕事では決まった服やスーツを着ている」という人がいれば、案外それが良い答えだなと感じます。考えることを減らせますし、仕事モードに入りやすいです(もちろんプログラミングにスーツは向いていません)。

もともと同じ服を着たい傾向があるのであれば、試す価値はあります。自分のもともとの精神構造が重要なポイントです。たとえば「すでに靴下は黒の1種類で統一している」ような人であれば、Tシャツやズボンも統一して良いと思います。ただ、あまり真剣になりすぎる意味はないと思います。

僕は気に入っているのでこれからも続けると思います。ですが、より楽な気持ちでいようかなと思います。まぁ、どんな服を着ていても、僕は僕です

一番気づいて良かったのは、そういう部分なのかもしれません。4年かかってそれかよ、という内容ですね。

ここまで読んでくれてありがとうございます。


もし気になることや相談したいことがあれば @hirokiky に聞いてください。同じ服を着ることについては、平均的な人よりも続けているほうだと思います。

執筆:Kiyohara Hiroki (@hirokiky)Shodoで執筆されました

JavaScriptのClipboard APIでリッチテキスト(書式付きテキスト)をコピーする

クリップボードにリッチテキストをコピーする方法を説明します。今回はとくにClipboard APIという現在推奨された方法で実装します。

「リッチテキストをコピー」というのは、ペーストしたときにWYSIWYGエディターへ書式が有効なまま入力されることを言っています。たとえばWordでコピーをすると、見出しや太字などを含めてコピーされるのと同じことです。

Clipboardを使ってリッチテキストをコピーする

標準のClipboard APIを使ってリッチテキストをコピーするには、以下のようにします。

const body = '<h1>見出し</h1><strong>太字</strong>'

const blob = new Blob([body], { type: 'text/html' })
const blobPlain = new Blob([body], { type: 'text/plain' })
const item = [new window.ClipboardItem({ 'text/html': blob, 'text/plain': blobPlain })]

await navigator.clipboard.write(item)

(たとえば「コピー」ボタンをクリックしたときなどに実行してください)

MIMEタイプに 'text/html' と指定して、Blobを渡すことでできます。こうすることでHTMLと認識させられるので、WordやWYSIWYGエディターへペーストしたときに書式が有効となります。Google Chromeの場合、コピーしたHTMLは自動でサニタイズされます。

実装するときは 'text/plain' としてもコピーしてください。そうしないと、メモ帳などにプレーンテキストとして貼り付けられるときに動作しません。

Firefoxは未対応

2022年1月26日時点ではFirefoxがHTMLのコピーに対応していません。

window.ClipboardItem が存在するかなどをチェックして、ない場合は navigator.clipboard.writeText を使ってプレーンテキストのみコピーするのが良いと思います(細かい実装の話はお任せしますが)。

Google Chromeで対応された履歴はこちらです。

chromestatus.com

Google ChromeSafariではできるので、そこまで困らないのが事実です(僕はFirefoxユーザーですが)。

document.execCommandは使わない

以前まではClipboard API経由でリッチテキストをコピーできませんでした。少し前の記事ですと document.execCommand('copy') とイベントリスナーを使って何とかする方法も書かれていますが、現在は避けたほうが良いかと思います。

document.execCommand 自体が非推奨になっていますので、できれば Clipboard を使いましょう。

developer.mozilla.org

まとめ

Clipboard APIを使ってリッチテキスト(書式付きテキスト)のコピーはできます! Firefoxは執筆時点で未対応ですが、そこは割り切れる範囲かなという気もします。

document.execCommand('copy') はなるべく使わないようにしましょう。

今後、対応されていくと良いなと思っています。

caniuse.com


執筆:Kiyohara Hiroki (@hirokiky)Shodoで執筆されました

Pythonで`{文字列: 数値}`の辞書から数値が最大のキーと値を取る

{文字列: 数値} のような辞書(Dict[str, int])があるときに、数値が最大・最小のキーと値を取得する方法です。

たとえば文字の出現回数をカウントしているときなどに使えます。

>>> d = {"a": 3, "b": 2, "c": 1}
>>> k, v = max(d.items(), key=lambda x: x[1])
>>> k
'a'
>>> v
3

他にも sorted()min() でも使えます。

collections.Counter とも併せて使えるので便利です。

>>> from collections import Counter
>>> d = Counter("aaaaabbbcc")
>>> k, v = max(d.items(), key=lambda x: x[1])
>>> k
'a'
>>> v
5

タプルのリストが便利に使える

タプルのリストから最大値、最小値を取ると便利に使えます。

たとえば辞書のキーにできないオブジェクトの場合は、第一要素に数値を持つタプルを使うと似たことができます。 この例では辞書がひも付いているとしました。

>>> l = []
>>> for i in range(5):
...     l.append((i, {}))
... 
>>> l
[(0, {}), (1, {}), (2, {}), ...]
>>> max(l, key=lambda x: x[0])
(4, {})

key= を指定しない場合、第1要素の数値が同値の場合に第2要素が評価されますので注意してください。

タプルのリストや key= 引数をうまく使えば、何らかの値に数値がひも付いているときに最大値や最小値を取得できます。

執筆:Kiyohara Hiroki (@hirokiky)Shodoで執筆されました

社会って論理的じゃないよね。僕らの弱さ、そして小野マトペ氏の裁判に感じること

皆さんのコメントを読んで、反省しました

皆さん、たくさんのコメントありがとうございます。 僕自身の考えや文が稚拙であったことを反省しました。

まず、僕は「社会は論理的でないところがある」ように書きましたが、これは良くなかったなと考えを改めました。 僕の間違いは、自分は論理的に考えていると思っていたものの、社会の中にある論理や合理性を軽視していたということです。 自分に理解できないものを、論理ではないものだと考える、感情的なものでした。 さらに文自体も感情的で良くなかったと反省しております。

皆さんのコメントのおかげで気づけました。ありがとうございます。 僕は、自分以外の世界というのに少し感覚が弱かったというか、軽視していたのだと思いました。

この記事について、削除してしまおうかとも思いましたが、僕自身が反省して学びこれからに活かすため残しておこうと思います。 内容はそのままにしておりますので、それを前提に読んでいただけると幸いです。

改めて、教えていただきありがとうございました。 そしていつも読んでいただき、ありがとうございます。

本文

社会って案外、論理的じゃないよね、と感じた話をさせてください。

いえ、僕こそホントは論理的でなかったと勝手に反省した 。オチを言うとそういう話です。

小野マトペ氏の裁判が終わり、個人的に「うわぁ」と思ったので感想です。

平たくまとめてるとこういう裁判です:

  • Twitterで「俺はコロナ」とネタをツイート
  • 居酒屋に行って写真をツイート
  • 刑事事件(偽計業務妨害)になる

もとの話はこちらを: note.com

何が怖いのか

まさに自分のことだったからです。

この裁判は控訴棄却で有罪判決となりました。 「ネタであり業務妨害をする気なんてなかった(故意でない)」という点が裁判において認められなかったということですね。

でも僕自身にも、すごく心当たりがあるんですよね。 まるで自分のことかと思いました。

Twitterでその日盛り上がった話題やニュースに、ちょっぴり過激な面白いことを言いたいことってあるじゃないですか。 友だちと飲み会をして「濃厚接触!」なんて冗談を飛ばしたいときもあります(ネットには書かないネットリテラシーを発動)。

もちろん、褒められたことではありません。 でもそんな、なくもないことが刑事事件になってしまう んだなということです。 僕も反省するところです。

たしかに前後関係を繋げていけば「業務妨害になっても構わないと思ってますよね?(未必の故意である)」と追い詰められる状況になります。

社会は論理的じゃない、そして僕こそ

僕が感じる「ロジック」とは違う論理があると言うべきでしょうか。そして自分が思っているほど、自分が論理的ではなかったということです。

裁判を見ると、小野マトペ氏が「故意に業務妨害をやったぞ!」と言える決定的な証拠はないわけです。 たとえば「店を名指しした犯罪行為を感じさせるツイート」など明らかなものはありません。

さらに、民事的ないざこざではないので、刑事的な「故意に犯罪をやっているかどうか」が争点なわけですね。

ただ、社会には「社会的に見てどうか?」という倫理による力があって、(情勢も鑑みて)納得感のある正義が勝ったわけです。 僕の学びとしては「ロジカルに言えば問題ないでしょう、とは言えない」、「納得感や社会的な倫理が重要な世界なんだ」という社会の掟に気づいたことです。

でも、そう考えれば、当たり前のことを言ってしまっていますね。

僕の弱点:論理的思考だと思ってしまう

論理的思考こそ至高なのではないのですか? そうなのですが、その思考が危ういんですね。

社会や法における「論理」と僕が感じている「論理」や合理性は違うものなんだなと分かりました。 いえ、むしろ本当はエンジニアの世界にもロジックだけじゃないものが大事なはずなんです。

そうでない、社会のもつ「納得感」が、一般的な世界の枠組みにおいて重要視されるわけです。 実際に小野マトペ氏の記事を読むと、論理や「自分の中にある正義」を大切にされてると分かります。

社会的な倫理観や、情勢、思惑や納得感を考える(おもんばかる)のも重要なんですね。 人の気持ちや常識、そしてそれらを動かす修辞や弁論も重要なわけです。

論理的思考は僕たちの世界においては絶対の理!と考えるのも、むしろいびつなんでしょうね。 正直、僕自身も上手に生きられてるとは思いません。

僕が学ぶこと

僕が学ぶこととしては、論理的思考だけで物事は決まらないと受け入れるだと思います。 実際に世の中は社会的な倫理観や納得感、そしてそれらを動かすレトリック(修辞)や弁論術やリテラシーが重要なようです。

飛躍してしまえば「有罪かどうかも修辞や弁論に左右される」ということですよね。 「いやいや、そのために弁護士がいるんでしょ!」と思った方は、そのとおりです。 小野マトペ氏のまとめ記事にも、弁護士を選ぶことが相当重要であったと反省が書かれています。

むしろそれこそが学びです。

「己の潔白と事実を説明して共感してもらえば分かってもらえる」と思っていませんか? そんなことはなかったんですね。 そもそも、社会的な通念を重んじるのも大切なんですね(当たり前のことですが)。

僕は、自分の「論理が正しい」思考を改める必要があると思いました。 そして合理的な時代の今だからこそ、修辞学(レトリック)や弁論術、そして法学や倫理こそ学ばないといけないのかな、ということです。

おわりに

ぜひ小野マトペ氏のまとめ記事を前半から読んでください。

あと、これに関したおすすめの本です。 このリンクから買ってくれると嬉しいです:


執筆:Kiyohara Hiroki (@hirokiky)Shodoで執筆されました

DjangoのQuerySetでグループごとに最大・最小のデータのみ取得する

DjangoのQuerySetでグループごとに最大・最小のデータのみ抽出する方法を紹介します。 この記事はDjango Advent Calendar 2021 3日目の記事です。

グループごとの最大・最小のデータとは何でしょうか?

たとえば以下のような場合に必要となります。

  • ブログ記事ごとに最新のコメントのみ取得
  • ユーザーごとに金額が最大の購入履歴のみ取得
  • ページごとにリビジョン番号が最大の差分データのみ取得

実際に仕事をしているとたまに欲しくなりますよね。

今回は Parent モデルというグループごとに、 Child モデルの number が最大になる Child の一覧を取得します。

class Parent(models.Model):
    pass
    
class Child(models.Model):
    parent = models.ForeignKey(Parent)
    number = models.IntegerField()

Meta__str__ は表記上省略)

QuerySetでグループごとに最大・最小のみ取得する

最大のみ取得する処理は以下のようになります(解説は後述します)。

children = Child.objects.all()
sub_qs = children.filter(
    parent=models.OuterRef("parent"),
    number__gt=models.OuterRef("number"),
)
qs = children.filter(~models.Exists(sub_qs))

実際に動作を確認してみましょう。 p1p2というグループごとに最大の値を持つ c1_4c2_2 のデータを作りました。

>>> p1 = Parent.objects.create()
>>> p2 = Parent.objects.create()
>>> c1_1 = Child.objects.create(parent=p1, number=1)
>>> c1_2 = Child.objects.create(parent=p1, number=2)
>>> c1_3 = Child.objects.create(parent=p1, number=3)
>>> c1_4 = Child.objects.create(parent=p1, number=4)
>>> c2_1 = Child.objects.create(parent=p2, number=1)
>>> c2_2 = Child.objects.create(parent=p2, number=2)
>>> children.filter(~models.Exists(sub_qs))
<QuerySet [<Child: 1-4>, <Child: 2-2>]>

Child: 1-4c1_4)とChild: 2-2c2_2)の取得を確認できました。

SQLは以下のようになりました(読みやすいよう改行を追加しています)。

SELECT "child"."id", "child"."parent_id", "child"."number"
FROM "child"
WHERE NOT EXISTS(
    SELECT (1) AS "a"
    FROM "child" U0
    WHERE (
        U0."number" > "child"."number" AND
        U0."parent_id" = "child"."parent_id"
    ) LIMIT 1
)

この処理では「グループごとに最大・最小の値が複数ある場合に両方とも取得される」点に注意してください。

解説

今回のSQLでは「よりnumberが高い値のある行を除外する」という方法で、グループごとの最大値を取得しています。直感的にはGROUP BYで最大値を計算するサブクエリーを書きたいところですが、実行速度が速い方法を紹介しました。

Djangoではこのサブクエリーを書くために、 OuterRefExists を使っています。OuterRef を使えば外側のクエリー中のフィールドを参照できますので、サブクエリーを簡単に書けます。 今回の場合は OuterRef("parent") でグループにする Parent を指定し、 OuterRef("number") で除外対象の number を指定しています。

実際の環境で高速に動作するかどうかは、データベースの実行計画を確認してください。 データベースやデータの内容によって変わってくると思いますので、仕事の環境で使う場合は実行計画を見ましょう。

GROUP BYを使った書き方も紹介しておきます。

他の書き方

参考として、GROUP BYとサブクエリーを使った方法も紹介します。

children = Child.objects.all()

sub_qs = children\
    .filter(parent=models.OuterRef("parent")) \
    .values("parent") \
    .annotate(max_number=models.Max("number")) \
    .values("max_number")
qs = children.filter(number=models.Subquery(sub_qs))

SQLは以下のようになります。

SELECT "child"."id", "child"."parent_id", "child"."number"
FROM "child"
WHERE "child"."number" = (
    SELECT MAX(U0."number") AS "max_number"
    FROM "child" U0
    WHERE U0."parent_id" = "child"."parent_id"
    GROUP BY U0."parent_id"
)

この処理はサブクエリー内で number の最大値を求めたうえで、その値を条件として Child の一覧を取得しています。こちらのほうが NOT EXISTS を使った書き方よりも理解しやすいですが、処理としては遅くなると思います(実際のデータや環境でお試しください)。

おわりに

DjangoOuterRefSubqueryExists を使ってグループごとに最大・最小の値のみを取得しました。 昔は「Djangoで凝ったSQLを書けない」という印象もありましたが、今のDjangoではクエリーの表現が多彩ですので、今回のようなサブクエリーも直感的に書けます。

ぜひ、業務の中でも活用していただけると嬉しいです (実行計画の確認はしてください)。

ちょっと聞いてください

このブログ記事は私の会社で開発しているShodo(https://shodo.ink/)を使って執筆されました。 Shodoは書いた文章をAIがリアルタイムにチェックしてくれるWebサービスです。

ただのAI校正ツールではありません。 エンジニアの皆さまにも嬉しい特徴がたくさんあります。

と、お勧めできます。

さらにGitHubのようなワークフローで記事を書けるのも特徴です:

  • 記事を書く日程やステータスを管理したり
  • 複数人で記事のレビューコメントやレビュー依頼をしたり
  • 共有リンクからたくさんの人にコメントをもらったり

そんな便利なWebサービスです。

今ならなんと!技術アドベントカレンダーの期間中、Shodoを無料で使えるキャンペーンを実施しています。 これから技術ブログを書く皆さん、ぜひShodoで技術記事を書いて知識やノウハウを共有しませんか?

クーポンコードはこちらから。 ぜひお試しください。

blog.shodo.ink

執筆:Kiyohara Hiroki (@hirokiky)Shodoで執筆されました

「若者エンジニア」が30歳になりました。老いが急激に加速するのはなぜ?

こんにちは。hirokikyです。

僕の個人的な話をしますが、4分ほどで誰でも気軽に読めるようまとめました ので、ぜひお付き合いください (5分の動画より短いです)。

今日の 2021年11月5日で、30歳になりました。 そしてこのブログも、もう10年以上やっていることになります。

僕は20歳のころからプログラミング(Python)界隈と関わりを持っていました。 当時は「若者Pythonエンジニア」と受け入れられたように覚えています。2011年ごろはまだRubyの全盛期で、わざわざPythonを選ぶのは少し変わった人たちでした(ChefやCoffeeScriptが流行り始める時代感です)。 そこに現れた20歳の僕や、同年代のPythonエンジニアはさらに珍しかったのです。

2012年のPyCon JPで併設カンファレンスを開催したとき

(2012年の併設カンファレンスでの懇親会)

「若者エンジニア」という名札は便利でした (正直に言ってしまうと)。

あれこれと技術について質問をしても、多少過激なことを言っても、周りは温かく受け入れてくれます。むしろ、その少し攻めた姿勢も良かったのでしょうか。臆せず質問や登壇、イベントの主催ができたように思います。親切な皆さんに助けていただいたり、一緒に仕事をしたり、イベントをやったりと楽しい日々でした。他にも自社で企画開発したWebサービスをお客様に買っていただいたり、そして起業したりと良い20代だったように思います。

DjangoCongress JP 2019の集合写真

主催したDjangoCongress JP 2019での写真(また皆んなで集まりたいね)

でもそんな若者エンジニアも、今日で30歳になります。

つまり、若さという免罪符が失効してしまったのです。

これからは大人の生き方を考えなければいけません。

...

と、文が続くと思ったのではないでしょうか。

いや、そんなことはありません。 若者らしさがなくなるのは、僕としてはどうでも良いのです(実を言えば27歳くらいから若者ではないですし)。

僕の中で困ったことは他にあるのです。

重鎮感 です。

何か「年上や先輩として気を遣われている感」、「界隈で歴の長い人として大切にされている感」です。 ときおりヌルリと感じるこの「圧」を、ここ数年感じていました。

たとえば軽い気持ちで「よしやってみよう」と言ったつもりで、周りの人がガッツリと作業に入っていた、などです。 他にもTwitterで「ああいうことやっても意味ないよ」とツイートすれば、知らないところで誰かが傷ついていたとか。

どちらにしろ僕が悪いだけです。

あと、少しうぬぼれすぎかもしれません。 僕はそこまで影響力のある人間ではないです(すいません)。

ですが、皆さんも何か心当たりがあるのではないでしょうか?

  • 「軽い気持ちで言ったのに、思ったより大事な発言になっていた」
  • 「いつの間にか、会議で発言が待たれている」

規模の大小はあれ、年を重ねたり、同じ業界でずっと頑張っていると誰しもが重鎮らしくなるわけです。 より一般化して言うと 「他人はあなたを、ロールに収めたがっている」 ということです(たとえば「決めてくれる人」)。 僕自身も他人にそれを期待してしまっています。

正直、若さを失うことはどうでも良いです。

ただ、 実際の現実は若さがなくなるだけでなく「老けさせようという圧力」がある んです。 より具体的に言うと 「他人が期待するあなたの姿へ、あなた自身を押し込む圧力」ということ です。

30歳くらいになった人が、急に老けてくる現象ってありますよね。 あれは、一度確立した自分の姿や「先輩としての自分」で留まると起こるのかな?と最近思います。 昔は尖ってカッコよかったのに、今は時事ネタのご意見番になった知識人などもそのタイプだと思います。

この力はおそらく人間心理的なものなのかなと思います。 責任や発言力、信頼や立場などというものが絡み合って、周囲が求める「あなた」という像が固定化されたのでしょう。あなた(そして僕)自身も誰かにそれを期待しているわけです。

でも僕は、 周囲が期待する僕に飲み込まれるのはカッコよくないな と思うわけです。 「適度に周りが気持ちいいことを言っていればいい」と迎合したり、「あの人が動いてくれるだろう」と無思慮に他人へ期待することです。そうすると、何も考えなくても案外生きられてしまうんです(現状への過学習というか、局所最適化というか)。

その他人が求める役割に浸っていると、人は急速に老いるわけです。 それがおそらく、30歳前後にある1つの分岐点なのでしょう。

若さがなくなるのは別に構わないんです。気遣いを勘違いしたり、自分が確立した自分に収められる力へ負けると、急激に老いる気がします。 努力した分だけ「先輩の威厳」や「重鎮感」まで追加されます。でもそれは相手の優しさであって、あなた(僕)のすごさではないんです。

なので、僕はなるべく初めて会う人や話してくれる人に、なるべく相手の立場を考えて話そうと思います。 そして、他の人にもロールや名札に落とし込んだような話し方はしないでおこうと思います。

世の中に、接しやすい先輩や、イジりやすい年上の人っていますよね?あの人たちは謙虚なんじゃなくて生存戦略としてああやってるんです。自分を重鎮扱いして固定化しないでくれよー!老いさせないでくれよー!というアピールなんですね。役割を捨てたピュアな関わりを、あなたと持ち続けたいんです(僕はどうにも絡みにくい人間になりがちなので、尊敬します)。

若さを失うことは怖くないですが、老けさせようという圧力は恐ろしいものです。 そして僕はこれからも抗っていきたいと思います。

そんなことを感じる、元、若者エンジニアでした。

ハッピーバースデー僕!

これからも頑張って良いものを作りますので、応援いただけると嬉しいです。

そんなわけで

そんなわけで、老いに抗っている僕が作っている新しいWebサービスがこちらです。

ブログ記事やプレスリリースを執筆する 「当たり前」のやり方を変えたい と思っています! まだまだ至らないところはありますが、頑張ってどんどん良くしていきます。

shodo.ink

以上です!

ここまで読んでくれてありがとうございます。


執筆:Kiyohara Hiroki (@hirokiky)Shodoで執筆されました