MongoDB Academy · Oppitunti

Aikasarjadatan lisääminen ja kyselyt

Oppijat lisäävät mittauseriä ja tekevät niihin kyselyitä aikaväli- ja metadatakenttien suodattimilla.

Oppitunti 2/413 vaihetta

Aikasarjadatan lisääminen ja kyselyt on ilmainen MongoDB Academy-oppitunti CoddyKitissä. Tämä on oppitunti 2/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.

Mittausten lisääminen aikasarjoihin

Aikasarjakokoelmaan lisääminen käyttää täsmälleen samoja insertOne()- ja insertMany()-metodeja kuin tavallisiin kokoelmiin lisääminen. MongoDB tarkistaa timeField-kentän (jonka on oltava BSON Date) ja metaField-kentän sijoittaakseen mittauksen oikeaan sisäiseen bucketiin. Lisäys-API on tarkoituksella samanlainen, joten olemassa oleva sovelluskoodi vaatii vain vähäisiä muutoksia aikasarjakokoelmia käyttöön otettaessa.

const now = new Date()

db.sensorReadings.insertOne({
  timestamp: now,
  sensorId: 'sensor-42',
  temperature: 23.1,
  humidity: 58.4,
  batteryLevel: 87
})

Historiallisten tietojen massalisäys

Kun lataat historiallisia mittauksia, käytä aina mieluummin insertMany()-metodia kuin toistuvia insertOne()-kutsuja. MongoDB voi niputtaa datan bucketeihin huomattavasti tehokkaammin massatoiminnoilla. Erittäin suurissa aineistoissa (miljoonissa riveissä) kannattaa käyttää mongoimport-työkalua tai Node.js-ajurin bulkWrite()-metodia ja ryhmitellä insertOne-operaatiot 1 000–5 000 dokumentin eriin.

const readings = []
const base = new Date('2024-06-01T00:00:00Z')

for (let i = 0; i < 1440; i++) {
  readings.push({
    timestamp: new Date(base.getTime() + i * 60000),
    sensorId: 'sensor-42',
    temperature: 20 + Math.random() * 5,
    humidity: 50 + Math.random() * 20
  })
}

db.sensorReadings.insertMany(readings)

Aikavälikyselyiden perusteet

Yleisin aikasarjadataa koskeva kyselymalli on aikavälisuodatin, joka kohdistetaan timeField-kenttään $gte- ja $lte-operaattoreilla. MongoDB käyttää sisäisten bucketien rajoja ohittaakseen kokonaiset pyydetyn aikavälin ulkopuolelle jäävät bucketit, mikä parantaa suorituskykyä huomattavasti jokaiseen dokumenttiin kohdistuvaan läpikäyntiin verrattuna. Sisällytä aikasuodatin aina suurten aikasarjakokoelmien kyselyihin.

// Last 1 hour of readings from one sensor
const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000)

db.sensorReadings.find({
  sensorId: 'sensor-42',
  timestamp: { $gte: oneHourAgo }
}).sort({ timestamp: 1 })

// Specific day range
db.sensorReadings.find({
  timestamp: {
    $gte: new Date('2024-06-01T00:00:00Z'),
    $lt:  new Date('2024-06-02T00:00:00Z')
  }
})

Metatietokenttien perusteella suodattaminen

metaField-kentän perusteella suodattaminen on erittäin hyvin optimoitu — MongoDB tallentaa meta-arvon bucket-tasolla ja voi ohittaa kokonaiset muille aikasarjoille kuuluvat bucketit tutkimatta yksittäisiä mittauksia. Siksi esimerkiksi kyselyt, jotka hakevat sensor-42:n kaikki lukemat viimeisten kuuden tunnin ajalta, ovat erittäin nopeita jopa kokoelmissa, joissa on miljardeja tuhansien antureiden mittauksia.

// Query a specific device
db.sensorReadings.find({
  sensorId: 'sensor-42',
  timestamp: { $gte: new Date('2024-06-01T00:00:00Z') }
})

// Query multiple devices using $in on the metaField
db.sensorReadings.find({
  sensorId: { $in: ['sensor-42', 'sensor-43', 'sensor-44'] },
  timestamp: { $gte: new Date('2024-06-01T00:00:00Z') }
})

Aikasarjojen aggregointi $match- ja $group-operaatioilla

Aggregointiputki on ensisijainen työkalu aikasarjadatan tilastojen laskemiseen. Tyypillisessä mallissa käytetään ensin $match-operaatiota aikavälin ja metaField-kentän perusteella, jotta MongoDB voi ohittaa tarpeettomat bucketit, ja sen jälkeen $group-operaatiota keskiarvojen, minimiarvojen ja maksimiarvojen laskemiseen. Sijoita $match aina ensimmäiseksi vaiheeksi, jotta bucketien karsinta voidaan ottaa käyttöön.

// Average temperature per hour for one sensor
db.sensorReadings.aggregate([
  {
    $match: {
      sensorId: 'sensor-42',
      timestamp: { $gte: new Date('2024-06-01T00:00:00Z') }
    }
  },
  {
    $group: {
      _id: {
        year:  { $year: '$timestamp' },
        month: { $month: '$timestamp' },
        day:   { $dayOfMonth: '$timestamp' },
        hour:  { $hour: '$timestamp' }
      },
      avgTemp: { $avg: '$temperature' },
      maxTemp: { $max: '$temperature' },
      minTemp: { $min: '$temperature' }
    }
  },
  { $sort: { '_id.hour': 1 } }
])

$dateTrunc-arvon käyttäminen aikabucketeihin

$dateTrunc-aggregointilauseke (lisätty MongoDB 5.0:ssa) helpottaa mittausten ryhmittelyä kiinteän levyisiin aikaikkunoihin. Se katkaisee päivämäärän lähimpään yksikkörajaan — esimerkiksi arvon katkaiseminen arvoon 'hour' ryhmittelee saman tunnin kaikki mittaukset saman avaimen alle. Tämä korvaa monisanaisen päivämäärän eri osien poimimiseen perustuvan lähestymistavan.

// Group readings into 15-minute windows
db.sensorReadings.aggregate([
  {
    $match: {
      sensorId: 'sensor-42',
      timestamp: { $gte: new Date('2024-06-01T00:00:00Z') }
    }
  },
  {
    $group: {
      _id: {
        $dateTrunc: {
          date: '$timestamp',
          unit: 'minute',
          binSize: 15
        }
      },
      avgTemp: { $avg: '$temperature' },
      count:   { $sum: 1 }
    }
  },
  { $sort: { _id: 1 } }
])

Aikasarjatulosten projisointi

Käytä projektiota rajoittamaan aikasarjakyselyistä palautettavia kenttiä aivan kuten tavallisissa kokoelmissa. Vain tarvittavien kenttien projisointi vähentää verkkosiirron määrää ja asiakkaan muistinkulutusta. Huomaa, että timeField- ja metaField-kentät ovat aina käytettävissä projisointiin ja _id-kentän voi piilottaa arvolla _id: 0.

// Return only timestamp and temperature
db.sensorReadings.find(
  {
    sensorId: 'sensor-42',
    timestamp: { $gte: new Date('2024-06-01T08:00:00Z') }
  },
  {
    _id: 0,
    timestamp: 1,
    temperature: 1
  }
).sort({ timestamp: 1 })

Mittausten laskeminen ja otanta

Laske aikavälin mittaukset käyttämällä countDocuments()-metodia suodattimen kanssa. Suurissa kokoelmissa estimatedDocumentCount() antaa nopean likimääräisen kokonaismäärän kokoelman metatietojen perusteella. Kun korjaat virheitä tai rakennat koontinäyttöjä, aggregointiputken $sample-operaatiolla voit hakea satunnaisen osajoukon mittauksista ilman koko tulosjoukon läpikäyntiä.

// Count readings in last 24 hours
const since = new Date(Date.now() - 86400000)
db.sensorReadings.countDocuments({
  sensorId: 'sensor-42',
  timestamp: { $gte: since }
})

// Random sample of 10 recent measurements
db.sensorReadings.aggregate([
  { $match: { timestamp: { $gte: since } } },
  { $sample: { size: 10 } }
])

Node.js-ajuri: aikasarjadatan lukeminen

Node.js-sovelluksessa aikasarjakokoelmien kyselyt tehdään samalla tavalla kuin tavallisten kokoelmien kyselyt. Käytä kokoelmaobjektin tavallisia find()- tai aggregate()-metodeja. Koska aikasarjakyselyt palauttavat usein suuria tulosjoukkoja, käytä kursorin kanssa async-iteraatiota sen sijaan, että lataisit kaiken muistiin toArray()-metodilla.

const { MongoClient } = require('mongodb')

async function getRecentReadings(client) {
  const db = client.db('iot')
  const col = db.collection('sensorReadings')
  const since = new Date(Date.now() - 3600000)  // last hour

  const cursor = col.find(
    { sensorId: 'sensor-42', timestamp: { $gte: since } },
    { projection: { _id: 0, timestamp: 1, temperature: 1 } }
  ).sort({ timestamp: 1 })

  for await (const doc of cursor) {
    console.log(doc.timestamp, doc.temperature)
  }
}

Suorituskyky: miksi aikaväli käsitellään ensin

Aikasarjadatan kyselyiden tärkein sääntö on: suodata aina aikavälin perusteella ennen muita ehtoja. MongoDB:n bucketien karsinta aktivoituu vain, kun timeField-kentän suodatin sisältyy kyselyyn. Ilman sitä MongoDB joutuu käymään läpi jokaisen bucketin. Yhdistä lisäksi aikasuodatin metaField-suodattimeen, jotta voit hyödyntää molempia bucketien ohitusmenetelmiä — aikarajoja ja aikasarjan tunnistetta.

// GOOD: time + meta filter — fast bucket pruning
db.sensorReadings.find({
  sensorId: 'sensor-42',       // prune by series
  timestamp: { $gte: since },  // prune by time
  temperature: { $gt: 30 }     // measurement filter applied after pruning
})

// BAD: no time filter — scans all buckets
db.sensorReadings.find({
  temperature: { $gt: 30 }     // forces full scan
})

Bucketien käyttöasteen seuranta

Voit tarkastella sisäisiä bucket-dokumentteja järjestelmän nimiavaruuden kautta: system.buckets.<collectionName>. Vaikka tähän nimiavaruuteen ei voi kirjoittaa suoraan, sen lukeminen paljastaa bucketien määrän ja sen, kuinka monta mittausta kukin bucket sisältää. Tämä on hyödyllistä granularity-asetusta säädettäessä — ihannetapauksessa jokaisen bucketin tulisi olla lähellä enimmäistäyttöastetta (3 600 mittausta 'seconds'-granularitylla).

// Count internal bucket documents
db['system.buckets.sensorReadings'].countDocuments()

// Inspect a sample bucket (internal format)
db['system.buckets.sensorReadings'].findOne()

Pikatarkistus

Testaa ymmärryksesi tämän oppitunnin MongoDB- ja NoSQL-tietokantoja koskevista käsitteistä.

Oppitunnin yhteenveto

Tässä oppitunnissa opit, että insertMany() erissä käytettynä on tehokas tapa ladata aikasarjadataa, timeField- ja metaField-kenttien perusteella yhdessä suodattaminen mahdollistaa bucketien karsimisen nopeissa aikavälikyselyissä ja $dateTrunc aggregointiputkissa helpottaa mittausten ryhmittelyä kiinteän levyisiin aikaikkunoihin. Seuraavaksi tutustumme aikasarjojen ikkuna-aggregointeihin $setWindowFields-operaation 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 ”Aikasarjadatan lisääminen ja kyselyt” ilmainen?

Kyllä – oppitunnin ”Aikasarjadatan lisääminen ja 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 ”Aikasarjadatan lisääminen ja kyselyt”?

Oppijat lisäävät mittauseriä ja tekevät niihin kyselyitä aikaväli- ja metadatakenttien suodattimilla. 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 2/4.

Kuinka kauan ”Aikasarjadatan lisääminen ja 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. Aikasarjakokoelman luominen
  2. Aikasarjadatan lisääminen ja kyselyt
  3. Ikkunakoostaminen aikasarjoille
  4. Datan automaattinen vanhentaminen expireAfterSeconds-asetuksella
← Takaisin: MongoDB Academy