O que você quer é o $cond operador e algumas condições aninhadas com $and . Mas isso deve lhe dar exatamente o que você quer.
db.collection.aggregate([
{"$group": {
"_id": {"$cond": [
{"$gte": ["$LoadTime", 2000] },
"Slowest", // return "Slowest" where true
{"$cond": [
{"$and": [
{"$lt": ["$LoadTime", 2000] },
{"$gte": ["$LoadTime", 1000] }
]},
"Slow", // then "Slow" here where true
{"$cond": [
{"$and": [
{"$lt": ["$LoadTime", 1000] },
{"$gte": ["$LoadTime", 500 ] }
]},
"Medium", // then "Medium" where true
"Fast" // and finally "Fast" < 500
]}
]}
]},
"count": {"$sum": 1}
}},
{"$sort": { "count": 1 }}
])
Como seu tempo é inteiro milissegundos você pode ver porque eu pedi a edição.
Assim como $cond é um ternário operador, leva três argumentos sendo:
- Uma condição para avaliar que retorna um booleano
- Um valor de retorno em que a condição é true
- Um valor de retorno em que a condição é falsa
Portanto, a ideia é aninhar todas as condições, passando para o próximo teste em falso até encontrar uma condição para corresponder e um valor para retornar.
O $ e parte é uma matriz de condições incluir. Isso fornece os intervalos . Então, nas partes mais longas:
{"$cond": [ // Evaluate here
{"$and": [ // Within the range of the next 2
{"$lt": ["$LoadTime", 2000] },
{"$gte": ["$LoadTime", 1000] }
]},
"Slow", // true condition - return
{"$cond": [ // false - move to next eval
Em cascata, você fica com "Rápido" por
times
menos de 500 milissegundos. Cada uma dessas
keys
é emitido para o grupo e nós apenas { $sum: 1 }
para obter uma contagem à medida que são agrupados. Se você precisar disso em sua própria implementação de linguagem, todo o
pipeline
conteúdo dentro é apenas JSON, então você pode analisá-lo em sua estrutura de dados nativa se a tradução manual lhe escapar ou se, como eu, você for apenas preguiçoso.
EDITAR
Devido aos comentários parece necessário explicar a forma da consulta apresentada. Então aqui o adendo de edição para esclarecimento.
Quando aprender uso do pipeline de agregação e, de fato, boas práticas para escrever e testar uma série complexa de estágios ou lógica, acho útil visualizar os resultados implementando partes um passo de cada vez . Então, no caso de escrever algo assim, meu primeiro passo seria o seguinte:
db.collection.aggregate([
{"$group": {
"_id": {"$cond": [
{"$gte": ["$LoadTime", 2000] },
"Slowest",
null
]}
}}
])
Agora, isso me daria a contagem de "Mais lento" como eu esperaria e, em seguida, bucket todo o resto em
null
. Portanto, há uma fase em que vejo os resultados até agora. Mas ao testar Na verdade, eu faria algo assim antes de prosseguir para construir uma cadeia:db.collection.aggregate([
{"$group": {
"_id": {"$cond": [
{"$and": [
{"$lt": ["$LoadTime", 2000] },
{"$gte": ["$LoadTime", 1000] }
]},
"Slow",
null
]}
}}
])
Então, estou apenas obtendo os resultados para "Lento" (entre 2000 e 1000) com todo o resto no
null
balde. Portanto, minha contagem geral permanece a mesma. Na final consulta, como foi apontado, em um ternário condição aninhada como esta, a primeira palco já avaliou
false
para os itens que estão sendo testados pelo próximo operador. Isso significa que eles não maior que o valor que já foi testado no primeiro estágio, e isso evita a necessidade de testar essa condição para que isso poderia ser escrito da seguinte forma:db.collection.aggregate([
{"$group": {
"_id": {"$cond": [
{"$gte": ["$LoadTime", 2000] }, // Caught everything over 2000
"Slowest",
{"$cond": [
{"$gte": ["$LoadTime", 1000] } // Catch things still over 1000
"Slow",
{"$cond": [ // Things under 1000 go here
// and so on
E que curtos-circuitos a avaliação, pois não há real precisa testar coisas que não vão passar para a próxima condição lógica.
Então puramente por razões visuais e por pura preguiça de cortar e colar lógica, acabamos com o formulário expandido usando o $ e condição para envolver o intervalo. Mas para aqueles não acostumados o uso do ternário forma há uma indicação visual clara que os resultados correspondentes nesta fase ficarão entre os valores de
2000ms
e 1000ms
, e assim por diante, que é o que você deseja como resultado em cada intervalo. Como eu disse, desnecessário ter por causa de como a lógica funciona, mas foi uma fase de desenvolvimento e é claro para as pessoas que ainda não compreenderam uso do ternário formulário que $cond fornece.