Eu tenho dois tipos de "elementos". Um que gera séries temporais (vamos chamá-los de elemento gerador ) e outro que com base em algumas regras lógicas aplicadas às séries temporais se torna "ativado" ( elementos ativáveis ).
Esta simplificação representa a série temporal
CREATE TABLE data.time_series
(
generator_element_id uuid NOT NULL,
epoch bigint NOT NULL, -- UNIX epoch
level integer NOT NULL, -- values from 0 to 3
-- other fields
-- PRIMARY KEY (generator_element_id, epoch),
-- FOREIG KEY TO the table with the generator_elements
)
A ideia é que os elementos ativáveis sejam ativados seguindo regras como
Lenda:
- Elemento gerador GE
- Elemento ativável AE
IF (GE1 has level > 1 AND GE2 has level > 1) OR (GE3 has level > 2) for a given instant T1 THEN AE1 becames activated
Estou tentando encontrar a melhor maneira de representar essas regras lógicas no banco de dados, pois elas serão configuradas pelo usuário e podem incluir várias combinações de regras "AND" e "OR"
O problema é justamente com essa combinação de uso de AND's e OR's, como se fosse apenas um tipo desses eu poderia criar outra tabela com a relação entre os diferentes tipos de elementos, e os limites. Mas usando uma combinação de ANDs e ORs estou perdido ..
Meu primeiro pensamento foi armazenar essas relações usando uma string simples, semelhante ao que descrevi antes, mas usando os UUIDs correspondentes para os elementos geradores, e então ter um serviço que processará essas regras e decidirá ativar ou não os elementos.
Estou procurando alternativas para essa abordagem, pois não acho que minha abordagem possa escalar bem o suficiente, nem gosto disso pessoalmente ...
Para contexto, estou usando o PostgreSQL 12.0 com docker
Editar:
Esclarecendo sobre as épocas, pois não estava claro. O valor da época não está incluído na "definição" da regra lógica, que inclui apenas os elementos e seus níveis (na verdade inclui outros ids, mas para simplificar apenas essas duas variáveis).
Quanto ao cálculo real, os registros serão recuperados e separados em "bins" para cada época. Desta forma aplicamos a regra sobre os registros para aquela época (assumindo que sempre haverá registros para todos os elementos geradores para a época dada)
Também adicionando alguns dados de teste como exemplo. Neste caso, usarei um valor de época 1581638400 que corresponde a 2020-02-14 00:00:00Z
INSERT INTO data.time_series
VALUES (
'00000000-0000-0000-0000-000000000001', -- uuid for GE1
1, --level
1581638400 -- epoch for 2020-02-14 00:00:00Z
)
INSERT INTO data.time_series
VALUES (
'00000000-0000-0000-0000-000000000002', -- uuid GE2
2, --level
1581638400 -- epoch for 2020-02-14 00:00:00Z
)
INSERT INTO data.time_series
VALUES (
'00000000-0000-0000-0000-000000000003', -- uuid GE3
0, --level
1581638400 -- epoch for 2020-02-14 00:00:00Z
)
Aqui a regra especificada como minha proposta seria para o elemento ativável AE1:
-- Omiting the 0s for simplicity
"('000...01' > 1 AND '000...02' > 1) OR ('000...03' > 2)"
Com os dados fictícios, o resultado será que AE1 é ativado assim que a primeira parte da regra for concluída
Mas com a forma que a regra está salva na minha proposta, terei que fazer um sistema de processamento específico para isso...
Qualquer ajuda é apreciada