MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Trova l'ultimo record di ogni giorno

Un po' più moderno della risposta originale:

db.collection.aggregate([
  { "$sort": { "date": 1 } },
  { "$group": {
    "_id": {
      "$subtract": ["$date",{"$mod": ["$date",86400000]}]
    },
    "doc": { "$last": "$$ROOT" }
  }},
  { "$replaceRoot": { "newDocument": "$doc" } }
])

Si applica lo stesso principio che essenzialmente $sort la raccolta e quindi $group sulla chiave di raggruppamento richiesta raccogliendo $last dati dal confine di raggruppamento.

Rendendo le cose un po' più chiare poiché la scrittura originale è che puoi usare $$ROOT invece di specificare ogni proprietà del documento e, naturalmente, il $replaceRoot stage ti consente di ripristinare i dati completamente come il modulo del documento originale.

Ma la soluzione generale è ancora $sort prima, quindi $group sulla chiave comune richiesta e mantieni il $last o $first a seconda delle occorrenze dell'ordinamento dal limite di raggruppamento per le proprietà richieste.

Anche per le date BSON anziché un valore di timestamp come nella domanda, vedere Risultato del gruppo per intervallo di tempo di 15 minuti in MongoDb per diversi approcci su come accumulare per diversi intervalli di tempo utilizzando effettivamente e restituendo valori BSON Date.

Non sono sicuro di cosa stai cercando qui, ma potresti farlo in aggregato se la mia comprensione è giusta. Quindi, per ottenere l'ultimo record per ogni giorno:

db.collection.aggregate([
    // Sort in date order  as ascending
    {"$sort": { "date": 1 } },

    // Date math converts to whole day
    {"$project": {
        "adco": 1,
        "hchc": 1,
        "hchp": 1,
        "hhphc": 1,
        "ptec": 1,
        "iinst": 1,
        "papp": 1,
        "imax": 1,
        "optarif": 1,
        "isousc": 1,
        "motdetat": 1,
        "date": 1,
        "wholeDay": {"$subtract": ["$date",{"$mod": ["$date",86400000]}]} 
    }},

    // Group on wholeDay ( _id insertion is monotonic )
    {"$group": 
        "_id": "$wholeDay",
        "docId": {"$last": "$_id" },
        "adco": {"$last": "$adco" },
        "hchc": {"$last": "$hchc" },
        "hchp": {"$last": "$hchp" },
        "hhphc": {"$last": "$hhphc" },
        "ptec": {"$last": "$ptec" },
        "iinst": {"$last": "$iinst" },
        "papp": {"$last": "$papp" },
        "imax": {"$last": "$imax" },
        "optarif": {"$last": "$optarif",
        "isousc": {"$last": "$isouc" },
        "motdetat": {"$last": "$motdetat" },
        "date": {"$last": "$date" },
    }}
])

Quindi il principio qui è che, dato il valore del timestamp, fai la matematica della data per proiettarlo come l'ora di mezzanotte all'inizio di ogni giorno. Quindi come _id la chiave sul documento è già monotona (sempre in aumento), quindi raggruppa semplicemente su wholeDay valore mentre si estrae $last documento dal confine di raggruppamento.

Se non hai bisogno di tutti i campi, proietta e raggruppa solo quelli che desideri.

E sì, puoi farlo nel framework dei dati di primavera. Sono sicuro che c'è un comando avvolto lì dentro. Ma per il resto, l'incantesimo per arrivare al comando nativo è più o meno questo:

mongoOps.getCollection("yourCollection").aggregate( ... )

Per la cronaca, se hai effettivamente dei tipi di data BSON anziché un timestamp come numero, puoi saltare la matematica della data:

db.collection.aggregate([
    { "$group": { 
        "_id": { 
            "year": { "$year": "$date" },
            "month": { "$month": "$date" },
            "day": { "$dayOfMonth": "$date" }
        },
        "hchp": { "$last": "$hchp" }
    }}
])