MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Encontre o último registro de cada dia


Um pouco mais moderno que a resposta original:
db.collection.aggregate([
  { "$sort": { "date": 1 } },
  { "$group": {
    "_id": {
      "$subtract": ["$date",{"$mod": ["$date",86400000]}]
    },
    "doc": { "$last": "$$ROOT" }
  }},
  { "$replaceRoot": { "newDocument": "$doc" } }
])

O mesmo princípio se aplica a você essencialmente $sort a coleção e, em seguida, $group na chave de agrupamento necessária, pegando o $last dados do limite de agrupamento.

Tornando as coisas um pouco mais claras, já que a escrita original é que você pode usar $$ROOT em vez de especificar cada propriedade do documento e, claro, o $replaceRoot stage permite que você restaure esses dados totalmente como o formulário do documento original.

Mas a solução geral ainda é $sort primeiro, depois $group na chave comum necessária e mantenha o $last ou $first dependendo das ocorrências de ordem de classificação do limite de agrupamento para as propriedades necessárias.

Também para datas BSON em vez de um valor de carimbo de data/hora como na pergunta, consulte Resultado do grupo por intervalo de tempo de 15 minutos no MongoDb para diferentes abordagens sobre como acumular para diferentes intervalos de tempo realmente usando e retornando valores de data BSON.

Não tenho certeza do que você está procurando aqui, mas você pode fazer isso de forma agregada, se meu entendimento estiver correto. Então, para obter o último registro para cada dia:
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" },
    }}
])

Portanto, o princípio aqui é que, dado o valor do carimbo de data/hora, faça a matemática da data para projetar isso como a hora da meia-noite no início de cada dia. Então, como _id key no documento já é monotônico (sempre crescente), então simplesmente agrupe no wholeDay valor ao puxar o $last documento do limite de agrupamento.

Se você não precisar de todos os campos, apenas projete e agrupe os que deseja.

E sim, você pode fazer isso na estrutura de dados da primavera. Tenho certeza de que há um comando encapsulado lá. Mas, caso contrário, o encantamento para chegar ao comando nativo é algo assim:
mongoOps.getCollection("yourCollection").aggregate( ... )

Para o registro, se você realmente tinha tipos de data BSON em vez de um carimbo de data/hora como um número, você pode pular a matemática de datas:
db.collection.aggregate([
    { "$group": { 
        "_id": { 
            "year": { "$year": "$date" },
            "month": { "$month": "$date" },
            "day": { "$dayOfMonth": "$date" }
        },
        "hchp": { "$last": "$hchp" }
    }}
])