Notionあれやこれや

情報一元化ツールNotion遊泳のTips

Notionでランダム数字を生成する方法をリサーチした

とある制作をしたくて、Notionのデータベース内にあるページに、ランダムな数字(乱数)を付与する方法はないかと調べていました。今回は (理解が足りないので) くわしい解説は割愛し、いくつかの生成案を生み出したサイト記事を紹介させていただきます。

前置き

ランダムな数字(乱数)の生成と言っても、各サイト記事で紹介されているのは大きく分けて「静的」なものと「動的」なものがありました。実現したい内容によって異なると思いますので、前提を定義しておきます。

共通定義

データベースの各ページに、数式プロパティを追加。そのプロパティに対して、生成した乱数を表示。

静的

何回更新しても変動しない固定乱数

  • ページ追加のたびに生成される乱数を基に、何らかのマスターデータとマッピングした結果を返す、とか

動的

時間が経って更新すれば変わる変動乱数

  • 既存マスターデータから毎度ランダムに1件表示する、とか


ざっくりと調査した結果、だいたい手法は同じでした。ただ、算出するための計算式が微妙に違います。理解が追い付いていない部分があり、雑な解釈ですが、生成乱数の一意性やランダム性、数値範囲、そして作者の思想や好みも含まれているのかなと思います。

🌄静的(ページIDから算出のみ)

肝になるのはページIDです。Notionの各ページには、以下のような一意のページIDが割り振られています。
2b7561e8f08c4572a758e420149c8428 (適当)
これは16進数(0-9までの数字と、a-fまでのアルファベットの計16個で表現される数の体系)ですね。
ページIDは、数式(Formula)プロパティで関数 id()で取得できます。

すでにランダムな値ですが、Notionの数式ではこれを直接演算できないんです。"type": "string"、つまり文字列型として扱うんですね。何らかのプログラミング言語のように、10進数(0-9までの10個の数字)へ変換する関数は、Notionに備わっていません。
そこでNotion先人たちが編み出したのは、ページIDに含まれる数字だけを抜き出して、それを使うということ。

toNumber(replaceAll(id(), "[^0-9]", ""))


/** 解説 **/
toNumber(        // カッコ内の値から数値を解析して返す
  replaceAll(    // `正規表現`で指定した内容に一致するものを、指定した内容に置き換える
    id(),        // 置き換える元の値(ページID)
    "[^0-9]",    // 置き換え条件(正規表現)
    ""           // 置き換える値(なにもない)
  )
)

// ページIDから、「0~9以外の値(つまりa~fのアルファべット)」を""(つまり消す)に置き換える
// 正規表現の内容を[a-f](aからfに一致するもの)としている人もいますが、結果は同じです。
// でもa,b,c,d,e,fしか対象にしていないので、16進数にしか対応しない点は留意。

これをベースに、ランダム性を高めたり、乱数範囲を調整したりできます。
もう少し分かり易い / 具体的な説明は以下が参考になりそう。英語ですが、翻訳機能使えばだいたい把握できると思います😎

参考サイト

Notion で乱数を生成する方法!

www.youtube.com

// 1~10の乱数
toNumber(replaceAll(id(), "[^0-9]", "")) % 10 + 1

NOTION で乱数を生成する

www.redgregory.com

// RANDOM NUMBER FROM 1-10 
round(toNumber(replaceAll(id(), "[^0-9]", "")) % 90 / 10) + 1

// RANDOM NUMBER FROM 0-1
round(toNumber(replaceAll(id(), "[^0-9]", "")) % 10 / 10)

静的な乱数を使うアイデア

ページを追加するごとにランダムな数字を表示する・数字の範囲も自分次第ということで、タロットカードを引いて(ページ追加)、結果(乱数の範囲に対応したマスターカード)を返す。とか、レシピ考案を追加して(ページ追加)、食材(乱数の範囲に対応した食材)を複数返し、その組み合わせでインスピレーションを得る。とかでしょうか…

ちなみに少し話が変わりますが、補足としてNotionのプロパティにはユニークIDという一意の数値を生成してくれるものがあります。いわゆる連番ですね。ページ追加ごとに+1されるので、それでOK!という方は、ユニークID(プロパティ変更画面では省略されてIDと表示されている)でもいいかなぁと思います。ページを削除したら欠番となる&自分で手動変更はできないので、個人的に使いどころは謎…😶

🌌動的(ページIDとtimestampで算出)

既存のページに対して、変動する乱数が欲しいんだ!という場合は、「常に動いているもの」を組み合わせます。時間ですね。
先ほどの項目で触れた、ページIDから抽出した数値と現在時刻(タイムスタンプ)を演算して、毎回変わる乱数を生成します。
タイムスタンプとはざっくり言うと、ある特定の基準時点からの経過時間を表したもの。2024/02/16 10:00:00 = 1708045200 みたいな感じです。
タイムスタンプを扱うにあたって、注意点としては2つ。

  • Notionのtimestampでは、分単位までしか保持されないようです。なので更新最低単位は1分。
  • ブラウザ更新しないと乱数も更新されません。たぶんデータ更新など何らかのイベントを発生させる必要がある。

乱数生成のイメージは、私ではうまく伝えられなさそうなので、順を追って説明してくれている親切な記事を紹介します。

参考サイト

Notion でランダム シャッフル ギャラリー ビューを作成する方法

medium.com

mod(toNumber(slice(replaceAll(id(), "[a-f]", ""), 0, 4))* mod(timestamp(now())/10000, 123456), 123456)

🤖 ChatGPTで数式内容をもっと詳しく

  • id()関数
    まず、id()関数は Notion において一意な ID を生成します。
  • replaceAll(id(), "[a-f]", "")
    id()関数が生成する16進数の文字列から、小文字のアルファベット "a" から "f" を取り除いています。この部分で生成される文字列は、数字のみで構成されたものになります。
  • ❸ slice(..., 0, 4)
    上記の結果から最初の4桁を取り出しています。これにより、ID の最初の4桁が残ります。
  • toNumber(...)
    得られた文字列を数値に変換します。
  • timestamp(now())/10000
    現在のタイムスタンプを10000で割った結果を取得しています。これにより、現在の時刻からの経過秒数を短縮しています。この 10000 は、タイムスタンプを簡略化し、結果として得られる数値を小さくするための調整値と見られます。
  • mod(..., 123456)
    上記で得られた2つの数値に対して、それぞれ123456で割った余りを計算(剰余演算)しています。ランダム性を導入するための素数として 123456 が使われています。素数を使うことで、剰余演算の結果がよりランダム性を持ち、一意性が高まります。

Notionのデータベースでランダムに1件だけ表示する方法

notion-lab.jp

toNumber((floor(timestamp(now()) / 60000) * toNumber(replaceAll(id(), "[^0-9]", ""))) % 1000)

ちなみに上記でタイムスタンプを割っている60000(ミリ秒)= 1分ですが、前述の通り、Notionでは1分以内でこのタイムスタンプの値は変動してくれなかった(保持していない?)ので、この割り算は省略しても実現するのかなぁと思ったりしてます。
乱数更新のタイミングを、別の間隔・単位で行いたい場合は、Web上の計算サイトなどで調べて算出されたミリ秒(ms)で割るようにすれば良いです。


なお、調べた限りでいちばん古そうな(原案的な)ものは、Can i generate random numbers in notion?(Notionで乱数を生成できますか?) というタイトルで質問された内容への回答。こちらも参考までに残しておきます。ちょっと自分には各数字の意味が理解できない。一意性を高めるためのもの?

mod(mod(timestamp(prop("Created Time")) * 100011979 + 500067713, 900066731) * mod(timestamp(now()) * 800067089 + 800068411, 800053967) + 900067309, 900066571)

動的な乱数を使うアイデア

これは既にいろんなテンプレートがありますが、単語暗記用のシャッフルカードとか、名言表示とか、今日のコーディネート案とか、そんな感じでしょうか。

いま、こういうアイデアにプラスして、Notion通知もできないかと画策しているんですが…。GASといった外部連携を使わずに(GASなら既にrandomメソッドがある)、Notion内で完結できるTipsが無いかなぁ。

おわりに

Notionのリリースは2018年ですが、日本語には2022年11月から対応されました。なので、日本人ユーザー数はまだまだ少ない気がしています(実際私も数カ月前からデビュー😂)。
Notion関連で何かをリサーチする時は、英単語で調べると海外の方の記事が豊富な印象です。最近はブラウザの翻訳機能に感謝する日々です。