2012-09-20 33 views
21

Tôi có một truy vấn trong mongo sao cho tôi muốn ưu tiên cho trường đầu tiên và sau đó là trường thứ hai.Sắp xếp trên nhiều trường mongo DB

Giả sử tôi có để truy vấn như vậy

db.col.find({category: A}).sort({updated: -1, rating: -1}).limit(10).explain() 

Vì vậy, tôi đã tạo ra index sau

db.col.ensureIndex({category: 1, rating: -1, updated: -1}) 

Nó làm việc quét chỉ bị xử phạt như nhiều đối tượng khi cần thiết tức là 10

Nhưng bây giờ tôi cần truy vấn

db.col.find({category: { $ne: A}}).sort({updated: -1, rating: -1}).limit(10) 

Vì vậy, tôi đã tạo ra index sau

db.col.ensureIndex({rating: -1, updated: -1}) 

nhưng điều này dẫn đến quét toàn bộ tài liệu và khi tôi tạo

db.col.ensureIndex({ updated: -1 ,rating: -1}) 

Nó quét ít số tài liệu

Tôi chỉ muốn hỏi phải rõ ràng về việc sắp xếp trên nhiều trường và thứ tự được giữ gìn khi làm như vậy. Bằng cách đọc tài liệu mongo-DB, rõ ràng rằng trường mà chúng ta cần thực hiện sắp xếp phải là trường cuối cùng. Vì vậy, đó là trường hợp tôi giả định trong truy vấn $ ne của tôi ở trên. Tôi có làm gì sai không?

Trả lời

25

MongoDB query optimizer hoạt động bằng cách thử các kế hoạch khác nhau để xác định phương pháp nào hoạt động tốt nhất cho một truy vấn nhất định. Kế hoạch chiến thắng cho mẫu truy vấn đó sau đó được lưu trong bộ nhớ cache cho ~ 1.000 truy vấn tiếp theo hoặc cho đến khi bạn thực hiện explain().

Để hiểu được các kế hoạch truy vấn được coi là, bạn nên sử dụng explain(1), ví dụ:

db.col.find({category:'A'}).sort({updated: -1}).explain(1) 

Chi tiết allPlans sẽ hiển thị tất cả các kế hoạch đó được so sánh.

Nếu bạn chạy truy vấn không chọn lọc (ví dụ: nếu nhiều bản ghi khớp với tiêu chí {category: { $ne:'A'}}), MongoDB có thể nhanh hơn để tìm kết quả bằng cách sử dụng BasicCursor (quét bảng) thay vì khớp với chỉ mục .

Thứ tự của các trường trong truy vấn thường không tạo sự khác biệt cho lựa chọn chỉ mục (có một vài ngoại lệ với các truy vấn phạm vi). Thứ tự các trường trong một loại sắp xếp không ảnh hưởng đến lựa chọn chỉ mục.Nếu tiêu chí sort() của bạn không khớp với thứ tự chỉ mục, dữ liệu kết quả phải được sắp xếp lại sau khi chỉ mục được sử dụng (bạn sẽ thấy scanAndOrder:true trong đầu ra giải thích nếu điều này xảy ra).

Cũng cần lưu ý rằng MongoDB sẽ chỉ sử dụng one index per query (ngoại trừ $or s).

Vì vậy, nếu bạn đang cố gắng để tối ưu hóa truy vấn:

db.col.find({category:'A'}).sort({updated: -1, rating: -1}) 

Bạn sẽ muốn bao gồm cả ba lĩnh vực trong chỉ mục:

db.col.ensureIndex({category: 1, updated: -1, rating: -1}) 

FYI, nếu bạn muốn để buộc một truy vấn cụ thể để sử dụng chỉ mục (thường không cần thiết hoặc được khuyến nghị), có một tùy chọn hint() bạn có thể thử.

+0

Làm thế nào để trả lời câu hỏi này? Bạn vẫn không thể đảm bảo bạn sắp xếp theo thứ tự "xếp hạng desc, cập nhật desc" thay vì "cập nhật desc, xếp hạng desc" – jobermark

+0

@jobermark Trong câu hỏi ban đầu, tiêu chí truy vấn là 'danh mục' với thứ tự sắp xếp hợp lý của' {đã cập nhật: -1, xếp hạng: -1} '. Thứ tự (và hướng) của các khóa trong chỉ mục là quan trọng; chỉ mục được đề xuất sẽ không hỗ trợ hiệu quả tìm kiếm trên 'nội dung' được sắp xếp theo' {rating: -1, updated: -1} '. Nếu bạn đang thao tác các giá trị sắp xếp hợp chất trong trình điều khiển, hãy sử dụng băm/từ điển được sắp xếp để đảm bảo thứ tự được giữ nguyên. Để biết thêm thông tin, hãy xem [Sắp xếp trên nhiều trường] (https://docs.mongodb.org/manual/tutorial/sort-results-with-indexes/#sort-on-multiple-fields) trong tài liệu MongoDB. – Stennie

1

Điều đó đúng nhưng có hai lớp đặt hàng bạn có ở đây vì bạn đang sắp xếp theo chỉ mục hợp chất.

Khi bạn nhận thấy khi trường đầu tiên của chỉ mục khớp với trường đầu tiên của sắp xếp, nó hoạt động và chỉ mục được nhìn thấy. Tuy nhiên khi làm việc theo cách khác xung quanh nó không.

Như vậy bằng cách che dấu của riêng bạn, thứ tự cần được bảo tồn là thứ tự truy vấn của các trường từ đầu đến cuối. Các phân tích mongo đôi khi có thể di chuyển xung quanh các lĩnh vực để phù hợp với một chỉ số nhưng thông thường nó sẽ chỉ cố gắng và phù hợp với lĩnh vực đầu tiên, nếu nó không thể nó sẽ bỏ qua nó.

0

thử mã này nó sẽ sắp xếp dữ liệu đầu tiên dựa trên tên thì giữ 'tên' trong người giữ chìa khóa nó sẽ sắp xếp 'lọc'

var cursor = db.collection('vc').find({ "name" : { $in: [ /cpu/, /memo/ ] }  }, { _id: 0, }).sort({ "name":1 , "filter": 1 }); 
Các vấn đề liên quan