Để trả lời câu hỏi đầu tiên của bạn:$group
không giữ gìn trật tự. Có một số yêu cầu thay đổi mở cũng làm nổi bật nền một chút nhưng có vẻ như sản phẩm sẽ không được thay đổi để bảo toàn thứ tự của tài liệu đầu vào:
- https://jira.mongodb.org/browse/SERVER-24799
- https://jira.mongodb.org/browse/SERVER-4507
- https://jira.mongodb.org/browse/SERVER-21022
Có thể nói chung hai điều:Bạn thường muốn nhóm trước rồi mới sắp xếp. Lý do là việc sắp xếp các phần tử ít hơn (mà nhóm thường tạo ra) sẽ nhanh hơn so với việc sắp xếp tất cả các tài liệu đầu vào.
Thứ hai, MongoDB sẽ đảm bảo sắp xếp hiệu quả và ít nhất có thể. tài liệu trạng thái:
Vì vậy, mã này hoàn thành công việc trong trường hợp của bạn:
collection.aggregate({
$group: {
_id: '$age',
names: { $push: '$name' }
}
}, {
$sort: {
'_id': 1
}
}, {
$limit: 10
})
CHỈNH SỬA theo dõi nhận xét của bạn:
Tôi đồng ý với những gì bạn nói. Và tiếp cận logic của bạn xa hơn một chút, tôi sẽ đi xa hơn khi nói:Nếu $group
đủ thông minh để sử dụng một chỉ mục thì nó thậm chí không cần phải có $sort
giai đoạn đầu. Thật không may, nó không phải (chưa chắc đã xảy ra). Như ngày nay, $group
sẽ không bao giờ sử dụng chỉ mục và nó sẽ không sử dụng các phím tắt dựa trên các giai đoạn sau ($limit
trong trường hợp này). Đồng thời xem liên kết
này nơi ai đó đã chạy một số thử nghiệm cơ bản.
Khung tổng hợp vẫn còn khá non trẻ nên tôi đoán, còn rất nhiều việc phải làm để làm cho đường ống tổng hợp trở nên thông minh hơn và nhanh hơn.
Có câu trả lời ở đây trên StackOverflow (ví dụ: đây
) nơi mọi người đề xuất sử dụng $sort
trả trước để "buộc" MongoDB sử dụng một chỉ mục bằng cách nào đó. Tuy nhiên, điều này đã làm chậm các thử nghiệm của tôi (1 triệu bản ghi hình dạng mẫu của bạn sử dụng các phân phối ngẫu nhiên khác nhau) đáng kể.
Khi nói đến hiệu suất của một đường ống tổng hợp, hãy $match
giai đoạn đầu là những gì thực sự hữu ích nhất. Nếu bạn có thể giới hạn tổng số lượng bản ghi cần phải xem xét ngay từ đầu thì đó là cách tốt nhất của bạn - rõ ràng là ...;)