Da Recuperação a Resultados Estruturados: Agregação e ORDER BY no Milvus 3.0
Considere um fluxo familiar de busca de produtos. Um comprador envia uma foto de um vestido, e a busca vetorial recupera um conjunto relevante de candidatos de um catálogo com dezenas de milhões de produtos.
A página, no entanto, precisa de mais do que uma lista ranqueada. Ela precisa de facetas de marca. Precisa de uma ordenação por preço. A equipe de merchandising quer saber quais marcas dominam esse conjunto de resultados, a faixa de preço dentro de cada marca e alguns produtos representativos de cada grupo.
Antes do Milvus 3.0, as aplicações geralmente lidavam com essa segunda etapa por conta própria: buscavam linhas no Milvus, agrupavam e ordenavam em pandas ou em uma camada de serviço, e então montavam a resposta. Algumas equipes mantinham um pipeline analítico separado apenas para calcular contagens e distribuições sobre dados que já estavam no banco de dados vetorial.
O banco de dados vetorial encontrava os candidatos; a aplicação precisava transformá-los em um resultado estruturado.
O Milvus 3.0 move mais desse trabalho para dentro do mecanismo de recuperação. Ele adiciona três capacidades relacionadas, mas distintas:
- Agregação de consultas calcula
count,sum,avg,minemaxsobre linhas filtradas e visíveis, com campos opcionais deGROUP BY. - Search Aggregation organiza candidatos de vizinhos mais próximos aproximados (ANN) retidos em buckets, calcula métricas por bucket, cria buckets aninhados e retorna resultados representativos.
- No lado do servidor,
**ORDER BY**ordena resultados de consulta ou candidatos ANN por um ou mais campos escalares antes que a aplicação os receba.
A distinção entre consulta e busca é importante:
| Capacidade | Dados sendo resumidos ou ordenados | Formato principal do resultado | Limite de exatidão |
|---|---|---|---|
| Agregação de consultas | Todas as linhas visíveis que correspondem ao filtro | Uma linha por grupo, com valores agregados | Exata sobre o conjunto de linhas visíveis da consulta |
| Search Aggregation | Candidatos retidos pela busca ANN e pelo estágio de agrupamento | Buckets, métricas, resultados representativos e buckets filhos opcionais | Aproximada por design |
Consulta com ORDER BY | Linhas visíveis que correspondem ao filtro | Linhas ordenadas | Exata sobre o resultado filtrado da consulta |
Busca com ORDER BY | Candidatos ANN | Resultados ou grupos de busca ordenados | Não expande o limite de recall da ANN |
Este artigo explica por que essas operações pertencem ao banco de dados, como funciona a agregação distribuída, como o Search Aggregation difere do Grouping Search e onde a nova semântica termina.
Por que o pós-processamento no lado da aplicação deixa de funcionar
Mover a agregação e a ordenação para a aplicação pode parecer uma pequena escolha de implementação. Em escala, isso cria três problemas maiores.
A aplicação move muito mais dados do que a resposta contém
Suponha que um painel operacional precise da contagem de produtos e do preço médio de cada categoria entre dois milhões de linhas em estoque. Mesmo com uma carga útil aproximada de apenas 100 bytes por linha para a categoria, preço, chave primária e sobrecarga de serialização, a aplicação precisa receber cerca de 200 MB de dados antes de poder calcular o resultado.
Se o catálogo tiver 200 categorias, a resposta terá apenas algumas centenas de chaves e números—na ordem de kilobytes. A aplicação move várias ordens de magnitude mais dados do que retorna, paga o mesmo custo a cada atualização e precisa de memória suficiente no cliente para manter ou transmitir as linhas intermediárias.
Uma agregação dentro do mecanismo altera a unidade de movimentação de dados. As linhas brutas permanecem onde estão. O que atravessa os nós e eventualmente sai do Milvus é o conjunto muito menor de estados parciais e finais de grupos.
A ordenação local da página não é ordenação global
Ordenar após a paginação é um bug de correção, não apenas uma implementação ineficiente.
Se uma aplicação busca as linhas 11 a 20 e ordena apenas essas linhas por preço, ela produziu a ordem de preço dentro dessa página—não as linhas 11 a 20 do resultado globalmente ordenado por preço. Uma página posterior pode conter produtos mais baratos do que todos os produtos da primeira página.
O mesmo limite é importante na busca vetorial. Buscar um pequeno conjunto Top-K e ordená-lo na aplicação só consegue reordenar esses candidatos. Isso não consegue recuperar candidatos relevantes que o estágio ANN não retornou, e muitas vezes leva as aplicações a buscar em excesso apenas para tornar útil a ordenação no lado do cliente.
A ordenação no lado do servidor dá ao Milvus controle sobre a sequência de ordenação e paginação. Para cargas de trabalho de consulta, o mecanismo ordena o conjunto de linhas filtradas antes de aplicar a janela da página. Para cargas de trabalho de busca, ele ordena dentro do limite dos candidatos ANN e mantém essa limitação explícita.
O cliente não consegue reproduzir a visibilidade do banco de dados
A agregação também depende de quais linhas são visíveis no timestamp da consulta. Exclusões, entidades expiradas e gravações concorrentes são governadas pelo controle de concorrência multiversão (MVCC) e pela semântica de consistência do Milvus.
Depois que as linhas brutas saem do banco de dados, a aplicação geralmente assume que o lote recebido representa o snapshot correto. Reconstruir as mesmas regras de visibilidade em um cliente é impraticável, especialmente enquanto a coleção está recebendo gravações e exclusões.
A solução comum—um segundo mecanismo analítico alimentado por exportação e ETL—adiciona outra cópia dos dados, outro limite de consistência e outro pipeline para operar. Contagens, métricas e ordenação devem ser executadas onde tanto os dados quanto suas regras de visibilidade já existem.
Agora, vamos ver o que o Milvus 3.0 oferece.
Agregação de consultas: estatísticas exatas sobre linhas visíveis
A agregação de consultas responde a perguntas como:
- Quantos produtos em estoque há em cada categoria?
- Qual é o preço médio por marca?
- Quais são os timestamps mínimo e máximo de eventos para cada host?
- Quantos registros permanecem após a aplicação de um filtro e da visibilidade de TTL?
A API parece familiar para qualquer pessoa que tenha usado SQL: passe um ou mais campos em group_by_fields e coloque expressões de agregação em output_fields.
res = client.query(
collection_name="products",
filter='status == "on_sale"',
group_by_fields=["category"],
output_fields=["category", "count(*)", "avg(price)"],
)
# [
# {"category": "books", "count(*)": 18734, "avg(price)": 45.3},
# …
# ]
A sintaxe é a parte simples. O modelo de execução é o que torna o resultado útil em um banco de dados vetorial distribuído.
Estados locais ao segmento substituem a movimentação de linhas brutas
Uma coleção do Milvus pode abranger centenas ou milhares de segmentos distribuídos por vários nós de consulta, com dados recém-gravados ainda no caminho de streaming. Nenhum nó de execução começa com todas as linhas visíveis.
Portanto, o Milvus empurra a agregação para os segmentos:
- Cada segmento aplica localmente o filtro e as regras de visibilidade MVCC.
- O segmento emite um estado parcial por grupo em vez de suas linhas correspondentes.
- Estados parciais são mesclados dentro de um nó de consulta.
- O proxy realiza a mesclagem final entre nós e retorna os grupos concluídos.
A quantidade de dados intermediários agora escala com o número de grupos e estados agregados, em vez de escalar diretamente com o número de linhas correspondentes.
A operação de mesclagem depende do agregado:
| Agregado | Estado parcial | Regra de mesclagem |
|---|---|---|
count | Contagem parcial | Somar contagens |
sum | Soma parcial | Somar somas |
min | Mínimo parcial | Tomar o mínimo |
max | Máximo parcial | Tomar o máximo |
avg | Soma e contagem parciais | Somar ambos os estados e então dividir uma vez no estágio final |
avg é o caso instrutivo. Tirar a média de duas médias parciais é incorreto quando as partições contêm números diferentes de linhas. O Milvus carrega sum e count independentemente e calcula a média final apenas depois que ambos foram mesclados globalmente.
Esse é um dos motivos pelos quais a agregação pertence ao banco de dados: a operação não é simplesmente “executar a mesma função em vários lotes”. O mecanismo precisa preservar a álgebra de cada agregado através dos limites de segmentos e nós.
A visibilidade é aplicada antes da agregação
Linhas excluídas e expiradas são removidas dos estados parciais no nível do segmento de acordo com o limite de visibilidade da consulta. Elas não sobem pela pilha para depois serem corrigidas na aplicação.
Portanto, o resultado descreve as linhas que o Milvus considera visíveis para aquela solicitação, não uma coleção arbitrária de lotes obtidos em momentos ligeiramente diferentes.
limit agora conta grupos
Em uma consulta normal, limit controla quantas linhas de entidade são retornadas. Em uma consulta agrupada, ele controla quantos grupos são retornados. Como a cardinalidade do resultado é determinada por grupos, e não por linhas correspondentes, uma agregação de consulta também pode omitir limit quando precisa de todos os grupos.
Isso parece um pequeno detalhe de API, mas reflete um modelo de resultado diferente: a saída não é mais uma página de entidades. É uma relação cujas linhas representam grupos.
Search Aggregation: uma visão em buckets dos candidatos ANN
A agregação de consultas responde: “Como são as linhas visíveis que correspondem a este filtro?” O Search Aggregation faz uma pergunta diferente: “Como é o conjunto de candidatos recuperado para este vetor?”
Essa operação não tem equivalente SQL exato. A busca ANN primeiro estabelece um limite de candidatos orientado por similaridade. O Milvus então organiza os candidatos retidos por chaves escalares e retorna uma árvore de buckets em vez de uma lista plana comum de resultados.
Um bucket pode conter:
- uma chave como
brandou uma chave composta como(brand, color); - uma contagem de candidatos retidos;
- métricas incluindo
count,sum,avg,minemax; - entidades representativas selecionadas com
top_hits; e - uma
sub_aggregationaninhada que cria buckets filhos.
Para a página de busca de produtos, uma solicitação pode retornar buckets de marca, o preço médio dentro de cada bucket e três produtos representativos por marca:
from pymilvus import SearchAggregation, TopHits
aggregation = SearchAggregation(
fields=[“brand”],
size=10, # Return up to 10 brand buckets
metrics={“avg_price”: {“avg”: “price”}},
order=[{“_count”: “desc”}], # Order by retained-candidate count
top_hits=TopHits(
size=3,
sort=[{“_score”: “desc”}], # Use “asc” for L2 distance
),
)
res = client.search(
collection_name=“products”,
data=[query_vector],
anns_field=“embedding”,
search_aggregation=aggregation,
output_fields=[“title”, “brand”, “price”],
)
buckets = res.agg_buckets[0]
Quando search_aggregation está definido, a lista comum de resultados fica vazia. A aplicação lê a resposta de buckets em result.agg_buckets.
A especificação de agregação define dois limites diferentes
O Search Aggregation não executa GROUP BY sobre todas as entidades da coleção, e também não simplesmente pega uma resposta Top-K comum e agrega essa lista plana.
Sua execução tem três estágios:
- O Milvus executa a busca ANN para recuperar candidatos próximos ao vetor de consulta.
- O estágio de agrupamento retém um número limitado de candidatos para cada chave completa de bucket.
- O Milvus cria buckets, calcula métricas sobre os candidatos retidos, ordena os buckets e anexa resultados representativos ou buckets filhos.
Dois parâmetros controlam partes diferentes do resultado:
SearchAggregation.sizelimita quantos buckets são retornados naquele nível de agregação.- O maior
TopHits.sizeem qualquer lugar da árvore de agregação define o orçamento de candidatos retidos para cada chave composta completa. Se a solicitação não contivertop_hits, o orçamento por chave terá como padrão um.
O limit da busca de nível superior não controla esse modo e é ignorado quando search_aggregation está presente.
Essa distinção é essencial ao interpretar o count ou as métricas de um bucket. Com TopHits(size=3), um bucket de marca pode resumir no máximo três candidatos retidos para sua chave completa, mesmo que a coleção contenha milhares de produtos relevantes dessa marca. Aumentar TopHits.size amplia a janela de métricas por chave, mas não transforma a busca ANN em uma varredura exata.
Se a aplicação precisa de estatísticas exatas sobre todas as linhas visíveis que correspondem a um filtro, deve usar agregação de consultas. O Search Aggregation serve para descrever e comparar os candidatos produzidos pela recuperação por similaridade.
Search Aggregation e Grouping Search resolvem problemas diferentes
O Milvus oferece suporte ao Grouping Search (group_by)desde o Milvus 2.4. É fácil ver a palavra “agrupamento” nos dois recursos e assumir que são duas interfaces para a mesma operação. Seus contratos de saída são diferentes.
Grouping Search altera quais entidades aparecem em uma lista de resultados ranqueada. Um padrão comum de RAG armazena chunks como entidades individuais, agrupa-os por doc_id e retorna um ou alguns chunks de cada documento. A saída principal continua sendo resultados de busca comuns, mas com menos valores repetidos do campo de agrupamento.
Search Aggregation retorna uma visão estatística. A saída principal é uma árvore de buckets contendo chaves, contagens, métricas, resultados representativos e buckets filhos opcionais.
| Necessidade da aplicação | Preferir | Consumir |
|---|---|---|
| Uma lista de entidades ranqueada com maior diversidade em um campo | Grouping Search | Resultados de busca comuns |
| Contagens de facetas, métricas por grupo, resultados representativos ou distribuições aninhadas | Search Aggregation | Objetos AggregationBucket em result.agg_buckets |
Uma regra prática é começar pelo formato de resposta da UI ou da API. Se a aplicação renderiza uma lista, Grouping Search geralmente é o primitivo certo. Se ela renderiza facetas, cartões de distribuição ou uma hierarquia de grupos, use Search Aggregation.
Os dois modos são mutuamente exclusivos em uma solicitação porque definem formatos principais de resultado diferentes.
ORDER BY: mova a ordenação para antes do limite da aplicação
A ordenação é o recurso menos exótico desta versão e um dos mais fáceis de implementar incorretamente fora do mecanismo.
O Milvus 3.0 expõe ordenação tanto em consulta quanto em busca, mas os dois caminhos usam parâmetros de SDK diferentes e operam sobre conjuntos de entrada diferentes.
A ordenação de consultas ordena o conjunto de linhas filtradas
A consulta do PyMilvus usa order_by, expresso como uma lista de strings "field:direction". O mecanismo aplica o filtro, ordena as linhas visíveis e então aplica limit e offset.
res = client.query(
collection_name="products",
filter='category == "books"',
output_fields=["title", "price"],
order_by=["price:desc", "title:asc"],
limit=10,
offset=10, # Rows 11-20 in the filtered, price-sorted result
)
Isso torna a consulta útil para navegação ordenada por negócios: registros ingeridos mais recentes, produtos de maior preço dentro de um filtro, menor estoque ou valores extremos para inspeção de dados. Sem ordenação no lado do servidor, as aplicações precisavam recuperar as linhas primeiro e não conseguiam definir uma ordem de negócio confiável entre páginas.
Para campos de consulta anuláveis, a ordem crescente coloca nulos por último e a ordem decrescente os coloca primeiro. Um campo de ordenação não precisa aparecer em output_fields; inclua-o apenas quando a aplicação precisar do valor na resposta.
A ordenação de busca reordena o conjunto de candidatos ANN
A busca do PyMilvus usa order_by_fields, em que cada entrada nomeia um campo escalar e uma direção:
res = client.search(
collection_name="products",
data=[query_vector],
anns_field="embedding",
limit=50,
output_fields=["title", "price"],
order_by_fields=[
{"field": "price", "order": "asc"},
],
)
A ANN ainda determina quais entidades se tornam candidatas. order_by_fields altera como esses candidatos são retornados; ela não faz a busca varrer globalmente a coleção pelos produtos mais baratos.
Esse limite dá às duas APIs funções distintas:
- Use consulta mais
order_byquando a própria ordem escalar define o resultado, como os dez produtos em estoque mais baratos. - Use busca mais
order_by_fieldsquando a relevância semântica ou vetorial define o conjunto de candidatos e um campo escalar determina como esses candidatos devem ser apresentados.
A ordenação por vários campos aplica as chaves na ordem da lista. Quando candidatos de busca têm os mesmos valores para todas as chaves escalares especificadas, o Milvus preserva sua ordem original por pontuação de similaridade.
A ordenação também se compõe com o Grouping Search. O Milvus ordena grupos pelo valor escalar configurado da entidade principal de cada grupo, mantendo o formato de resultado agrupado. Isso é útil quando a aplicação quer tanto diversidade em um campo quanto uma ordem de grupos relevante para o negócio.
O que essas capacidades tornam possível
As APIs são primitivas gerais de banco de dados, mas várias cargas de trabalho de recuperação se beneficiam imediatamente.
RAG e agentes: inspecionar a concentração da recuperação
Um sistema RAG ou agêntico pode agrupar chunks recuperados por documento de origem, linha de produto, tenant ou tipo de conteúdo. Um resultado concentrado em dois documentos carrega um sinal de cobertura diferente de um resultado espalhado por dezenas de fontes.
Essa distribuição não é uma garantia de qualidade da resposta. Ela é, no entanto, um diagnóstico de recuperação útil que uma aplicação ou agente pode combinar com pontuações, citações e outras verificações ao decidir se deve ampliar a consulta, recuperar novamente ou pedir esclarecimento.
Grouping Search continua sendo a escolha certa quando o objetivo é simplesmente diversificar os chunks retornados. Search Aggregation é útil quando o sistema precisa da própria distribuição.
E-commerce e recomendação de conteúdo: retornar facetas junto com a busca
A página inicial de busca de produtos pode receber buckets de marca, métricas de preço, itens representativos e uma lista de candidatos ordenada por escalar a partir do Milvus. A aplicação ainda controla a apresentação e a lógica de negócio, mas não precisa mais reconstruir semânticas básicas de bucket a partir de resultados exportados.
Logs e segurança: combinar similaridade com distribuição de incidentes
A busca por similaridade pode encontrar eventos relacionados a uma linha de log suspeita. O Search Aggregation pode então mostrar quais hosts dominam esses candidatos, o timestamp mínimo e máximo em cada bucket de host ou como os candidatos se dividem por severidade e serviço.
O resultado continua sendo uma visão dos candidatos recuperados, e não uma contagem global exata de incidentes. Quando a investigação precisa de contagens exatas sobre todos os eventos que correspondem a um filtro, a agregação de consultas fornece esse segundo caminho.
Operações e exploração de dados: calcular em vez de exportar
Painéis e ferramentas administrativas podem executar contagens e médias exatas sobre linhas filtradas e então navegar pelas entidades subjacentes em uma ordem escalar definida. Isso remove muitos utilitários pontuais de “exportar, calcular e ordenar”, sem fingir que o Milvus se tornou um banco de dados analítico completo.
Limites: o que agregação e ORDER BY não substituem
Esses recursos estendem o mecanismo de recuperação; eles não transformam o Milvus em um sistema de processamento analítico online (OLAP).
- A agregação de consultas oferece suporte a agrupamento mais
count,sum,avg,minemax. Ela não adiciona joins, funções de janela ou subconsultas complexas. Grandes trabalhos analíticos offline ainda pertencem a sistemas como Spark, que podem trabalhar com snapshots do Milvus 3.0 e caminhos de armazenamento compartilhado. - Chaves de grupo de consulta oferecem suporte a campos inteiros,
VARCHAReTIMESTAMPTZ. As chaves de bucket do Search Aggregation também oferecem suporte a campos booleanos. Valores de ponto flutuante, vetores, JSON e arrays não são chaves de bucket. - Para Search Aggregation,
countaceita"*"ou uma origem não JSON e não dinâmica;sumeavgexigem origens numéricas; eminemaxtambém oferecem suporte a origens string eTIMESTAMPTZ. A agregação de consultas segue os mesmos limites de tipos aritméticos. Consulte o guia da API antes de aplicar um agregado a um tipo de campo complexo. - A agregação de consultas pode ordenar a saída agrupada por chaves de grupo, enquanto a ordenação por um agregado calculado como
count(*)continua sendo um limite atual. Sem uma ordem explícita, a ordem dos grupos não é garantida. - Search Aggregation atualmente não pode ser combinado com Hybrid Search, Grouping Search, Search Iterators, um offset diferente de zero ou realce na mesma solicitação.
- Contagens e métricas do Search Aggregation descrevem candidatos ANN retidos, não a coleção completa nem todas as entidades que possam ser semanticamente relevantes.
- O
ORDER BYde busca altera a apresentação dos candidatos. Ele não corrige candidatos ANN perdidos nem converte a recuperação por similaridade em uma consulta Top-N escalar exata.
A forma mais clara de escolher entre os novos primitivos é começar pela pergunta:
- Para estatísticas exatas sobre linhas visíveis filtradas, use agregação de consultas.
- Para uma distribuição sobre candidatos de recuperação por similaridade, use Search Aggregation.
- Para uma lista ranqueada diversa, use Grouping Search.
- Para uma ordem escalar definida, use consulta ou busca com
ORDER BYde acordo com o caminho que estabeleceu o conjunto de resultados.
De listas de candidatos a resultados estruturados
Bancos de dados vetoriais tradicionalmente otimizaram uma pergunta: quais K entidades estão mais próximas deste vetor?
Sistemas de recuperação em produção fazem perguntas de acompanhamento imediatamente. Quais grupos dominam o resultado? Quais são suas contagens e intervalos? Quais exemplos representam cada grupo? Em que ordem de negócio a aplicação deve apresentar as linhas ou candidatos?
O Milvus 3.0 traz essas operações para o mesmo mecanismo que é dono dos dados, do limite de candidatos ANN e da semântica de visibilidade. A agregação de consultas realiza redução distribuída exata sobre linhas visíveis. O Search Aggregation constrói uma visão em buckets sobre candidatos ANN retidos. ORDER BY dá aos caminhos de consulta e busca uma ordem escalar no lado do servidor, sem pedir que a aplicação a reconstrua página por página.
O resultado não é um mecanismo OLAP escondido dentro de um banco de dados vetorial. É um mecanismo de recuperação que consegue retornar mais da estrutura de que as aplicações realmente precisam.
Experimente agregação e ORDER BY no Milvus 3.0
O Milvus 3.0 já está disponível. Use o guia de consultas para agregação exata e ordenação de consultas, o guia de Search Aggregation para semântica e limites de buckets, o guia de Basic Vector Search para ordenação de buscas e o guia de Grouping Search quando seu objetivo principal for diversidade de resultados.
Para a versão mais ampla, consulte o blog de lançamento do Milvus 3.0, as notas de versão do Milvus 3.0 e o repositório milvus-io/milvus.
Se você quiser avaliar as mesmas APIs sem operar o cluster por conta própria, experimente-as no Zilliz Cloud. A referência atual de consultas do Zilliz Cloud e a referência de busca descrevem disponibilidade e parâmetros para tipos de cluster gerenciado.
Para discutir uma carga de trabalho ou um caso limite com a equipe, participe da comunidade Milvus no Discord ou agende uma sessão de Milvus Office Hours.
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word



