まず、すべての本にルールを作らないでください。制限に関するルールを作成します。本よりもはるかに少ない制限が定義されています。これは、実行時間とメモリ使用量に大きな影響を与えます。
大量の本をルール エンジンで実行すると、コストがかかります。特に、すべての結果をユーザーに表示するわけではないため、1 ページあたり 10 ~ 50 のみです。頭に浮かぶアイデアの 1 つは、ルール エンジンを使用して一連のクエリ条件を作成することです。(私は実際にはこれを行いません。以下を参照してください。)
これが私が考えていることです:
rule "Only two books for networking"
when
Student($checkedOutBooks : checkedOutBooks),
Book(subjects contains "networking", $book1 : id) from $checkedOutBooks,
Book(subjects contains "networking", id != $book1) from $checkedOutBooks
then
criteria.add("subject is not 'networking'", PRIORITY.LOW);
end
rule "Books allowed for course"
when
$course : Course($textbooks : textbooks),
Student(enrolledCourses contains $course)
Book($book : id) from $textbooks,
then
criteria.add("book_id = " + $book, PRIORITY.HIGH);
end
しかし、私は実際にはそれをしません!
これは、私が問題をどのように変更したかです: ユーザーに書籍を表示しないことは、悪い経験です. ユーザーは、次にどの本を入手するかを知るために本を熟読したいと思うかもしれません。書籍を表示しますが、制限された書籍のチェックアウトは許可しません。この方法では、ユーザーごとに一度に 1 ~ 50 本のルールを実行するだけです。これはかなり楽になります。上記のルールは次のようになります。
rule "Allowed for course"
activation-group "Only one rule is fired"
salience 10000
when
// This book is about to be displayed on the page, hence inserted into working memory
$book : Book(),
$course : Course(textbooks contains $book),
Student(enrolledCourses contains $course),
then
//Do nothing, allow the book
end
rule "Only two books for networking"
activation-group "Only one rule is fired"
salience 100
when
Student($checkedOutBooks : checkedOutBooks),
Book(subjects contains "networking", $book1 : id) from $checkedOutBooks,
Book(subjects contains "networking", id != $book1) from $checkedOutBooks,
// This book is about to be displayed on the page, hence inserted into working memory.
$book : Book(subjects contains "networking")
then
disallowedForCheckout.put($book, "Cannot have more than two networking books");
end
アクティベーション グループを使用して 1 つのルールのみが実行されるようにし、salience を使用して希望する順序で実行されるようにします。
最後に、ルールをキャッシュしたままにします。Drools では、ルールを 1 回だけナレッジ ベースにロードし、そこからセッションを作成することができます (また、そのように提案されています)。ナレッジ ベースは高価ですが、セッションは安価です。