¿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
users
colección y unacomments
colección y desea tener una nueva colección que tenga información demográfica del usuario para cada comentario.Digamos que la
users
colección tiene los siguientes campos:Y luego la
comments
colección tiene los siguientes campos:Harías este mapa / reducir:
En este punto, tendrá una nueva colección llamada
users_comments
que contiene los datos combinados y ahora puede usarla. Todas estas colecciones reducidas tienen_id
la clave que emitía en sus funciones de mapa y luego todos los valores son un subobjeto dentro de lavalue
clave: 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_comments
colecció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
ensureIndex
la 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 unavalue
clave, por lo que si tuviera que indexarcomments_with_demographics
elcreated
tiempo de comentario , seríadb.comments_with_demographics.ensureIndex({"value.created": 1});
fuente
users_comments
colecció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
books
colecció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_collection
y 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
aggregate
de 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
$project
etapa: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
pipeline
campo para hacer un poco de filtrado específico, o salirlocalField
yforeignField
como 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
$project
etapa junto con el$concatArrays
operador 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
$unwind
y una$replaceRoot
etapa 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$unionWith
etapa de agregación con$group
el nuevo$accumulator
operador:$unionWith
combina 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
$group
registramos$user
y acumulamos elementos utilizando el$accumulator
operador que permite acumulaciones personalizadas de documentos a medida que se agrupan:accumulateArgs
.init
define el estado que se acumulará a medida que agrupamos elementos.accumulate
funció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 elbook
campo definido, entonces actualizamos labooks
parte del estado.merge
se 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
@Reference
anotación recupera la entidad referenciada cuando se la consulta, por lo que puedo evitar hacerlo yo mismo en el código.fuente