sql >> Databáze >  >> NoSQL >> MongoDB

$unionWith – MongoDB je ekvivalent UNION ALL

Pokud jste obeznámeni s SQL, možná znáte UNION klauzule, která zřetězí výsledky dvou dotazů do jediné sady výsledků. Konkrétně UNION ALL zahrnuje duplikáty.

V MongoDB můžeme použít $unionWith agregační fáze potrubí k dosažení stejného efektu jako UNION ALL vyrábí. $unionWith stage provádí spojení dvou kolekcí – kombinuje výsledky z potrubí ze dvou kolekcí do jediné sady výsledků. A zahrnuje duplikáty.

Příklad

Předpokládejme, že vytvoříme dvě kolekce; jeden s názvem cats a další s názvem dogs . A vložíme do nich následující dokumenty:

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 }
    ]) 

Nyní můžeme spustit dotazy na tyto kolekce a použít $unionWith fázi ke kombinaci výsledků každého dotazu.

Příklad:

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

Výsledek:

{ "_id" :3, "name" :"Mňau", "type" :"Kočka", "váha" :7 }{ "_id" :1, "name" :"Fluffy", "type" :"Kočka", "váha" :5 }{ "_id" :2, "jméno" :"Scratch", "type" :"Kočka", "váha" :3 }{ "_id" :3, "jméno" :"Fluffy", "type" :"Pes", "váha" :40 }{ "_id" :1, "name" :"Wag", "type" :"Pes", "váha" :20 }{ " _id" :2, "name" :"Štěkání", "type" :"Pes", "váha" :10 }

V tomto příkladu má každý dokument pole typu s buď cat nebo dog a tak je zcela zřejmé, který dokument pochází z které sbírky.

Pokud by však dokumenty neměly pole typu, bylo by těžší zjistit, kde jedna kolekce končí a druhá začíná. V tomto případě můžeme použít řetězcový literál v $set fázi reprezentující název kolekce.

Příklad:

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

Výsledek:

{ "_id" :"cat", "name" :"Mňau", "type" :"Kočka", "váha" :7 }{ "_id" :"cat", "name" :"Fluffy" , "type" :"Kočka", "váha" :5 }{ "_id" :"kočka", "jméno" :"Scratch", "type" :"Kočka", "váha" :3 }{ "_id" :"pes", "name" :"Fluffy", "type" :"Pes", "váha" :40 }{ "_id" :"pes", "name" :"Wag", "type" :"Pes" ", "váha" :20 }{ "_id" :"pes", "jméno" :"Štěkání", "typ" :"Pes", "váha" :10 }

Řazení napříč kolekcemi

V předchozích příkladech byli kočky a psi roztříděni způsobem, který je rozděloval do dvou odlišných skupin; nejprve kočky, pak psi. Stalo se to hlavně proto, že jsme třídili podle type pole jako první.

Ale můžeme to třídit na jakémkoli jiném poli, což by mohlo vést ke spojení koček a psů.

Příklad:

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

Výsledek:

{ "_id" :"pes", "name" :"Štěkání", "type" :"Pes", "váha" :10 }{ "_id" :"kočka", "jméno" :"Načechraný" , "type" :"Kočka", "váha" :5 }{ "_id" :"pes", "name" :"Fluffy", "type" :"Pes", "váha" :40 }{ "_id" :"kočka", "jméno" :"Mňau", "typ" :"Kočka", "váha" :7 }{ "_id" :"kočka", "jméno" :"Scratch", "type" :"Kočka ", "váha" :3 }{ "_id" :"pes", "name" :"Wag", "type" :"Pes", "váha" :20 }

Projekce

Můžete použít $project fázi k určení, která pole mají být předána do další fáze v potrubí. Můžete tak například snížit počet polí vrácených dotazem.

Příklad:

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

Výsledek:

{ "name" :"Fluffy" }{ "name" :"Scratch" }{ "name" :"Mňau" }{ "name" :"Wag" }{ "name" :"Bark" }{ " jméno" :"Načechraný" }

Odstranit duplikáty

Můžete použít $group fázi k odstranění nadbytečných duplikátů z výsledku.

Například předchozí dotaz vrátil dva mazlíčky s názvem Fluffy. Můžeme přidat $group fázi k tomuto dotazu, abyste odstranili nadbytečný duplikát, takže je vrácen pouze jeden Fluffy.

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

Výsledek:

{ "_id" :"Mňau" }{ "_id" :"Štěkat" }{ "_id" :"Škrábnutí" }{ "_id" :"Wag" }{ "_id" :"Načechraný" } 

Tentokrát je vrácen pouze jeden Fluffy.

Neodpovídající sloupce

Jedna z výhod MongoDB $unionWith má více než SQL UNION ALL je, že jej lze použít s neodpovídajícími sloupci.

SQL UNION klauzule vyžaduje, aby:

  • Oba dotazy vracejí stejný počet sloupců
  • Sloupce ve stejném pořadí
  • Odpovídající sloupce musí mít kompatibilní datový typ

MongoDB $unionWith fáze tato omezení neukládá.

Proto bychom mohli použít $unionWith udělat něco takového:

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

Výsledek:

{ "_id" :2, "jméno" :"Sarah", "plat" :128000 }{ "_id" :5, "jméno" :"Beck", "plat" :82000 }{ "_id" :4, "jméno" :"Chris", "plat" :45000 }{ "_id" :3, "jméno" :"Fritz", "plat" :25000 }{ "_id" :1, "jméno" :"Fluffy ", "type" :"Kočka", "váha" :5 }{ "_id" :2, "name" :"Scratch", "type" :"Kočka", "váha" :3 }{ "_id" :3, "jméno" :"Mňau", "typ" :"Kočka", "váha" :7 }

V tomto případě jsme se připojili k cats sběr s employees sbírka. employees kolekce neměla stejná pole jako cats kolekce, ale to je v pořádku – stále to fungovalo.


  1. Mongoose JS findOne vždy vrátí hodnotu null

  2. Mongoose nevytváří indexy

  3. MongoDB $indexOfBytes

  4. mongo.so:> nedefinovaný symbol:php_json_encode v Neznámý na řádku 0. Po instalaci ovladače mongo pro php