Механизм правил – это логика или условие, например: "Когда некоторые условия оцениваются как истинные, выполните некоторую задачу". Механизм правил можно рассматривать как сложный интерпретатор операторов if/then
Rule Engine состоит из трех компонентов
- Правила
- Факт/ы
- Оценщик
Определение условия правила
Мы будем использовать просеивание для определения правил, он предоставляет синтаксис типа запроса mongodb для определения правила и простой API для проверки по текущим объектам.
Чтобы определить правило, вы можете использовать операторы запросов mongodb, такие как $in
→ Для проверки заданного значения в диапазоне$lte
→ Для проверки заданного значения меньше определенного значения
Давайте определим правило просеивания
Правило — Пользователь принадлежит к городу "Дели" и имеет возраст от 20 до 30 лет.
import sift from 'sift'; const youngUsersWithCityDelhi = sift({ age: {$gt: 20, $lt: 30}, city: 'Delhi' }); const oldUsersWithCityDelhi = sift({ age: {$gt: 50}, city: 'Delhi' });
Здесь вы создали два правила, вы можете хранить эти правила в памяти или хранить их в БД, поскольку их можно преобразовать в строку.
Определите факты
С просеиванием вместо тестового объекта, являющегося действующими лицами, а затем правилом тестирования, здесь правило становится действующим лицом, и правило может быть проверено на разных фактах.
Теперь, определяя факты, мы должны знать о схеме правила, так как в нашем примере правила у нас были ключи правил, такие как возраст и город, поэтому мы должны быть согласованы с ключами при определении фактов.
const Person1 = { age: 10, city: 'Delhi' } const Person2 = { age: 25, city: 'Delhi' }
Может быть случай, когда ваши факты имеют другую схему, в этом случае вам нужно преобразовать и создать временные факты, придерживаясь схемы правил.
Как правило, будет один факт для каждого запроса или варианта использования, но все может измениться в соответствии с требованиями.
Определить репозиторий правил
Repostiroy отвечает за фильтрацию/выбор подходящих правил для определенного сценария, а затем проверяет подходящие правила, какие из них применяются, а затем принимает соответствующие
Оценщик правил
С созданными фильтрами правила оценки довольно просты. В приведенном выше примере мы создали два правила и два контрольных факта. Вот как мы можем проверить, применимо ли правило к факту или нет.
import sift from 'sift'; const youngUsersWithCityDelhi = sift({ age: {$gt: 20, $lt: 30}, city: 'Delhi' }); const oldUsersWithCityDelhi = sift({ age: {$gt: 50}, city: 'Delhi' }); const Person1 = { age: 10, city: 'Delhi' } const Person2 = { age: 25, city: 'Delhi' } console.log(youngUsersWithCityDelhi(Person1)) // false console.log(youngUsersWithCityDelhi(Person2)) // true
Множитель перенапряжения
Постановка задачи
Учитывая список правил всплеска с условием и множителем, рассчитайте множитель всплеска для данного сценария.
Правило
Создадим класс для правила, у которого будет свое условие и множитель
export default class Rule { constructor(name, condition) { this.name = name; this.condition = condition; } } export class SurgeRule extends Rule { constructor(name, condition, surgeMultiplier) { super(name, condition); this.surgeMultiplier = surgeMultiplier; } }
Факт/ы
Определите факт, убедитесь, что схема факта совпадает со схемой правила. Факт может быть создан с использованием комбинации нескольких атрибутов объектов, таких как параметры запроса пользователя и другие объекты.
const fact1 = { rain: true, isPremiumUser: false, orderAmount: 400 } const fact2 = { rain: false, isPremiumUser: true, orderAmount: 600 }
Репозиторий
Репозиторий — это место, где будут храниться все правила и связанные с ними метаданные. Он будет использоваться для фильтрации неактивных правил или любой необходимой пользовательской фильтрации.
export class RuleRepository { constructor(rules) { this.rules = rules; } getRules() { return this.rules; } getRulesForRain() { return this.rules.filer(rule => rule.rain == true); } }
основной
import sift from 'sift'; import { SurgeRule } from './rule.js'; import { RuleRepository } from './rule-repository.js'; import { SurgeService } from './surge-service.js'; const lowSurgeMultiplierRule = new SurgeRule('low-surge', {rain: false, isPremiumUser: true, orderAmount: {$gt: 500}}, 1.1); const mediumSurgeMultiplierRule = new SurgeRule('mid-surge', {rain: false, isPremiumUser: false, orderAmount: {$gt: 500}}, 1.5); const highSurgeMultiplierRule = new SurgeRule('high-surge', {rain: true, isPremiumUser: true, orderAmount: {$gt: 500}}, 2); const defaultSurgeMultiplierRule = new SurgeRule('high-surge', {}, 1.3); const rules = [lowSurgeMultiplierRule, mediumSurgeMultiplierRule, highSurgeMultiplierRule, defaultSurgeMultiplierRule]; const ruleRepository = new RuleRepository(rules) const surgeService = new SurgeService(ruleRepository, sift) const fact1 = { rain: true, isPremiumUser: false, orderAmount: 400 } const fact2 = { rain: false, isPremiumUser: true, orderAmount: 600 } console.log(surgeService.getSurgeMultiplier(fact1)) // 1.3 as it matched with last rule console.log(surgeService.getSurgeMultiplier(fact2)) // 1.1
Пример кода можно найти по адресу — https://replit.com/@09saurabh09/RuleEngineSift
Хороший, плохой и уродливый
Хороший
- Определение правила легко, поддерживает несколько операторов
- Проверка правила делегирована просеиванию
- Может храниться в любой БД
- Может работать с моделью с несколькими матчами, гибкой для использования так, как вы хотите
Плохой
- Необходимо преобразовать/сериализовать перед сохранением правил
- Невозможно фильтровать правила на основе условия правила
- Необходимо написать дополнительный код для составления правил
- Зависит от языка
Уродливый
- Необходимо перебрать все правила, чтобы найти возможное совпадение
Спасибо
Спасибо, что прочитали эту статью! Если вы хотите углубиться и быть в курсе моих последних идей и статей, обязательно подпишитесь на меня на Medium и не стесняйтесь связаться со мной в LinkedIn.