/ / MongoDB Project / Aggregate per ottenere tutte le voci degli array dei documenti secondari più recenti - mongodb, mongodb-query, aggregation-framework

MongoDB Project / Aggregate per ottenere tutte le ultime voci di array dei documenti secondari - mongodb, mongodb-query, aggregation-framework

Uso MongoDB per memorizzare i dati di serie storiche con lacune. Ogni documento appartiene a un elemento e contiene le modifiche per diversi punti di misura. Ogni punto di misura ha un id, ho usato il seguente schema id some-id-XXX nell'esempio qui sotto.

L'applicazione scrive solo le modifiche al filedocumento secondario specifico. Quindi esiste la possibilità di lacune nella serie in cui l'APP carica l'intero documento, lo controlla per eventuali modifiche e aggiorna il / i documento / i secondario / i ("some-id-1" per esempio) che ha delle modifiche.

{
"_id": "XXX-DAY_OF_YEAR",
"date": null /* A date used for the TTL index */,
"series" : {
"some-id-1" : [
{
"ts" : 1457959837,
"value" : 385,
"meta" : "some meta info …"
},
{
"ts" : 1457959837,
"value" : 385,
"meta" : "some meta info …"
},
{
"ts" : 1458286255,
"value" : 380,
"meta" : "some meta info …"
},
{
"ts" : 1458346606,
"value" : 375,
"meta" : "some meta info …"
},
{
"ts" : 1458381111,
"value" : 368,
"meta" : "some meta info …"
},
{
"ts" : 1458381461,
"value" : 365,
"meta" : "some meta info …"
},
{
"ts" : 1458606338,
"value" : 385,
"meta" : "some meta info …"
},
{
"ts" : 1458606338,
"expired": true
}
],
"some-id-2" : [
{
"ts" : 1439802083,
"value" : 430,
"meta" : "some meta info …"
}
],
"some-id-42" : [
{
"ts" : 1457545167,
"value" : 518,
"meta" : "some meta info …"
},
{
"ts" : 1458483441,
"value" : 1034,
"meta" : "some meta info …"
},
{
"ts" : 1458518979,
"value" : 518,
"meta" : "some meta info …"
}
],
"some-id-1337" : [
{
"ts" : 1458017854,
"value" : 361,
"meta" : "some meta info …"
},
{
"ts" : 1458050773,
"value" : 384,
"meta" : "some meta info …"
},
{
"ts" : 1458115173,
"value" : 383,
"meta" : "some meta info …"
},
{
"ts" : 1458143968,
"value" : 382,
"meta" : "some meta info …"
},
{
"ts" : 1458176011,
"value" : 381,
"meta" : "some meta info …"
},
{
"ts" : 1458212600,
"value" : 384,
"meta" : "some meta info …"
},
{
"ts" : 1458245285,
"value" : 383,
"meta" : "some meta info …"
},
{
"ts" : 1458277108,
"value" : 382,
"meta" : "some meta info …"
},
{
"ts" : 1458309875,
"value" : 379,
"meta" : "some meta info …"
},
{
"ts" : 1458338258,
"value" : 378,
"meta" : "some meta info …"
},
{
"ts" : 1458374471,
"value" : 374,
"meta" : "some meta info …"
},
{
"ts" : 1458405856,
"value" : 364,
"meta" : "some meta info …"
},
{
"ts" : 1458435330,
"value" : 363,
"meta" : "some meta info …"
},
{
"ts" : 1458471185,
"value" : 362,
"meta" : "some meta info …"
},
{
"ts" : 1458500103,
"value" : 361,
"meta" : "some meta info …"
},
{
"ts" : 1458535837,
"value" : 360,
"meta" : "some meta info …"
},
{
"ts" : 1458568805,
"value" : 364,
"meta" : "some meta info …"
},
{
"ts" : 1458633188,
"value" : 384,
"meta" : "some meta info …"
}
]
}
}

Il problema con questo approccio è il traffico generato caricando l'intero documento, che è necessario per verificare eventuali modifiche o lacune.

Se sarei in grado di recuperare solo il valore più recente (l'ultimo valore nella matrice), il traffico verrebbe ridotto.

{
"series" : {
"some-id-1" : [
{
"ts" : 1458606338,
"expired": true
}
],
"some-id-2" : [
{
"ts" : 1439802083,
"value" : 430,
"meta" : "some meta info …"
}
],
"some-id-42" : [
{
"ts" : 1458518979,
"value" : 518,
"meta" : "some meta info …"
}
],
"some-id-1337" : [
{
"ts" : 1458633188,
"value" : 384,
"meta" : "some meta info …"
}
]
}
}

Finché conosco l'ID posso usare una proiezione per recuperare l'ultima voce recente.

db.Series.find(
{ "series.some-id-42" : { $exists: true } },
{ "series.some-id-42.$": -1}
)

Ma poiché una modifica può contenere lacune, non conosco tutti gli ID presenti nel documento della serie di destinazione.

C'è qualche possibilità di archiviarlo usando il framework di aggregazione o con qualche proiezione intelligente?

La mia unica idea è quella di memorizzare i valori recenti in una forma più compatta e solo progetto {last_recent: 1}:

{
"recent": {
"some-id-1" : 0,
"some-id-2" : 430,
"some-id-42" : 518,
"some-id-1337" : 384
}
"series" : { /* … */ }
}

Ma spero che ci sia una soluzione più elegante per questo problema.

risposte:

0 per risposta № 1

Il problema principale è che stai memorizzando i dati nei nomi dei campi, ovvero l'ID.

Lo schema dovrebbe probabilmente essere:

{
"series": [
{
"id": 1,
"content": [
{
"ts": 1458606338,
"expired": true
}
]
},
{
"id": 2,
"content": [
{
"ts": 1439802083,
"value": 430,
"meta": "some meta info …"
}
]
},
{
"id": 42,
"content": [
{
"ts": 1458518979,
"value": 518,
"meta": "some meta info …"
}
]
},
{
"id": 1337,
"content": [
{
"ts": 1458633188,
"value": 384,
"meta": "some meta info …"
}
]
}
]
}