Reimplementacja agregacji

Trzeba też przemyśleć sprawę tego, w jaki dokładnie sposób będziemy łączyć dwie listy kroków agregacji spójnikami and lub or.

O ile w przypadku and możemy po prostu skleić dwie tablice i dowolnie mieszać kroki $match i $lookup, o tyle w przypadku or nie jest już tak fajnie, gdyż nie możemy korzystać z faktu, że gdy jedna z łączonych orem strategii dostępu odrzuci zasób, nie musimy już go sprawdzać drugą z łączonych strategii dostępu.

I tutaj ponownie przydaje nam się trochę wiedzy z uczelni :wink: Istnieje sposób na rozbicie dużej alternatywy (OR) na kilka mniejszych klauzul, które można połączyć spójnikiem AND, przy 100% zachowaniu ich wartości logicznej. Możemy skorzystać z Koniunkcyjnej Postaci Normalnej:

Dzięki temu zmieniamy alternatywę (gdzie głównym operatorem jest OR) na koniunkcję (gdzie głównym operatorem jest AND) i możemy wtedy dowolnie zmieniać kolejność kolejnych kroków agregacji. Przykładowo: z wyrażenia, które jest jednym wielkim krokiem agregacji:

or(and(a,b), and(c,d))

możemy zrobić tożsame wyrażenie w postaci koniunkcyjnej:

and(or(and(a,b), c), or(and(a,b), d))

O ile taki zapis jest trochę redundantny (jest trochę powtórzeń), to głównym operatorem jest już and - dzięki temu możemy doklejać śmiało inne klauzule, zmieniać ich kolejność i dalej optymalizować zapytanie.

O ile tego typu optymalizacja jest jak najbardziej w naszym zasięgu, o tyle z uwagi na czas póki co dla strategii dostępu or zrobiłbym następujący algorytm:

  1. wszystkie lookupy na początek agregacji;
  2. wszystkie matche sklejone $or-em tuż po nich.