¿Cómo puedo (en MongoDB) combinar datos de múltiples colecciones en una sola colección?
¿Puedo usar map-reduce y si es así, cómo?
Agradecería mucho algún ejemplo, ya que soy un novato.
mongodb
mongodb-query
aggregation-framework
usuario697697
fuente
fuente

db.collection1.find().forEach(function(doc){db.collection2.save(doc)});es suficiente. Especifique su controlador usado (java, php, ...) si no usa mongo shell.Respuestas:
Aunque no puede hacer esto en tiempo real, puede ejecutar map-reduce varias veces para fusionar datos mediante la opción "reduce" en MongoDB 1.8+ map / reduce (consulte http://www.mongodb.org/ display / DOCS / MapReduce # MapReduce-Outputoptions ). Debe tener alguna clave en ambas colecciones que pueda usar como _id.
Por ejemplo, supongamos que tiene una
userscolección y unacommentscolección y desea tener una nueva colección que tenga información demográfica del usuario para cada comentario.Digamos que la
userscolección tiene los siguientes campos:Y luego la
commentscolección tiene los siguientes campos:Harías este mapa / reducir:
En este punto, tendrá una nueva colección llamada
users_commentsque contiene los datos combinados y ahora puede usarla. Todas estas colecciones reducidas tienen_idla clave que emitía en sus funciones de mapa y luego todos los valores son un subobjeto dentro de lavalueclave: los valores no están en el nivel superior de estos documentos reducidos.Este es un ejemplo algo simple. Puede repetir esto con más colecciones tanto como quiera seguir acumulando la colección reducida. También puede hacer resúmenes y agregaciones de datos en el proceso. Probablemente definiría más de una función de reducción, ya que la lógica para agregar y preservar los campos existentes se vuelve más compleja.
También notará que ahora hay un documento para cada usuario con todos los comentarios de ese usuario en una matriz. Si fusionáramos datos que tienen una relación uno a uno en lugar de uno a muchos, sería plano y simplemente podría usar una función de reducción como esta:
Si desea aplanar la
users_commentscolección para que sea un documento por comentario, ejecute esto adicionalmente:Esta técnica definitivamente no debe realizarse sobre la marcha. Es adecuado para un trabajo cron o algo así que actualiza los datos combinados periódicamente. Probablemente querrá ejecutar
ensureIndexla nueva colección para asegurarse de que las consultas que realice contra ella se ejecuten rápidamente (tenga en cuenta que sus datos aún están dentro de unavalueclave, por lo que si tuviera que indexarcomments_with_demographicselcreatedtiempo de comentario , seríadb.comments_with_demographics.ensureIndex({"value.created": 1});fuente
users_commentscolección después del primer bloque de código gist.github.com/nolanamy/83d7fb6a9bf92482a1c4311ad9c78835MongoDB 3.2 ahora permite combinar datos de múltiples colecciones en una a través de la etapa de agregación $ lookup . Como ejemplo práctico, supongamos que tiene datos sobre libros divididos en dos colecciones diferentes.
Primera colección, llamada
books, que tiene los siguientes datos:Y la segunda colección, llamada
books_selling_data, tiene los siguientes datos:Para fusionar ambas colecciones es solo una cuestión de usar $ lookup de la siguiente manera:
Después de esta agregación, la
bookscolección tendrá el siguiente aspecto:Es importante tener en cuenta algunas cosas:
books_selling_data, no se puede fragmentar.Entonces, como conclusión, si desea consolidar ambas colecciones, teniendo, en este caso, un campo plano copias_vendidas con el total de copias vendidas, tendrá que trabajar un poco más, probablemente utilizando una colección intermedia que, entonces, ser $ a cabo a la colección definitiva.
fuente
$lookup¿no deberían estar todos "localField" y "foreignField" iguales "isbn"? no "_id" e "isbn"?Si no hay una inserción masiva en mongodb, colocamos todos los objetos en bucle
small_collectiony los insertamos uno por uno enbig_collection:fuente
Ejemplo muy básico con $ lookup.
Aquí se usa
En vez de
Porque {$ unwind: "$ userRoleData"} esto devolverá un resultado vacío o 0 si no se encuentra un registro coincidente con $ lookup.
fuente
Es posible hacer uniones en MongoDB de una manera 'UNIÓN SQL' usando agregaciones junto con búsquedas, en una sola consulta. Aquí hay un ejemplo que he probado que funciona con MongoDB 4.0:
Aquí está la explicación de cómo funciona:
Cree una instancia
aggregatede cualquier colección de su base de datos que tenga al menos un documento. Si no puede garantizar que una colección de su base de datos no estará vacía, puede solucionar este problema creando en su base de datos algún tipo de colección 'ficticia' que contenga un único documento vacío que estará allí específicamente para realizar consultas sindicales.Haga que la primera etapa de su tubería sea
{ $limit: 1 }. Esto eliminará todos los documentos de la colección, excepto el primero.Elimine todos los campos del documento restante utilizando una
$projectetapa:Su agregado ahora contiene un único documento vacío. Es hora de agregar búsquedas para cada colección que desee unir. Usted puede utilizar el
pipelinecampo para hacer un poco de filtrado específico, o salirlocalFieldyforeignFieldcomo nulo para que coincida con la colección completa.Ahora tiene un agregado que contiene un único documento que contiene 3 matrices como esta:
Luego puede combinarlos en una sola matriz usando una
$projectetapa junto con el$concatArraysoperador de agregación:Ahora tiene un agregado que contiene un único documento, en el que se encuentra una matriz que contiene su unión de colecciones. Lo que queda por hacer es agregar una
$unwindy una$replaceRootetapa para dividir su matriz en documentos separados:Voilà. Ahora tiene un conjunto de resultados que contiene las colecciones que desea unir. Luego puede agregar más etapas para filtrarlo aún más, ordenarlo, aplicar skip () y limit (). Casi todo lo que quieras.
fuente
use múltiples búsquedas $ para múltiples colecciones en agregación
consulta:
resultado:
fuente
Mongorestore tiene esta característica de agregar encima de lo que ya está en la base de datos, por lo que este comportamiento podría usarse para combinar dos colecciones:
Todavía no lo intenté, pero podría funcionar más rápido que el enfoque de mapa / reducción.
fuente
Comenzando
Mongo 4.4, podemos lograr esta unión dentro de una tubería de agregación al acoplar la nueva$unionWithetapa de agregación con$groupel nuevo$accumulatoroperador:$unionWithcombina registros de la colección dada dentro de documentos que ya están en la tubería de agregación. Después de las 2 etapas de unión, tenemos todos los registros de usuarios, libros y películas dentro de la tubería.Luego
$groupregistramos$usery acumulamos elementos utilizando el$accumulatoroperador que permite acumulaciones personalizadas de documentos a medida que se agrupan:accumulateArgs.initdefine el estado que se acumulará a medida que agrupamos elementos.accumulatefunción permite realizar una acción personalizada con un registro que se agrupa para generar el estado acumulado. Por ejemplo, si el elemento que se está agrupando tiene elbookcampo definido, entonces actualizamos labooksparte del estado.mergese usa para fusionar dos estados internos. Solo se usa para agregaciones que se ejecutan en grupos fragmentados o cuando la operación excede los límites de memoria.fuente
Sí, puedes: Toma esta función de utilidad que he escrito hoy:
Puede pasar a esta función cualquier cantidad de colecciones, la primera será la meta. Todas las colecciones restantes son fuentes para ser transferidas a la meta.
fuente
Fragmento de código. Cortesía: varias publicaciones en el desbordamiento de pila, incluido este.
fuente
Tienes que hacer eso en tu capa de aplicación. Si está utilizando un ORM, podría usar anotaciones (o algo similar) para extraer referencias que existen en otras colecciones. Solo he trabajado con Morphia , y la
@Referenceanotación recupera la entidad referenciada cuando se la consulta, por lo que puedo evitar hacerlo yo mismo en el código.fuente