sql >> Base de Datos >  >> NoSQL >> MongoDB

Cómo escribir consultas de unión en mongoDB

Es posible realizar uniones en MongoDB al estilo 'SQL UNION' utilizando agregaciones junto con búsquedas, en una sola consulta.

Algo como esto:

    db.getCollection("AnyCollectionThatContainsAtLeastOneDocument").aggregate(
    [
      { $limit: 1 }, // Reduce the result set to a single document.
      { $project: { _id: 1 } }, // Strip all fields except the Id.
      { $project: { _id: 0 } }, // Strip the id. The document is now empty.

      // Lookup all collections to union together.
      { $lookup: { from: 'collectionToUnion1', pipeline: [...], as: 'Collection1' } },
      { $lookup: { from: 'collectionToUnion2', pipeline: [...], as: 'Collection2' } },
      { $lookup: { from: 'collectionToUnion3', pipeline: [...], as: 'Collection3' } },

      // Merge the collections together.
      {
        $project:
        {
          Union: { $concatArrays: ["$Collection1", "$Collection2", "$Collection3"] }
        }
      },

      { $unwind: "$Union" }, // Unwind the union collection into a result set.
      { $replaceRoot: { newRoot: "$Union" } } // Replace the root to cleanup the resulting documents.
    ]);

Aquí está la explicación de cómo funciona:

  1. Crear una instancia de un aggregate de cualquiera colección de su base de datos que tiene al menos un documento en ella. Si no puede garantizar que ninguna colección de su base de datos esté 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 de unión.

  2. Haga que la primera etapa de su canalización sea { $limit: 1 } . Esto eliminará todos los documentos de la colección excepto el primero.

  3. Elimina todos los campos del documento restante usando $project etapas:

    { $project: { _id: 1 } },
    { $project: { _id: 0 } }
    
  4. Su agregado ahora contiene un único documento vacío. Es hora de agregar búsquedas para cada colección que desee unir. Puede usar la pipeline campo para hacer un filtrado específico, o dejar localField y foreignField como nulo para que coincida con toda la colección.

    { $lookup: { from: 'collectionToUnion1', pipeline: [...], as: 'Collection1' } },
    { $lookup: { from: 'collectionToUnion2', pipeline: [...], as: 'Collection2' } },
    { $lookup: { from: 'collectionToUnion3', pipeline: [...], as: 'Collection3' } }
    
  5. Ahora tiene un agregado que contiene un solo documento que contiene 3 matrices como esta:

    {
        Collection1: [...],
        Collection2: [...],
        Collection3: [...]
    }
    

    Luego puede fusionarlos en una sola matriz usando un $project escenario junto con $concatArrays operador de agregación:

    {
      "$project" :
      {
        "Union" : { $concatArrays: ["$Collection1", "$Collection2", "$Collection3"] }
      }
    }
    
  6. Ahora tiene un agregado que contiene un solo documento, en el que se encuentra una matriz que contiene su unión de colecciones. Lo que queda por hacer es agregar un $unwind y un $replaceRoot etapa para dividir su matriz en documentos separados:

    { $unwind: "$Union" },
    { $replaceRoot: { newRoot: "$Union" } }
    
  7. Voila. Sabe que tiene un conjunto de resultados que contiene las colecciones que quería unir. Luego puede agregar más etapas para filtrarlo aún más, ordenarlo, aplicar skip() y limit(). Prácticamente todo lo que quieras.