Agrupar dados adjacentes pode ser um desafio em bancos de dados NoSQL como o MongoDB, especialmente quando se busca uma solução eficiente e direta. A flexibilidade do MongoDB, no entanto, permite que você explore alternativas para alcançar o resultado desejado, mesmo que isso envolva abordagens um pouco mais elaboradas do que as tradicionais. Vamos mostrar como lidar com essa tarefa de forma eficaz!
Agregação no MongoDB: Desafios e Soluções
No MongoDB, a agregação no MongoDB de estados adjacentes diretamente com consultas pode ser complexa, já que a linguagem de consulta nativa não oferece suporte direto a essa lógica de agrupamento. Para contornar essa limitação, é possível combinar o Aggregation Pipeline com alguma lógica customizada. Essa combinação permite implementar indiretamente a função de agrupar os estados vizinhos.
Imagine que você tem uma coleção de dados (chamada “estados”) em seu banco de dados MongoDB, organizada da seguinte forma:
[
{order: 1, state: 'one'},
{order: 2, state: 'one'},
{order: 3, state: 'one'},
{order: 4, state: 'two'},
{order: 5, state: 'two'},
{order: 6, state: 'one'},
{order: 7, state: 'two'},
{order: 8, state: 'three'},
{order: 9, state: 'three'}
]
O objetivo é agrupar esses estados de forma adjacente, de modo que o resultado final seja:
[
[
{order: 1, state: 'one'},
{order: 2, state: 'one'},
{order: 3, state: 'one'}
],
[
{order: 4, state: 'two'},
{order: 5, state: 'two'}
],
[
{order: 6, state: 'one'}
],
[
{order: 7, state: 'two'}
],
[
{order: 8, state: 'three'},
{order: 9, state: 'three'}
]
]
Implementando a Agregação com Aggregation Pipeline
Para realizar essa tarefa, o Aggregation Pipeline oferece uma estrutura poderosa. Veja como você pode escrever o código para alcançar o resultado desejado:
db.states.aggregate([
{
$sort: { order: 1 }
},
{
$group: {
_id: null,
documents: { $push: "$$ROOT" }
}
},
{
$project: {
grouped: {
$reduce: {
input: "$documents",
initialValue: {
previousState: null,
groups: []
},
in: {
$let: {
vars: {
currentState: "$$this.state",
lastGroup: { $arrayElemAt: ["$$value.groups", -1] }
},
in: {
$cond: [
{ $eq: ["$$value.previousState", "$$this.state"] },
{
previousState: "$$this.state",
groups: {
$concatArrays: [
{ $slice: ["$$value.groups", { $subtract: [{ $size: "$$value.groups" }, 1] }] },
[
{
$concatArrays: [
"$$lastGroup",
["$$this"]
]
}
]
]
}
},
{
previousState: "$$this.state",
groups: {
$concatArrays: [
"$$value.groups",
[["$$this"]]
]
}
}
]
}
}
}
}
}
}
},
{
$project: {
_id: 0,
grouped: "$grouped.groups"
}
},
{
$unwind: "$grouped"
},
{
$project: {
_id: 0,
documents: "$grouped"
}
},
{
$group: {
_id: null,
result: { $push: "$documents" }
}
},
{
$project: {
_id: 0,
result: 1
}
}
])
Este código utiliza várias etapas do Aggregation Pipeline para ordenar os documentos, agrupar todos os documentos em um único array, e, em seguida, usar a função $reduce para iterar sobre os documentos e criar os grupos adjacentes com base no valor do estado. O resultado final é um array de arrays, onde cada sub-array contém os documentos agrupados por estados adjacentes.
Resultado da Execução
Ao executar o código acima, você obterá o seguinte resultado:
{
result: [
[
{
_id: ObjectId('67c65e846d497a00cd02a427'),
order: 1,
state: 'one'
},
{
_id: ObjectId('67c65e846d497a00cd02a428'),
order: 2,
state: 'one'
},
{
_id: ObjectId('67c65e846d497a00cd02a429'),
order: 3,
state: 'one'
}
],
[
{
_id: ObjectId('67c65e846d497a00cd02a42a'),
order: 4,
state: 'two'
},
{
_id: ObjectId('67c65e846d497a00cd02a42b'),
order: 5,
state: 'two'
}
],
[
{
_id: ObjectId('67c65e846d497a00cd02a42c'),
order: 6,
state: 'one'
}
],
[
{
_id: ObjectId('67c65e846d497a00cd02a42d'),
order: 7,
state: 'two'
}
],
[
{
_id: ObjectId('67c65e846d497a00cd02a42e'),
order: 8,
state: 'three'
},
{
_id: ObjectId('67c65e846d497a00cd02a42f'),
order: 9,
state: 'three'
}
]
]
}
Este resultado mostra os documentos agrupados conforme o estado adjacente, atendendo ao requisito inicial.
Alternativa com SPL (Statistical Programming Language)
Uma alternativa para realizar essa tarefa é utilizar o SPL (Statistical Programming Language), que oferece uma função específica para agrupar registros adjacentes. O código em SPL é mais conciso e claro:
As três primeiras linhas são responsáveis pela leitura dos dados, e o cálculo é feito em uma única linha (A4). A linha A5 retorna os resultados em formato JSON, que são idênticos aos requisitos originais.
Em resumo, embora o MongoDB não ofereça uma solução direta para agrupar estados adjacentes com suas ferramentas nativas, é possível alcançar o resultado desejado combinando o Aggregation Pipeline com lógica customizada. Além disso, ferramentas como o SPL oferecem alternativas mais concisas e claras para essa tarefa.
Este conteúdo foi auxiliado por Inteligência Artificiado, mas escrito e revisado por um humano.