Vấn đề cơ bản với những gì bạn đang hỏi ở đây là do dữ liệu được đề cập nằm trong một "mảng", và do đó, MongoDB đưa ra một số giả định cơ bản về cách xử lý dữ liệu này.
Nếu bạn đã áp dụng sắp xếp theo "thứ tự giảm dần", thì MongoDB sẽ thực hiện chính xác những gì bạn yêu cầu và sắp xếp tài liệu theo giá trị "lớn nhất" của trường được chỉ định trong mảng:
.sort({ "revisions.created": -1 ))
Nhưng thay vào đó, nếu bạn sắp xếp theo thứ tự "tăng dần" thì tất nhiên điều ngược lại là đúng và giá trị "nhỏ nhất" được coi là.
.sort({ "revisions.created": 1 })
Vì vậy, cách duy nhất để làm điều này có nghĩa là tìm ra ngày tối đa từ dữ liệu trong mảng, sau đó sắp xếp theo kết quả đó. Về cơ bản, điều này có nghĩa là áp dụng .aggregate()
, đối với sao băng là một hoạt động phía máy chủ, không may là một cái gì đó như thế này:
Collection.aggregate([
{ "$unwind": "$revisions" },
{ "$group": {
"_id": "$_id",
"name": { "$first": "$name" },
"revisions": { "$push": "$revisions" },
"number": { "$first": "$number" }
"maxDate": { "$max": "$revisions.created" }
}},
{ "$sort": { "maxDate": 1 }
])
Hoặc tốt nhất là với MongoDB 3.2, trong đó $max
có thể được áp dụng trực tiếp cho một biểu thức mảng:
Collection.aggregate([
{ "$project": {
"name": 1,
"revisions": 1,
"number": 1,
"maxDate": {
"$max": {
"$map": {
"input": "$revisions",
"as": "el",
"in": "$$el.created"
}
}
}
}},
{ "$sort": { "maxDate": 1 } }
])
Nhưng thực sự thì cả hai đều không phải là tuyệt vời, ngay cả khi cách tiếp cận MongoDB 3.2 có ít chi phí hơn so với những gì có sẵn cho các phiên bản trước, nó vẫn không tốt như bạn có thể nhận được về mặt hiệu suất do cần phải chuyển qua dữ liệu và làm việc. ra giá trị để sắp xếp.
Vì vậy, để tốt nhất hiệu suất, "luôn luôn" giữ dữ liệu mà bạn sẽ cần "bên ngoài" của mảng. Đối với điều này, có $max
toán tử "update", sẽ chỉ thay thế một giá trị trong tài liệu "nếu" giá trị được cung cấp "lớn hơn" giá trị hiện tại đã có ở đó. tức là:
Collection.update(
{ "_id": "qTF8kEphNoB3eTNRA" },
{
"$push": {
"revisions": { "created": new Date("2016-02-01") }
},
"$max": { "maxDate": new Date("2016-02-01") }
}
)
Điều này có nghĩa là giá trị bạn muốn sẽ "luôn" hiện diện trong tài liệu với giá trị mong đợi, vì vậy việc sắp xếp trên trường đó chỉ là một vấn đề đơn giản:
.sort({ "maxDate": 1 })
Vì vậy, vì tiền của tôi, tôi sẽ sử dụng dữ liệu hiện có với một trong hai .aggregate()
có sẵn các câu lệnh và sử dụng các kết quả đó để cập nhật từng tài liệu để chứa trường "maxDate". Sau đó, thay đổi mã của tất cả các bổ sung và sửa đổi dữ liệu mảng để áp dụng $max
đó "cập nhật" về mọi thay đổi.
Có một trường vững chắc hơn là một phép tính luôn có ý nghĩa hơn nhiều nếu bạn sử dụng nó đủ thường xuyên. Và việc bảo trì khá đơn giản.
Trong mọi trường hợp, xem xét ngày ví dụ được áp dụng ở trên, "nhỏ hơn" các ngày tối đa khác hiện tại sẽ trả lại cho tôi dưới mọi hình thức:
{
"_id" : "5xF9iDTj3reLDKNHh",
"name" : "Lorem ipsum",
"revisions" : [
{
"number" : 0,
"comment" : "Dolor sit amet",
"created" : ISODate("2016-02-11T01:22:45.588Z")
}
],
"number" : 1,
"maxDate" : ISODate("2016-02-11T01:22:45.588Z")
}
{
"_id" : "qTF8kEphNoB3eTNRA",
"name" : "Consecitur quinam",
"revisions" : [
{
"comment" : "Hoste ad poderiquem",
"number" : 1,
"created" : ISODate("2016-02-11T23:25:46.033Z")
},
{
"number" : 0,
"comment" : "Fagor questibilus",
"created" : ISODate("2016-02-11T01:22:45.588Z")
},
{
"created" : ISODate("2016-02-01T00:00:00Z")
}
],
"number" : 2,
"maxDate" : ISODate("2016-02-11T23:25:46.033Z")
}
Điều nào chính xác đặt tài liệu đầu tiên ở đầu thứ tự sắp xếp có cân nhắc đến "Ngày tối đa".