🧩

Active RecordでのNAND条件、NOR条件の書き方

2024/02/28に公開

こんにちは!ラブグラフの開発チームでインターンシップをしているけいすけと申します。
先日、Active RecordでNAND条件、NOR条件を書く機会があったのでまとめておきます。

NAND条件

NANDとはNOT ANDの略で、ANDの否定をとったものです。日本語では否定論理積といいます。
Aという条件とBという条件があるとき、
A AND Bは、AとBがどちらもtrueのときにtrue、それ以外の場合はfalseになりますが、
A NAND Bは、AとBがどちらもtrueのときにfalse、それ以外の場合はtrueになります。

https://ja.wikipedia.org/wiki/否定論理積

真理値表

真理値表は次のようになります。

A B A AND B A NAND B
false false false true
false true false true
true false false true
true true true false

ベン図

左の円に囲まれた部分をA、右の円に囲まれた部分をBとすると、
下の図の赤い部分がA NAND Bを表します。AとBが逆でも同じです。

Active Recordでの書き方

Model.where.not(A, B)

マッチングアプリのようなサービスを扱っていて、その中から特定の条件を満たすユーザーを取得するクエリを書く例を考えてみます。

このサービスのユーザーの名前(name)、職業(occupation)、趣味(hobby)を持つ次のようなusersテーブルがあるとします。

usersテーブル

name occupation hobby
一郎 engineer workout
二郎 engineer cooking
三郎 designer workout
四郎 designer cooking

このテーブルから

「職業がエンジニア」かつ「趣味が筋トレ」のユーザー以外

を取得するクエリはNAND条件の書き方を使って次のように書けます。

User.where.not(occupation: "engineer", hobby: "workout")

このクエリで取得できるのは次の3人です。

name occupation hobby
二郎 engineer cooking
三郎 designer workout
四郎 designer cooking

一郎は「職業がエンジニア」かつ「趣味が筋トレ」のユーザーなので、このクエリの取得結果には含まれません。

NOR条件

NORとはNOT ORの略で、ORの否定をとったものです。日本語では否定論理和といいます。
Aという条件とBという条件があるとき、
A OR Bは、AとBのどちらかがtrueのときにtrue、それ以外の場合はfalseになりますが、
A NOR Bは、AとBのどちらかがtrueのときにfalse、それ以外の場合はtrueになります。

https://ja.wikipedia.org/wiki/否定論理和

真理値表

真理値表は次のようになります。

A B A OR B A NOR B
false false false true
false true true false
true false true false
true true true false

ベン図

左の円に囲まれた部分をA、右の円に囲まれた部分をBとすると、
下の図の赤い部分がA NOR Bを表します。AとBが逆でも同じです。

Active Recordでの書き方

Model.where.not("A OR B")

または

Model.where.not(A).where.not(B)

.where.not(A).where.not(B) は、「Aでない」かつ「Bでない」を表します。

https://manabitimes.jp/math/897

NANDの場合と同じ例で考えます。

usersテーブル

name occupation hobby
一郎 engineer workout
二郎 engineer cooking
三郎 designer workout
四郎 designer cooking

このテーブルから

「職業がエンジニア」または「趣味が筋トレ」のユーザー以外

を取得するクエリはNOR条件の書き方を使って次のように書けます。

User.where.not("occupation = :occupation OR hobby = :hobby", occupation: "engineer", hobby: "workout")

または

User.where.not(occupation: "engineer").where.not(hobby: "workout")

このクエリで取得できるのは次の1人です。

name occupation hobby
四郎 designer cooking

一郎、二郎、三郎は「職業がエンジニア」または「趣味が筋トレ」のユーザーなので、このクエリの取得結果には含まれません。

以上、Active RecordでのNAND条件とNOR条件の書き方でした!
読んでいただきありがとうございました!

ラブグラフのエンジニアブログ

Discussion