sql >> Database teknologi >  >> NoSQL >> MongoDB

$unionWith – MongoDBs ækvivalent af UNION ALL

Hvis du er fortrolig med SQL, kender du måske til UNION klausul, som sammenkæder resultaterne af to forespørgsler til et enkelt resultatsæt. Især UNION ALL omfatter dubletter.

I MongoDB kan vi bruge $unionWith aggregeringspipeline-stadiet for at opnå den samme effekt som UNION ALL producerer. $unionWith stage udfører en forening af to samlinger – den kombinerer pipelineresultater fra to samlinger til et enkelt resultatsæt. Og det inkluderer dubletter.

Eksempel

Antag, at vi opretter to samlinger; en kaldet cats og en anden kaldet dogs . Og vi indsætter følgende dokumenter i dem:

db.cats.insertMany([
    { _id: 1, name: "Fluffy", type: "Cat", weight: 5 },
    { _id: 2, name: "Scratch", type: "Cat", weight: 3 },
    { _id: 3, name: "Meow", type: "Cat", weight: 7 }
    ])

db.dogs.insertMany([
    { _id: 1, name: "Wag", type: "Dog", weight: 20 },
    { _id: 2, name: "Bark", type: "Dog", weight: 10 },
    { _id: 3, name: "Fluffy", type: "Dog", weight: 40 }
    ]) 

Vi kan nu køre en forespørgsel mod disse samlinger og bruge $unionWith trin for at kombinere resultaterne af hver forespørgsel.

Eksempel:

db.cats.aggregate( [
   { $set: { _id: "$_id" } },
   { $unionWith: { coll: "dogs", pipeline: [ { $set: { _id: "$_id" } } ] } },
   { $sort: { type: 1, weight: -1, name: 1 } }
] ) 

Resultat:

{ "_id" :3, "name" :"Mjav", "type" :"Kat", "vægt" :7 }{ "_id" :1, "name" :"Fluffy", "type" :"Kat", "vægt" :5 }{ "_id" :2, "navn" :"Krat", "type" :"Kat", "vægt" :3 }{ "_id" :3, "navn" :"Fluffy", "type" :"Hund", "weight" :40 }{ "_id" :1, "name" :"Wag", "type" :"Hund", "weight" :20 }{ " _id" :2, "name" :"Bark", "type" :"Hund", "vægt" :10 }

I dette eksempel har hvert dokument et typefelt med enten cat eller dog og så det er ret tydeligt, hvilket dokument der kommer fra hvilken samling.

Men hvis dokumenterne ikke havde typefeltet, ville det være sværere at finde ud af, hvor en indsamling slutter, og en anden starter. I dette tilfælde kan vi bruge en streng literal ved $set fase for at repræsentere samlingens navn.

Eksempel:

db.cats.aggregate( [
   { $set: { _id: "cat" } },
   { $unionWith: { coll: "dogs", pipeline: [ { $set: { _id: "dog" } } ] } },
   { $sort: { type: 1, weight: -1, name: 1 } }
] ) 

Resultat:

{ "_id" :"cat", "name" :"Mjav", "type" :"Kat", "vægt" :7 }{ "_id" :"kat", "name" :"Fluffy" , "type" :"Kat", "vægt" :5 }{ "_id" :"kat", "navn" :"Krat", "type" :"Kat", "vægt" :3 }{ "_id" :"hund", "name" :"Fluffy", "type" :"Hund", "vægt" :40 }{ "_id" :"hund", "name" :"Wag", "type" :"Hund ", "weight" :20 }{ "_id" :"dog", "name" :"Bark", "type" :"Hund", "weight" :10 }

Sortering på tværs af samlinger

I de foregående eksempler blev kattene og hundene sorteret på en måde, der adskilte dem i to adskilte grupper; først katte, så hunde. Dette skete primært fordi vi sorterede efter type felt først.

Men vi kan sortere det på et hvilket som helst andet felt, hvilket kan resultere i, at katte og hunde bliver kombineret.

Eksempel:

db.cats.aggregate( [
   { $set: { _id: "cat" } },
   { $unionWith: { coll: "dogs", pipeline: [ { $set: { _id: "dog" } } ] } },
   { $sort: { name: 1 } }
] ) 

Resultat:

{ "_id" :"hund", "name" :"Bark", "type" :"Hund", "vægt" :10 }{ "_id" :"kat", "name" :"Fluffy" , "type" :"Kat", "vægt" :5 }{ "_id" :"hund", "name" :"Fluffy", "type" :"Hund", "vægt" :40 }{ "_id" :"kat", "name" :"Mjav", "type" :"Kat", "vægt" :7 }{ "_id" :"kat", "name" :"Krat", "type" :"Kat ", "weight" :3 }{ "_id" :"dog", "name" :"Wag", "type" :"Hund", "weight" :20 }

Projektioner

Du kan bruge $project trin for at angive, hvilke felter der skal videregives til næste trin i pipelinen. For eksempel kan du derfor reducere antallet af felter, der returneres af forespørgslen.

Eksempel:

db.cats.aggregate( [
   { $project: { name: 1, _id: 0 } },
   { $unionWith: { coll: "dogs", pipeline: [ { $project: { name: 1, _id: 0 } } ]} }
] ) 

Resultat:

{ "name" :"Fluffy" }{ "name" :"Scratch" }{ "name" :"Meow" }{ "name" :"Wag" }{ "name" :"Bark" }{ " name" :"Fluffy" }

Fjern dubletter

Du kan bruge $group fase for at eliminere overflødige dubletter fra resultatet.

For eksempel returnerede den forrige forespørgsel to kæledyr kaldet Fluffy. Vi kan tilføje en $group trin til den forespørgsel for at eliminere den overflødige duplikat, så kun én Fluffy returneres.

db.cats.aggregate( [
   { $project: { name: 1, _id: 0 } },
   { $unionWith: { coll: "dogs", pipeline: [ { $project: { name: 1, _id: 0 } } ]} },
   { $group: { _id: "$name" } }
] ) 

Resultat:

{ "_id" :"Meow" }{ "_id" :"Bark" }{ "_id" :"Scratch" }{ "_id" :"Wag" }{ "_id" :"Fluffy" } 

Denne gang returneres kun én Fluffy.

Ikke-matchende kolonner

En af fordelene ved MongoDB's $unionWith har over SQL's UNION ALL er, at den kan bruges med ikke-matchende kolonner.

SQL UNION klausul kræver, at:

  • Begge forespørgsler returnerer det samme antal kolonner
  • Kolonnerne i samme rækkefølge
  • De matchende kolonner skal være af en kompatibel datatype

MongoDB $unionWith fase pålægger ikke disse begrænsninger.

Derfor kunne vi bruge $unionWith at gøre noget som dette:

db.cats.aggregate( [
   { $set: { _id: "$_id" } },
   { $unionWith: { coll: "employees", pipeline: [ { $set: { _id: "$_id" } } ] } },
   { $sort: { type: 1, salary: -1 } }
] ) 

Resultat:

{ "_id" :2, "name" :"Sarah", "salary" :128000 }{ "_id" :5, "name" :"Beck", "salary" :82000 }{ "_id" :4, "name" :"Chris", "salary" :45000 }{ "_id" :3, "name" :"Fritz", "salary" :25000 }{ "_id" :1, "name" :"Fluffy ", "type" :"Kat", "vægt" :5 }{ "_id" :2, "name" :"Scratch", "type" :"Kat", "vægt" :3 }{ "_id" :3, "name" :"Mjav", "type" :"Kat", "vægt" :7 }

I dette tilfælde sluttede vi os til cats indsamling med employees kollektion. employees samlingen havde ikke de samme felter som cats indsamling, men det er fint – det virkede stadig.


  1. Hvordan opretter man en lokal Windows-baseret servicebus uden for Azure, der ligner Redis med automatisk fail-over?

  2. Mongo forsøger at oprette forbindelse automatisk til port 27017 (localhost)

  3. The ABCs of NestJS:A Beginner's Guide with MongoDB (Mongoose).

  4. Zookeeper vs In-memory-data-grid vs Redis