Hiện đại hơn một chút so với câu trả lời ban đầu:
db.collection.aggregate([
{ "$sort": { "date": 1 } },
{ "$group": {
"_id": {
"$subtract": ["$date",{"$mod": ["$date",86400000]}]
},
"doc": { "$last": "$$ROOT" }
}},
{ "$replaceRoot": { "newDocument": "$doc" } }
])
Nguyên tắc tương tự áp dụng về cơ bản bạn $ sort
tập hợp và sau đó là $ group
trên khóa nhóm bắt buộc, chọn mã $ last >
dữ liệu từ ranh giới nhóm.
Làm cho mọi thứ rõ ràng hơn một chút vì văn bản gốc là bạn có thể sử dụng $$ ROOT
thay vì chỉ định mọi thuộc tính tài liệu và tất nhiên là $ ReplaceRoot
giai đoạn cho phép bạn khôi phục dữ liệu đó đầy đủ như ở dạng tài liệu ban đầu.
Nhưng giải pháp chung vẫn là $ sort
trước tiên, sau đó đến $ group
trên khóa chung được yêu cầu và giữ $ last
hoặc $ first
tùy thuộc vào sự xuất hiện của thứ tự sắp xếp từ ranh giới nhóm cho các thuộc tính được yêu cầu.
Ngoài ra đối với Ngày BSON thay vì giá trị dấu thời gian như trong câu hỏi, hãy xem Kết quả nhóm theo khoảng thời gian 15 phút trong MongoDb cho các phương pháp tiếp cận khác nhau về cách tích lũy trong các khoảng thời gian khác nhau thực sự sử dụng và trả về các giá trị Ngày BSON.
Không hoàn toàn chắc chắn bạn sẽ làm gì ở đây nhưng bạn có thể làm điều này tổng thể nếu sự hiểu biết của tôi là đúng. Vì vậy, để có được bản ghi cuối cùng cho mỗi ngày:
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" },
}}
])
Vì vậy, nguyên tắc ở đây là với giá trị dấu thời gian, hãy thực hiện phép toán ngày để dự đoán đó là thời gian nửa đêm vào đầu mỗi ngày. Sau đó là _id
khóa trên tài liệu đã là đơn âm (luôn tăng), sau đó chỉ cần nhóm trên wholeDay
giá trị trong khi kéo $ last
tài liệu từ ranh giới nhóm.
Nếu bạn không cần tất cả các trường thì chỉ chiếu và nhóm trên những trường bạn muốn.
Và có, bạn có thể làm điều này trong khung dữ liệu mùa xuân. Tôi chắc chắn rằng có một lệnh được bao bọc trong đó. Nhưng nếu không, câu thần chú truy cập lệnh gốc sẽ giống như sau:
mongoOps.getCollection("yourCollection").aggregate( ... )
Đối với bản ghi, nếu bạn thực sự có các loại ngày BSON thay vì dấu thời gian dưới dạng số, thì bạn có thể bỏ qua phép toán ngày:
db.collection.aggregate([
{ "$group": {
"_id": {
"year": { "$year": "$date" },
"month": { "$month": "$date" },
"day": { "$dayOfMonth": "$date" }
},
"hchp": { "$last": "$hchp" }
}}
])