Como posso (no MongoDB) combinar dados de várias coleções em uma coleção?
Posso usar a redução de mapa e, em caso afirmativo, como?
Eu apreciaria muito alguns exemplos, pois sou um novato.
mongodb
mongodb-query
aggregation-framework
user697697
fonte
fonte
db.collection1.find().forEach(function(doc){db.collection2.save(doc)});
é suficiente. Por favor, especifique o driver usado (java, php, ...) se você não usar o mongo shell.Respostas:
Embora você não possa fazer isso em tempo real, é possível executar a redução de mapa várias vezes para mesclar dados usando a opção "reduzir" no MongoDB 1.8+ map / reduz (consulte http://www.mongodb.org/ display / DOCS / MapReduce # MapReduce-Outputoptions ). Você precisa ter alguma chave nas duas coleções que possa ser usada como um _id.
Por exemplo, digamos que você tenha uma
users
coleção e umacomments
coleção e deseje ter uma nova coleção com algumas informações demográficas do usuário para cada comentário.Digamos que a
users
coleção tenha os seguintes campos:E então a
comments
coleção possui os seguintes campos:Você faria este mapa / reduziria:
Nesse ponto, você terá uma nova coleção chamada
users_comments
que contém os dados mesclados e agora poderá usá-lo. Todas essas coleções reduzidas possuem_id
qual é a chave que você estava emitindo nas funções do mapa e, em seguida, todos os valores são um subobjeto dentro davalue
chave - os valores não estão no nível superior desses documentos reduzidos.Este é um exemplo um pouco simples. Você pode repetir isso com mais coleções o quanto quiser continuar construindo a coleção reduzida. Você também pode fazer resumos e agregações de dados no processo. É provável que você defina mais de uma função de redução, pois a lógica para agregar e preservar campos existentes fica mais complexa.
Você também observará que agora existe um documento para cada usuário com todos os comentários desse usuário em uma matriz. Se estivéssemos mesclando dados que têm um relacionamento um para um em vez de um para muitos, seria simples e você poderia simplesmente usar uma função de redução como esta:
Se você deseja nivelar a
users_comments
coleção, de modo que seja um documento por comentário, execute adicionalmente este:Esta técnica definitivamente não deve ser realizada em tempo real. É adequado para um trabalho cron ou algo assim que atualiza os dados mesclados periodicamente. Provavelmente, você desejará executar
ensureIndex
a nova coleção para garantir que as consultas executadas com rapidez sejam executadas rapidamente (lembre-se de que seus dados ainda estão dentro de umavalue
chave; portanto, se você indexarcomments_with_demographics
ocreated
tempo dos comentários , seriadb.comments_with_demographics.ensureIndex({"value.created": 1});
fonte
users_comments
coleção após o primeiro bloco de código gist.github.com/nolanamy/83d7fb6a9bf92482a1c4311ad9c78835O MongoDB 3.2 agora permite combinar dados de várias coleções em uma até o estágio de agregação de pesquisa $ . Como exemplo prático, digamos que você tenha dados sobre livros divididos em duas coleções diferentes.
Primeira coleção, chamada
books
, com os seguintes dados:E a segunda coleção, chamada
books_selling_data
, com os seguintes dados:Para mesclar as duas coleções, basta usar a pesquisa $ da seguinte maneira:
Após essa agregação, a
books
coleção terá a seguinte aparência:É importante observar algumas coisas:
books_selling_data
, não podem ser fragmentados.Portanto, como conclusão, se você deseja consolidar as duas coleções, tendo, nesse caso, um campo simples de cópias_soldado com o total de cópias vendidas, será necessário trabalhar um pouco mais, provavelmente usando uma coleção intermediária que, então, seja $ out para a coleção final.
fonte
$lookup
nem todos "localField" e "ForeignField" devem ser iguais a "isbn"? não "_id" e "isbn"?Se não houver inserção em massa no mongodb, fazemos um loop de todos os objetos no
small_collection
e os inserimos um a um nobig_collection
:fonte
Exemplo muito básico com $ lookup.
Aqui é usado
Ao invés de
Como {$ unwind: "$ userRoleData"}, isso retornará um resultado vazio ou 0 se nenhum registro correspondente for encontrado com a pesquisa $.
fonte
É possível fazer uniões no MongoDB da maneira 'SQL UNION' usando agregações e pesquisas, em uma única consulta. Aqui está um exemplo que testei que funciona com o MongoDB 4.0:
Aqui está a explicação de como funciona:
Instanciar um
aggregate
fora de qualquer coleção de seu banco de dados que tem pelo menos um documento na mesma. Se você não pode garantir que nenhuma coleção do seu banco de dados esteja vazia, você pode solucionar esse problema criando no seu banco de dados algum tipo de coleção 'fictícia' contendo um único documento vazio que estará lá especificamente para realizar consultas de união.Faça o primeiro estágio do seu pipeline
{ $limit: 1 }
. Isso removerá todos os documentos da coleção, exceto o primeiro.Retire todos os campos do documento restante usando um
$project
estágio:Seu agregado agora contém um único documento vazio. É hora de adicionar pesquisas para cada coleção que você deseja unir. Você pode usar o
pipeline
campo para fazer alguma filtragem específica ou deixarlocalField
eforeignField
como nulo para corresponder à coleção inteira.Agora você tem um agregado que contém um único documento que contém três matrizes como este:
Você pode mesclá-los em uma única matriz usando um
$project
estágio junto com o$concatArrays
operador de agregação:Agora você tem um agregado que contém um único documento, no qual está localizada uma matriz que contém sua união de coleções. O que falta fazer é adicionar um
$unwind
e um$replaceRoot
estágio para dividir sua matriz em documentos separados:Voilà. Agora você tem um conjunto de resultados contendo as coleções que deseja unir. Você pode adicionar mais estágios para filtrá-lo ainda mais, classificá-lo, aplicar skip () e limit (). Praticamente qualquer coisa que você quiser.
fonte
use várias pesquisas de $ para várias coleções na agregação
inquerir:
resultado:
fonte
O Mongorestore possui esse recurso de anexar sobre o que já está no banco de dados, portanto esse comportamento pode ser usado para combinar duas coleções:
Ainda não tentei, mas pode ter um desempenho mais rápido que a abordagem de mapa / redução.
fonte
Começando
Mongo 4.4
, podemos conseguir essa junção em um pipeline de agregação, acoplando o novo$unionWith
estágio de agregação ao$group
novo$accumulator
operador:$unionWith
combina registros da coleção fornecida em documentos já no pipeline de agregação. Após os 2 estágios da união, temos todos os registros de usuários, livros e filmes no pipeline.Em seguida,
$group
registramos$user
e acumulamos itens usando o$accumulator
operador, permitindo acumulações personalizadas de documentos conforme eles são agrupados:accumulateArgs
.init
define o estado que será acumulado à medida que agrupamos elementos.accumulate
função permite executar uma ação personalizada com um registro sendo agrupado para criar o estado acumulado. Por exemplo, se o item que está sendo agrupado tiver obook
campo definido, atualizamos abooks
parte do estado.merge
é usado para mesclar dois estados internos. É usado apenas para agregações executadas em clusters fragmentados ou quando a operação excede os limites de memória.fonte
Sim, você pode: Pegue esta função de utilidade que escrevi hoje:
Você pode passar para esta função qualquer número de coleções, a primeira será a de destino. Todas as demais coleções são fontes a serem transferidas para a de destino.
fonte
Fragmento de código. Cortesia - várias postagens no estouro de pilha, incluindo esta.
fonte
Você deve fazer isso na sua camada de aplicativo. Se você estiver usando um ORM, ele poderá usar anotações (ou algo semelhante) para extrair referências que existem em outras coleções. Eu só trabalhei com Morphia , e a
@Reference
anotação busca a entidade referenciada quando consultada, por isso sou capaz de evitar fazer isso sozinha no código.fonte