MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Comment écrire des requêtes d'union dans mongoDB

Faire des unions dans MongoDB de manière "SQL UNION" est possible en utilisant des agrégations avec des recherches, dans une seule requête.

Quelque chose comme ça :

    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.
    ]);

Voici l'explication de son fonctionnement :

  1. Instancier un aggregate sur tout collection de votre base de données contenant au moins un document. Si vous ne pouvez pas garantir qu'aucune collection de votre base de données ne sera vide, vous pouvez contourner ce problème en créant dans votre base de données une sorte de collection 'factice' contenant un seul document vide qui sera là spécifiquement pour faire des requêtes d'union.

  2. Faites en sorte que la première étape de votre pipeline soit { $limit: 1 } . Cela supprimera tous les documents de la collection sauf le premier.

  3. Supprimez tous les champs du document restant en utilisant $project étapes :

    { $project: { _id: 1 } },
    { $project: { _id: 0 } }
    
  4. Votre agrégat contient maintenant un seul document vide. Il est temps d'ajouter des recherches pour chaque collection que vous souhaitez regrouper. Vous pouvez utiliser le pipeline champ pour effectuer un filtrage spécifique, ou laissez localField et foreignField comme null pour correspondre à toute la collection.

    { $lookup: { from: 'collectionToUnion1', pipeline: [...], as: 'Collection1' } },
    { $lookup: { from: 'collectionToUnion2', pipeline: [...], as: 'Collection2' } },
    { $lookup: { from: 'collectionToUnion3', pipeline: [...], as: 'Collection3' } }
    
  5. Vous avez maintenant un agrégat contenant un seul document qui contient 3 tableaux comme celui-ci :

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

    Vous pouvez ensuite les fusionner en un seul tableau à l'aide d'un $project étape avec le $concatArrays opérateur d'agrégation :

    {
      "$project" :
      {
        "Union" : { $concatArrays: ["$Collection1", "$Collection2", "$Collection3"] }
      }
    }
    
  6. Vous avez maintenant un agrégat contenant un seul document, dans lequel se trouve un tableau qui contient votre union de collections. Il ne reste plus qu'à ajouter un $unwind et un $replaceRoot étape pour diviser votre tableau en documents distincts :

    { $unwind: "$Union" },
    { $replaceRoot: { newRoot: "$Union" } }
    
  7. Voilà. Vous savez que vous avez un jeu de résultats contenant les collections que vous vouliez réunir. Vous pouvez ensuite ajouter plus d'étapes pour le filtrer davantage, le trier, appliquer skip() et limit(). À peu près tout ce que vous voulez.