MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Usando um valor dinâmico na agregação


A pergunta geral aqui é incluir o intervalo para o "month" valores em consideração onde é "maior que" o -5 meses "antes" e "menor que" o +2 meses "depois" conforme registrado no "enrolled" entradas de matriz.

O problema é que, como esses valores são baseados em "dateJoined" , eles precisam ser ajustados pelo intervalo correto entre o "dateJoined" e o "dateActivated" . Isso torna a expressão efetivamente:
monthsDiff = (yearActivated - yearJoined)*12 + (monthActivated - monthJoined)

where month >= ( startRange + monthsDiff ) and month <= ( endRange + monthsDiff )
and enrolled = "01"

Ou expresso logicamente "Os meses entre o intervalo expresso ajustado pelo número de meses de diferença entre a adesão e a ativação" .

Conforme declarado no comentário, a primeira coisa que você precisa fazer aqui é armazenar esses valores de data como uma BSON Date em oposição aos seus valores aparentes de "string" atuais. Feito isso, você pode aplicar a seguinte agregação para calcular a diferença das datas fornecidas e filtrar o intervalo ajustado de acordo com a matriz antes de contar:
var rangeStart = -5,
    rangeEnd = 2;

db.getCollection('enrollments').aggregate([
  { "$project": {
    "enrollments": {
      "$size": {
        "$filter": {
          "input": "$enrolled",
          "as": "e",
          "cond": {
            "$let": {
              "vars": {
                "monthsDiff": {
                  "$add": [
                    { "$multiply": [
                      { "$subtract": [
                        { "$year": "$dateActivated" },
                        { "$year": "$dateJoined" }
                      ]},
                      12
                    }},
                    { "$subtract": [
                      { "$month": "$dateActivated" },
                      { "$month": "$dateJoined" }
                    ]}
                  ]
                }
              },
              "in": {
                "$and": [
                  { "$gte": [ { "$add": [ rangeStart, "$$monthsDiff" ] }, "$$e.month" ] },
                  { "$lte": [ { "$add": [ rangeEnd, "$$monthsDiff" ] }, "$$e.month" ] },
                  { "$eq": [ "$$e.enrolled", "01" ] }
                ]
              }
            }
          } 
        }
      }
    }
  }}
])

Portanto, isso se aplica ao mesmo $filter para a matriz que você estava tentando, mas agora leva em consideração os valores ajustados no intervalo de meses para filtrar também.

Para facilitar a leitura, aplicamos $let que permite o cálculo do valor comum obtido para $$monthsDiff como implementado em uma variável. Aqui é onde a expressão explicada originalmente é aplicada, usando $year e $month para extrair esses valores numéricos das datas armazenadas.

Usando os operadores matemáticos adicionais $add , $subtract e $multiply você pode calcular a diferença em meses e também aplicar posteriormente para ajustar os valores de "intervalo" nas condições lógicas com $gte e $lte .

Finalmente, porque $filter emite uma matriz apenas das entradas que correspondem às condições, para "contar" aplicamos $size que retorna o comprimento da matriz "filtrada", que é a "contagem" de correspondências.

Dependendo do objetivo pretendido, a expressão inteira também pode ser fornecida como argumento para $sum como um $group acumulador, se então era de fato a intenção.