首先,不要为每本书制定规则。对限制制定规则——定义的限制比书本少得多。这将对运行时间和内存使用产生巨大影响。
通过规则引擎运行大量书籍的成本将会很高。特别是因为您不会向用户显示所有结果:每页仅显示 10-50 个结果。我想到的一个想法是使用规则引擎来构建一组查询条件。 (我实际上不会这样做——见下文。)
这就是我的想法:
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
我使用激活组来确保只触发一条规则,并使用显着性来确保它们按照我希望的顺序触发。
最后,保留规则缓存。 Drools 允许并建议您将规则仅加载到知识库中一次,然后从中创建会话。知识库很昂贵,课程很便宜。