Should I use Drools in this situation?

后端 未结 5 1716
难免孤独
难免孤独 2021-02-08 19:11

I\'ll use a university\'s library system to explain my use case. Students register in the library system and provide their profile: gender, age, department, previously completed

5条回答
  •  一生所求
    2021-02-08 20:00

    First, Don't make rules for every book. Make rules on the restrictions—there are a lot fewer restrictions defined than books. This will make a huge impact on the running time and memory usage.

    Running a ton of books through the rule engine is going to be expensive. Especially since you won't show all the results to the user: only 10-50 per page. One idea that comes to mind is to use the rule engine to build a set of query criteria. (I wouldn't actually do this—see below.)

    Here's what I have in mind:

    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
    

    But I wouldn't actually do that!

    This is how I would have changed the problem: Not showing the books to the user is a poor experience. A user may want to peruse the books to see which books to get next time. Show the books, but disallow the checkout of restricted books. This way, you only have 1-50 books to run through the rules at a time per user. This will be pretty zippy. The above rules would become:

    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
    

    Where I am using activation-group to make sure only one rule is fired, and salience to make sure they are fired in the order I want them to be.

    Finally, keep the rules cached. Drools allows—and suggests that—you load the rules only once into a knowledge base and then create sessions from that. Knowledge bases are expensive, sessions are cheap.

提交回复
热议问题