MongoDB Academy · Oppitunti

$- ja $elemMatch-taulukkoprojektiot

Palautatte vain ensimmäisen täsmäävän taulukkoalkion tai suodatetun alitaulukon käyttämällä $- ja $elemMatch-projektioita.

Oppitunti 3/413 vaihetta

$- ja $elemMatch-taulukkoprojektiot on ilmainen MongoDB Academy-oppitunti CoddyKitissä. Tämä on oppitunti 3/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu MongoDB Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. MongoDB Academy-kurssilla on yhteensä 4 oppituntia.

Ongelma: vain yhden taulukkoalkion palauttaminen

Joskus kysely löytää dokumentin taulukkoalkion perusteella – esimerkiksi tilauksen, joka sisältää tietyn tuotteen – mutta haluat palauttaa vain täsmäävän taulukkoalkion, et koko taulukkoa. Tavallinen sisällytysprojektio palauttaa kaikki taulukon alkiot. MongoDB tarjoaa tähän kaksi erityistä taulukon projektio-operaattoria: paikallaan olevan $-operaattorin ja operaattorin $elemMatch.

Paikallaan oleva $-operaattori

Paikallaan oleva $-projektio-operaattori palauttaa taulukon ensimmäisen alkion, joka vastaa kyselyn ehtoa. Se sijoitetaan projektioon kohtaan, jossa taulukon kentän nimi tavallisesti olisi. Suodattimessa käytetty täsmäävä ehto määrittää automaattisesti projisoitavan alkion. Yhdessä projektiossa voi esiintyä vain yksi $.

// Find the order and return only the matching line item
db.orders.findOne(
  { 'items.productId': ObjectId('p1') },
  { projection: { 'items.$': 1 } }
);
// Result: { _id: ..., items: [{ productId: ObjectId('p1'), qty: 2, price: 9.99 }] }
// Only the FIRST matching element is returned

Miten $ vastaa suodatusehtoa

$-operaattori käyttää kyselyn taulukkokenttää koskevaa suodatusehtoa määrittääkseen palautettavan alkion. Kyselyn suodattimen on sisällettävä ehto samalle taulukkokentälle, joka esiintyy projektiossa. Jos suodatin täsmää useaan alkioon, palautetaan vain ensimmäinen täsmäävä alkio taulukon järjestyksessä. Tämä on tärkeä rajoitus, joka on syytä muistaa.

// Filter on items.qty, project only that matching item
db.orders.find(
  { 'items.qty': { $gt: 1 } },
  { projection: { 'items.$': 1, total: 1 } }
);
// Returns the first item in the items array where qty > 1
// If multiple items have qty > 1, only the first one is projected

$-operaattorin rajoitukset

$-sijaintioperaattorilla on kaksi keskeistä rajoitusta: (1) se palauttaa vain ensimmäisen täsmäävän alkion, vaikka suodatusehdot täyttäisi useampi alkio; (2) taulukon kentän on oltava mukana kyselysuodattimessa (et voi projisoida $-operaattorilla kenttää, joka ei ollut osa suodatusehtoa). Jos täsmäytykseen tarvitaan useita ehtoja tai alkioita, käytä projektiossa $elemMatch-operaattoria.

<code>$elemMatch</code>-projektio-operaattori

Projektiossa käytetty $elemMatch palauttaa vain ensimmäisen määritetyt ehdot täyttävän taulukkoalkion, samalla tavoin kuin $-operaattori, mutta yhdellä keskeisellä erolla: suodatusehdot määritetään suoraan projektiossa, ei kyselysuodattimessa. Näin voit projisoida taulukosta täsmäävän alkion, vaikka pääkysely käyttäisi eri ehtoja.

// Find all orders, but from the items array return only the item with qty > 1
db.orders.find(
  { status: 'shipped' },  // main filter on a different field
  {
    projection: {
      total: 1,
      items: { $elemMatch: { qty: { $gt: 1 } } }  // array filter in projection
    }
  }
);
// items array is present only if an element matches; absent if none match

$ vs $elemMatch: keskeinen ero

Keskeinen ero:

  • $ projektiossa: täsmäytysehto tulee kyselysuodattimesta. Taulukon kentän on oltava mukana suodattimessa.
  • $elemMatch projektiossa: kirjoitat erillisen ehdon suoraan projektioon. Pääsuodatin voi kohdistua mihin tahansa kenttään.
Molemmat palauttavat vain ensimmäisen täsmäävän alkion. Käytä $-operaattoria, kun suodatusehto kohdistuu jo taulukon kenttään. Käytä $elemMatch-projektiota, kun tarvitset eri ehdon tai suodatin kohdistuu toiseen kenttään.

$elemMatch useilla ehdoilla

Projektiossa käytetty $elemMatch voi soveltaa useita ehtoja taulukon alidokumenttiin. Kaikkien ehtojen on täytyttävä samassa taulukkoalkiossa. Tämä on tärkeää alidokumenttien yhteydessä: ilman $elemMatch-operaattoria MongoDB arvioi ehdot eri alkioiden välillä, mikä voi tuottaa virheellisiä osumia.

// From orders, return only items where qty > 1 AND price < 20
db.orders.find(
  { status: 'delivered' },
  {
    projection: {
      items: {
        $elemMatch: {
          qty: { $gt: 1 },
          price: { $lt: 20 }
        }
      }
    }
  }
);
// Both conditions must match the SAME array element

Puuttuva taulukkokenttä, kun mikään alkio ei täsmää

Kun käytät $elemMatch-operaattoria projektiossa eikä yksikään taulukkoalkio täytä ehtoa, taulukon kenttä puuttuu kokonaan tulosdokumentista (sitä ei palauteta tyhjänä taulukkona). Sovelluskoodin on siis käsiteltävä tilanne, jossa projisoitu taulukkokenttä voi olla undefined. Tarkista aina kentän olemassaolo ennen sen alkioiden käyttämistä.

const order = await db.collection('orders').findOne(
  { status: 'shipped' },
  { projection: { items: { $elemMatch: { qty: { $gt: 100 } } } } }
);

// Safe access — items may be absent if no element matched
const matchedItem = order.items ? order.items[0] : null;
console.log('Matched item:', matchedItem);

$elemMatchin yhdistäminen muihin projektioihin

Voit yhdistää $elemMatch-taulukkoprojektion tavallisiin kenttäprojektioihin samassa kyselyssä. Projisoi skalaarikentät tavallista sisällyttämissyntaksia käyttäen ja käytä $elemMatch-operaattoria vain taulukkokentässä. Muista sekoittamista koskeva sääntö: kaikkien muiden kuin taulukkokenttien on käytettävä samaa tilaa (sisällyttämistä tai poissulkemista).

// Project total and status (inclusion) + first matching item
db.orders.findOne(
  { customerId: ObjectId('c1') },
  {
    projection: {
      total: 1,
      status: 1,
      _id: 0,
      items: { $elemMatch: { qty: { $gt: 0 } } }
    }
  }
);

$elemMatch kyselysuodattimessa vs. projektiossa

Älä sekoita keskenään kyselysuodattimessa olevaa $elemMatch-operaattoria (joka valitsee dokumentit) ja projektiossa olevaa $elemMatch-operaattoria (joka valitsee palautettavan alkion). Suodatinmuoto määrittää, mitkä dokumentit palautetaan, kun taas projektiomuoto määrittää, mitkä taulukkoalkiot näissä dokumenteissa näkyvät. Niitä käytetään usein yhdessä, mutta niiden tarkoitukset ovat erilaiset.

// $elemMatch in FILTER: find orders containing a specific item
db.orders.find({
  items: { $elemMatch: { productId: ObjectId('p1'), qty: { $gt: 1 } } }
});

// $elemMatch in PROJECTION: from all shipped orders, return only that matching item
db.orders.find(
  { status: 'shipped' },
  { projection: { items: { $elemMatch: { productId: ObjectId('p1'), qty: { $gt: 1 } } } } }
);

Käytännön esimerkki: käyttäjien pisteet

Pelien pistetaulukon dokumentti tallentaa pelaajan kaikki pisteet upotettuun taulukkoon. Kun näytät pelaajan pisteet tietyssä pelissä, tarvitset vain kyseisen pelin pistealkion, et koko pistehistoriaa. Projektiossa käytetty $elemMatch kohdistaa haun juuri tähän alkioon, joten vastaus pysyy pienenä, vaikka pelaajalla olisi tallennettuna tuhansien pelien pisteet.

db.players.find(
  { username: 'gamer42' },
  {
    projection: {
      username: 1,
      scores: { $elemMatch: { gameId: 'chess_blitz' } },
      _id: 0
    }
  }
);
// Result: { username: 'gamer42', scores: [{ gameId: 'chess_blitz', score: 1540 }] }

Pikatarkistus

Testaa, miten hyvin ymmärrät tämän oppitunnin MongoDB- ja NoSQL-tietokantoihin liittyvät käsitteet.

Oppitunnin yhteenveto

Tässä oppitunnissa opit, että $-sijaintioperaattori palauttaa ensimmäisen kyselysuodattimen ehdon täyttävän alkion, projektiossa käytetyn $elemMatch-operaattorin avulla täsmäytysehdot voi määrittää kyselysuodattimesta riippumatta ja jos mikään alkio ei täsmää $elemMatch-operaattorin ehtoihin, kenttä puuttuu tuloksesta. Seuraavaksi tarkastelemme projektioiden parhaita käytäntöjä API-vastauksissa.

Aloita maksutta

Opi JavaScript tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
30
Oppitunnit
120

Usein kysytyt kysymykset

Onko oppitunti ”$- ja $elemMatch-taulukkoprojektiot” ilmainen?

Kyllä – oppitunnin ”$- ja $elemMatch-taulukkoprojektiot” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko MongoDB Academy-kurssin, päivitä CoddyKit PROhon. MongoDB Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”$- ja $elemMatch-taulukkoprojektiot”?

Palautatte vain ensimmäisen täsmäävän taulukkoalkion tai suodatetun alitaulukon käyttämällä $- ja $elemMatch-projektioita. Harjoittelet MongoDB Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni MongoDB Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin MongoDB Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 3/4.

Kuinka kauan ”$- ja $elemMatch-taulukkoprojektiot”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä MongoDB Academy-oppitunnilla?

Kyllä. Jokainen MongoDB Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Sisällytys- ja poissulkemisprojektiot
  2. Sisäkkäisten ja taulukkokenttien projisointi
  3. $- ja $elemMatch-taulukkoprojektiot
  4. Projektioiden parhaat käytännöt API-vastauksissa
← Takaisin: MongoDB Academy