ミツモア Tech blog

「ミツモア」を運営する株式会社ミツモアの技術ブログです

JsonLogicで複雑な条件分岐をシンプルに実装する

※ こちらはミツモアAdvent Calendar 2021の12/23分の記事です。

こんにちは、ミツモアのエンジニアの宮内です
本記事ではJsonLogicについて簡単に紹介します


ミツモアは「リモートワークが増えてエアコンを綺麗にしたい」「引っ越しで出た不用品を回収してもらいたい」といった生活のあらゆるシーンであなたにぴったりの専門家を無料で探せるサービスですので、ぜひ気軽に使ってみてください!

meetsmore.com


ミツモアのコアバリューは、
「依頼者は質問に答えるだけで、ぴったりの見積もりがすぐ届くこと」です

ぴったりの見積もりを届けるために、
ユーザーがミツモア上で入力した情報をもとに条件分岐を重ね
依頼内容に合った見積もりを自動で算出します

依頼するサービスによって質問内容は様々
ユーザーによって回答内容も様々
If文でハードコーディングなんて!無理!です
そこで活躍してくれるのがJsonLogicです

JsonLogicとは

https://jsonlogic.com/

JsonLogicとは、ほとんどコーディングすることなく、
複雑な条件分岐を実装できる便利なモジュールです
判定ルールとデータは、Json形式で扱います

こんなふうに使うよ

jsonLogic.apply() を使います

  • 第一引数に判定ルール
  • 第二引数に判定するデータ

以下の判定を行いたいとすると

( 3 > 1 && 1 < 3)

JsonLogicでは以下のようにして結果が得られます

jsonLogic.apply(
    {"and" : [
      { ">" : [3,1] },
      { "<" : [1,3] }
    ] } // 判定ルールのみ渡す
)
// true を返す

また、varというオペレータを使用することで、データから特定の値を取り出すこともできます

ex ) Keyがaの値を取り出したい

jsonLogic.apply(
    { "var" : ["a"] }, // 判定ルール
    { a : 1, b : 2 }   // データ
);
// 1

判定ルールをJsonで扱える利点は、DBに判定ルールを保存することができることです

ミツモアでユーザーが作成した依頼はObjectデータとして保存されます
依頼するサービスに関連づいた判定ルールを、必要な時にDBから取得して、依頼内容データとともにJsonLogic.apply()に渡せば、うまいこと処理してくれるわけです

こういった形で、複雑な分岐処理のコーディングが不要になります

判定ルールはどう生成する?

複雑な判定ルールになるほど、手で書くのは大変です!
ミツモアではreact-awesome-query-builderを使って、UIで条件を組み合わせて判定ルールを生成しています
UIで設定された判定ルールを、Json形式で出力してくれるモジュールです

github.com

このモジュールの詳しい使用方法についてはまた別の機会に紹介できたらと思います

利用例

ミツモアでの利用例を簡単に紹介します

以下が、顧問税理士でユーザーが依頼を作成した際に使う判定ルールだとします

質問「現在の従業員数はどのくらいですか?」
回答「20人以上」
かつ
質問「事業形態は?」
回答「個人・個人事業主」
であるか

react-awesome-query-builderで条件を設定し、フォームが出力したJson形式のルールをDBに保存します

f:id:meetsmore:20211223130836p:plain
react-awesome-query-builder

顧問税理士で依頼が作成されたら、DBから取得した判定ルールと回答内容をJsonLogic.applyします

JsonLogic.apply(
    { DBから取得した判定ルール },
    { 依頼者の回答内容 }
)

applyした結果、trueが返ったら、機械学習Aモデルでマッチング

といった感じで利用しています

便利なオペレーターたち

最後に、オペレーターを紹介します
公式でデモを試せるので色々触ってみると面白いと思います

データ検索

  • missing
    データに存在しない値を絞り込む
jsonLogic.apply(
    { "missing" : [ "a",  "b" ] },
    { "a" : "apple", "c" : "carrot" }
);
// [ "b" ]

bool判定

  • > >= < <=
  • Between
  • max
  • min
  • + - * /
  • %

演算子

  • if
  • ==
  • !=
  • !==
  • !
  • !!
  • or
  • and

配列操作

  • map ex ) 指定した配列を2の倍数にして取得する
jsonLogic.apply(
    { "map" : [
      { "var" : "integers" },
      { "*" :[{ "var" : "" }, 2 ] } 
    ]},
    { "integers" : [ 1, 2, 3, 4, 5 ] }
);
// [ 2, 4, 6, 8, 10 ]
  • reduce
  • filter
  • some
  • etc...