MongoDB Academy · Oppitunti

Sisäkkäisten kenttien ja taulukoiden kyselyt

Kirjoitatte piste-notaatiota käyttäviä kyselyjä upotettujen alidokumenttien ja yksittäisten taulukon alkioiden saavuttamiseksi.

Oppitunti 3/413 vaihetta

Sisäkkäisten kenttien ja taulukoiden kyselyt 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.

Miksi sisäkkäisillä kyselyillä on merkitystä

Yksi MongoDB:n keskeisistä vahvuuksista on sisäkkäisten alidokumenttien ja taulukoiden tallentaminen dokumentin sisälle. Tästä ominaisuudesta on kuitenkin hyötyä vain, jos näitä sisäkkäisiä tietoja voi myös kysellä tehokkaasti. MongoDB:n pistemerkinnän avulla voitte käsitellä minkä tahansa syvyystason sisäkkäisiä tietoja suodatusta, projektiota, indeksointia ja tiettyjen kenttien päivittämistä varten.

Ilman tätä ominaisuutta joutuisitte lataamaan kokonaiset dokumentit sovellukseenne ja suodattamaan ne koodissa—mikä kuluttaisi turhaan kaistanleveyttä ja tekisi indekseistä hyödyttömiä. Pistemerkintää käyttävät kyselyt suoritetaan palvelimella, ja ne voivat hyödyntää sisäkkäisten kenttien indeksejä.

Sisäkkäisten kenttien pistemerkintä

Pistemerkinnässä käytetään pistettä (.) sisäkkäisiin alidokumentteihin siirtymiseen. Kysely { 'address.city': 'Chicago' } löytää dokumentit, joissa address-kenttä on objekti, jonka city-kentän arvo on 'Chicago'. Pisteitä voi ketjuttaa mille tahansa syvyydelle: 'address.location.lat'.

Tärkeä sääntö: ympäröikää pistemerkintää käyttävät polut aina lainausmerkeillä, kun niitä käytetään JavaScriptin objektien avaimina (muutoin piste tulkittaisiin ominaisuuden käyttönä). Tämä on yleinen aloittelijoiden virhe.

// Document structure
// { name: 'Alice', address: { city: 'Chicago', state: 'IL' } }

// Correct: dot notation in quotes
db.users.find({ 'address.city': 'Chicago' });

// Incorrect: this queries for a field literally named 'address.city'
// (a common mistake)
db.users.find({ address: { city: 'Chicago' } });
// This requires the address to be EXACTLY { city: 'Chicago' } — no other fields!

// Deep nesting: 3 levels
db.users.find({ 'address.location.lat': { $gt: 41.5 } });

Tarkka alidokumenttiosuma ja pistemerkintä

Alidokumenttien kyselyyn on kaksi tapaa, joiden välillä on tärkeä ero:

  • Tarkka osuma: { address: { city: 'Chicago', state: 'IL' } } — edellyttää, että address-kenttä on täsmälleen kyseinen objekti, jossa ei ole muita kenttiä ja jossa kentät ovat juuri tässä järjestyksessä
  • Pistemerkintä: { 'address.city': 'Chicago' } — löytää kaikki dokumentit, joissa address.city on 'Chicago', riippumatta siitä, mitä muita kenttiä address sisältää

Käytännössä alidokumentteja kyseltäessä kannattaa aina käyttää pistemerkintää. Tarkat alidokumenttiosumat ovat herkkiä muutoksille, ja harvoin tarkoitatte juuri niitä.

// Document: { address: { city: 'Chicago', state: 'IL', zip: '60601' } }

// Exact match - FAILS to find the document (zip field is extra)
db.users.find({ address: { city: 'Chicago', state: 'IL' } });
// Returns 0 results - zip field makes it not an exact match!

// Dot notation - WORKS correctly
db.users.find({ 'address.city': 'Chicago', 'address.state': 'IL' });
// Returns the document regardless of other address fields

Taulukoiden kysely: yhtäsuuruuden tarkistus

Kun taulukkokenttää kysellään yksinkertaisella yhtäsuodatuksella, MongoDB tarkistaa, sisältääkö taulukko arvon—ei sitä, onko taulukko sama kuin arvo. Tämä on yksi MongoDB:n kyselymallin intuitiivisimmista ominaisuuksista.

Jos tuotteella on esimerkiksi tags: ['electronics', '4K', 'HDR'], kysely { tags: '4K' } palauttaa tämän dokumentin, koska taulukko sisältää arvon '4K'. Erityistä operaattoria ei tarvita—taulukon sisältämän arvon tarkistus on taulukkokenttien yhtäsuodattimien oletustoiminta.

// Document: { name: 'Smart TV', tags: ['electronics', '4K', 'HDR'] }

// Query: does tags array contain '4K'?
db.products.find({ tags: '4K' });
// Returns the Smart TV document

// Multiple values: documents where tags contains BOTH values
db.products.find({ tags: { $all: ['4K', 'HDR'] } });
// Returns documents with BOTH '4K' AND 'HDR' in tags

Taulukoiden kysely indeksisijainnin perusteella

Voitte kysellä taulukon tietystä sijainnista käyttämällä pistemerkintää ja taulukon indeksiä: 'arrayField.0' kohdistuu ensimmäiseen alkioon, 'arrayField.1' toiseen ja niin edelleen (indeksointi alkaa nollasta).

Tämä on hyödyllistä, kun taulukon järjestyksellä on merkitystä—esimerkiksi dokumentissa, jossa on scores: [95, 87, 71] ja ensimmäinen pistemäärä on aina tuorein. Voitte suodattaa dokumentit, joissa ensimmäinen pistemäärä ylittää raja-arvon: { 'scores.0': { $gt: 90 } }. Käyttäkää tätä säästeliäästi—sijaintiin perustuvat kyselyt ovat herkkiä muutoksille, jos taulukon järjestys muuttuu.

// Document: { player: 'Alice', scores: [95, 87, 71] }
// Array indices: scores.0 = 95, scores.1 = 87, scores.2 = 71

// Find players whose first (most recent) score > 90
db.players.find({ 'scores.0': { $gt: 90 } });

// Find players whose third score is exactly 71
db.players.find({ 'scores.2': 71 });

Alidokumenttitaulukoiden kysely

Taulukot sisältävät usein alidokumentteja—esimerkiksi tilaussisältö voisi olla items: [{sku:'A1',qty:2},{sku:'B2',qty:1}]. Taulukon alidokumenttien kenttiä kysellään pistemerkinnällä: { 'items.sku': 'A1' } löytää kaikki tilaukset, joissa on tuote, jonka sku on 'A1'.

Tämä voi kuitenkin aiheuttaa vääriä osumia: { 'items.sku': 'A1', 'items.qty': 5 } saattaa löytää dokumentin, jossa sku='A1' ja qty=5 ovat eri taulukkoalkioissa. Jos haluatte edellyttää molempien ehtojen täyttymistä samassa alkiossa, käyttäkää $elemMatch-operaattoria (käsitellään myöhemmässä oppitunnissa).

// Document:
// { orderId: 'ORD-1', items: [ {sku:'A1',qty:2}, {sku:'B2',qty:1} ] }

// Find orders containing sku 'A1' (any array element)
db.orders.find({ 'items.sku': 'A1' });

// Dot notation on nested array field
db.orders.find({ 'items.qty': { $gte: 2 } });
// Returns orders where ANY item has qty >= 2

// Combining two array fields - potential false positive!
db.orders.find({ 'items.sku': 'A1', 'items.qty': { $gte: 5 } });
// Matches even if sku=A1 is one element and qty>=5 is another!

Sisäkkäisten ja taulukkokenttien indeksointi

Sisäkkäisten kenttien ja taulukkokenttien indeksien luominen toimii täsmälleen kuten ylimmän tason kenttien indeksointi—käyttäkää vain pistemerkintää:

  • db.users.createIndex({ 'address.city': 1 }) — sisäkkäisen kentän indeksi
  • db.products.createIndex({ tags: 1 }) — taulukkokentän moniavaiminen indeksi (indeksoi jokaisen alkion erikseen)

MongoDB tunnistaa automaattisesti, että tags on taulukko, ja luo moniavaimisen indeksin. Jokainen taulukon alkio saa oman merkintänsä indeksipuussa. Moniavaimisia indeksejä ei voi käyttää sirpaloidun klusterin sirpaloitavan avaimen (shard key) avaimina, mutta ne toimivat täydellisesti itsenäisten käyttöönottojen ja replikajoukkojen kyselyissä.

// Index a nested field
db.users.createIndex({ 'address.city': 1 });
// Query: { 'address.city': 'Chicago' } now uses the index

// Multikey index on array field
db.products.createIndex({ tags: 1 });
// Query: { tags: '4K' } now uses the index
// Each tag value gets its own B-tree entry

// Compound index combining top-level and nested field
db.orders.createIndex({ customerId: 1, 'shipping.country': 1 });

Sisäkkäisten kenttien projektio

Projektiot toimivat myös pistemerkinnän kanssa, joten voitte palauttaa tiettyjä sisäkkäisiä kenttiä tai taulukon alkioita lataamatta koko dokumenttia. Tämä on erityisen tärkeää, kun dokumentit sisältävät suuria alidokumentteja, joita ette aina tarvitse.

Käyttäkää ilmaisua { 'address.city': 1, 'address.state': 1 }, jos haluatte sisällyttää sisäkkäisestä address-objektista vain kaupungin ja osavaltion. Vastauksessa on edelleen address-objekti, mutta se sisältää vain projektoidut kentät.

// Project only city and state from nested address
db.users.find(
  { 'address.state': 'IL' },
  { name: 1, 'address.city': 1, 'address.state': 1, _id: 0 }
);
// Returns: { name: 'Alice', address: { city: 'Chicago', state: 'IL' } }
// NOT returned: address.zip, address.street, etc.

// Project array field using $slice to limit elements returned
db.posts.find(
  { authorId: userId },
  { title: 1, comments: { $slice: 3 } }  // first 3 comments only
);

Suodatus taulukon pituuden perusteella

Kun haluatte kysellä dokumentteja, joiden taulukkokentässä on tietty määrä alkioita, käyttäkää $size-operaattoria: { tags: { $size: 3 } } löytää dokumentit, joissa tags-taulukossa on täsmälleen 3 alkiota. Huomioikaa, että $size ei toimi vertailuoperaattoreiden kanssa—se täsmää vain tarkkaan määrään.

Kun haluatte löytää dokumentit, joissa taulukossa on vähintään n alkiota, yleinen kiertotapa on käyttää taulukkokentän indeksiä ja suodattaa n:nnen alkion olemassaolon perusteella: { 'tags.2': { $exists: true } } tarkoittaa, että taulukossa on vähintään 3 alkiota (indeksit 0, 1 ja 2).

// Exact array length match
db.products.find({ tags: { $size: 3 } });
// Returns products with exactly 3 tags

// At least 2 elements (index 1 must exist = min length 2)
db.products.find({ 'tags.1': { $exists: true } });

// Array must be empty
db.users.find({ orders: { $size: 0 } });
// OR equivalently:
db.users.find({ orders: [] });

Käytännön esimerkki: tuotekatalogi

Sovelletaan sisäkkäisiä ja taulukoihin kohdistuvia kyselyitä realistiseen tuotekatalogidokumenttiin. Tyypillisellä verkkokaupan tuotteella on sisäkkäisiä teknisiä tietoja ja taulukko luokittelutunnisteita.

Pistemerkinnän ehtojen yhdistäminen vertailuoperaattoreihin mahdollistaa täsmällisten suodattimien rakentamisen, kuten: ”etsi kaikki kannettavat tietokoneet, joita on varastossa, joissa on yli 16 Gt RAM-muistia, jotka tukevat Wi-Fi 6:ta ja jotka kuuluvat premium-luokkaan”—kaikki yhtenä tehokkaana palvelimella suoritettavana kyselynä.

// Sample product document:
// {
//   name: 'UltraBook Pro',
//   category: 'laptops',
//   specs: { ramGB: 32, storageGB: 1000, wifi: 'Wi-Fi 6' },
//   tags: ['premium', 'business', 'ultrabook'],
//   inStock: true
// }

db.products.find({
  category: 'laptops',
  inStock: true,
  'specs.ramGB': { $gte: 16 },
  'specs.wifi': 'Wi-Fi 6',
  tags: 'premium'
});

Sisäkkäisten ja taulukkokenttien päivittäminen

Pistemerkintä ei ole tarkoitettu vain kyselyihin—se toimii myös päivitysoperaattoreissa. Käyttäkää -operaattoria pistemerkinnän kanssa tietyn sisäkkäisen kentän päivittämiseen korvaamatta koko alidokumenttia: { : { 'address.city': 'Boston' } } muuttaa vain kaupungin, ja kaikki muut address-kentät säilyvät ennallaan.

Taulukoissa voitte yhdistää pistemerkinnän ja sijaintiin perustuvan $-operaattorin ensimmäisen suodatinta vastaavan taulukkoalkion päivittämiseen: db.orders.updateOne({ 'items.sku': 'A1' }, { : { 'items.$.qty': 5 } }). Tämä on turvallinen tapa päivittää yksi osuva taulukkoalkio ilman, että sen indeksiä tarvitsee tietää.

// Update a nested field without overwriting sub-document
db.users.updateOne(
  { _id: userId },
  { : { 'address.city': 'Boston' } }
);
// Only address.city changes; address.street, address.zip unchanged

// Positional operator: update matched array element
db.orders.updateOne(
  { 'items.sku': 'A1' },         // Filter matches array element
  { : { 'items.$.qty': 5 } } // $ = first matched element
);
// Updates qty on the item where sku='A1'

Pikatarkistus

Testatkaa, miten hyvin hallitsette tällä oppitunnilla käsitellyt MongoDB:n ja NoSQL-tietokantojen käsitteet.

Oppitunnin yhteenveto

Tässä oppitunnissa opitte seuraavat asiat: pistemerkinnässä käytetään pisteillä erotettuja polkuja, kuten 'address.city', sisäkkäisten alidokumenttikenttien kyselemiseen ja projektioon millä tahansa syvyydellä; taulukoiden yhtäsuuruuskyselyt tarkistavat sisällön—{ tags: '4K' } löytää dokumentin, jos taulukko sisältää arvon '4K' missä tahansa; ja $size täsmää tietynpituisiin taulukoihin, kun taas sijaintiin perustuva indeksointi ('tags.0') kohdistuu tiettyihin taulukon sijainteihin. Seuraavaksi yhdistämme Node.js-komentosarjan MongoDB:hen ja suoritamme lisäys- ja hakuoperaatioita virallisen ajurin avulla.

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 ”Sisäkkäisten kenttien ja taulukoiden kyselyt” ilmainen?

Kyllä – oppitunnin ”Sisäkkäisten kenttien ja taulukoiden kyselyt” 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 ”Sisäkkäisten kenttien ja taulukoiden kyselyt”?

Kirjoitatte piste-notaatiota käyttäviä kyselyjä upotettujen alidokumenttien ja yksittäisten taulukon alkioiden saavuttamiseksi. 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 ”Sisäkkäisten kenttien ja taulukoiden kyselyt”-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. insertOne ja insertMany
  2. findOne ja find: kursorit selitettynä
  3. Sisäkkäisten kenttien ja taulukoiden kyselyt
  4. Dokumenttien lukeminen Node.js-ajurilla
← Takaisin: MongoDB Academy