Хранение условий запроса в БД - PullRequest
0 голосов
/ 27 апреля 2020

У меня есть две сущности: Activity и Rule.

«Activity» имеет несколько постоянных полей (user_id, type, date и т. Д. c). И некоторые динамические c поля (полезная нагрузка), которые зависят от типа деятельности. Например, действие, сохраненное, когда пользователь заказывает что-либо:

{
    user_id: 1,
    date: 2020-01-01,
    type: "user_ordered",
    payload: {
        total: 100,
        items: 2
    }
}

Вторым объектом является правило, которое в основном определяет, какие действия следует отслеживать. Например, может существовать правило «заказы с элементами = 2» или «заказы с общим числом> 10 и датой> 2020-01-01».

Проблема в том, что я не могу решить, как хранить и запросить такие случаи. Можно сохранить полезную нагрузку действия как json, но как сохранить эти условия, такие как «total> 10» или «items = 2», и использовать их для выбора действий? Может быть, мне стоит больше не смотреть на sql дБ?

Буду признателен за любую помощь в этом.

1 Ответ

0 голосов
/ 27 апреля 2020

Вы можете представить все необходимые условия с минимальными / максимальными значениями. Например, total > 10 может быть выражено как min_value = 11, max_value = null.

Реалистичные таблицы будут включать таблицы ключ / значение для деталей, которые различны для каждого типа.

Таблица активности

+ ------------+--------------+---------+------------+
| activity_id | type         | user_id | date       |
+ ------------+--------------+---------+------------+
|           1 | user_ordered |       1 | 2020-01-01 |
+ ------------+--------------+---------+------------+

Таблица activity_detail

+ ------------+-------+-------+
| activity_id | key   | value |
+ ------------+-------+-------+
|           1 | total |   100 |
|           1 | items |     2 |
+ ------------+-------+-------+

Таблица правил

+ --------+--------------+----------+------------+------------+
| rule_id | type         | user_id  | min_date   | max_date   |
+ --------+--------------+----------+------------+------------+
|       1 | user_ordered |          | 2020-01-01 | 2020-01-15 |
+ --------+--------------+----------+------------+------------+

Таблица rule_detail

+ --------+-------+-----------+-----------+
| rule_id | key   | min_value | max_value |
+ --------+-------+-----------+-----------+
|       1 | total |        11 |           |
|       1 | items |         2 |         2 |
+ --------+-------+-----------+-----------+

Запрос

select a.*
from rule r
join activity a on a.type = r.type
               and (a.user_id >= r.min_user_id or r.min_user_id is null)
               and (a.date >= r.min_date or r.min_date is null)
               and (a.date <= r.max_date or r.max_date is null)
where r.rule_id = 1
and not exists
(
  select
  from rule_detail rd
  join activity_detail ad on ad.key = rd.key
  where rd.rule_id = r.rule_id
  and ad.activity_id = a.activity_id
  and not
  (
    (ad.value >= rd.min_value or rd.min_value is null)
    and
    (ad.value <= rd.max_value or rd.max_value is null)
  )
);

Альтернатива будет быть плоскими столами, где вы освобождаете место для всех возможных атрибутов:

Таблица активности

+ ------------+--------------+---------+------------+------------+------------+------------+------------+
| activity_id | type         | user_id | date       | total      | items      | name       | location   |
+ ------------+--------------+---------+------------+------------+------------+------------+------------+
|           1 | user_ordered |       1 | 2020-01-01 |        100 |          2 |            |            |
+ ------------+--------------+---------+------------+------------+------------+------------+------------+

Правило таблицы

+ --------+--------------+----------+------------+------------+------------+------------+------------+------------+------------+------------+--------------+--------------+
| rule_id | type         | user_id  | min_date   | max_date   | min_total  | max_total  | min_items  | max_items  | min_name   | max_name   | min_location | max_location |
+ --------+--------------+----------+------------+------------+------------+------------+------------+------------+------------+------------+--------------+--------------+
|       1 | user_ordered |          | 2020-01-01 | 2020-01-15 |         11 |            |          2 |          2 |            |            |              |              |
+ --------+--------------+----------+------------+------------+------------+------------+------------+------------+------------+------------+--------------+--------------+

Запрос

select a.*
from rule r
join activity a on a.type = r.type
               and (a.user_id >= r.min_user_id or r.min_user_id is null)
               and (a.date >= r.min_date or r.min_date is null)
               and (a.date <= r.max_date or r.max_date is null)
               and (a.total >= r.min_total or r.min_total is null)
               and (a.total <= r.max_total or r.max_total is null)
               and (a.items >= r.min_items or r.min_items is null)
               and (a.items <= r.max_items or r.max_items is null)
               and (a.name >= r.min_name or r.min_name is null)
               and (a.name <= r.max_name or r.max_name is null)
               and (a.location >= r.min_location or r.min_location is null)
               and (a.location <= r.max_location or r.max_location is null)
where r.rule_id = 1;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...