2017-08-14 14 views
5

Tình huống:Tìm kiếm theo thẻ hiệu quả như thế nào?

Tôi có 1 triệu người dùng và tôi muốn tìm kiếm chúng theo thẻ.

Dưới đây là sơ đồ:

const Account = new Schema({ 
    tags: { type: [String], default: ['cats'] } 
}) 

Dưới đây là các truy vấn đầu tiên:

const query = { tags: 'cats'} 
const fields = { _id: 0 } 
const options = { skip: 0, limit: 5 } 

Account.find(query, fields, options) 

Sau khi gọi find phương pháp Mongoose sẽ bắt đầu tìm kiếm và trả lại 5 mục đầu tiên nó phù hợp. Hiệu suất trong trường hợp này là tối ưu.

Dưới đây là các truy vấn thứ hai:

const query = { tags: 'cats'} 
const fields = { _id: 0 } 
const options = { skip: 500 000, limit: 5 } 

Account.find(query, fields, options) 

gì xảy ra trong trường hợp này là quan tâm đến tôi.

Mongoose khớp 500 000 mục trước và sau đó trả lại 5 mục tiếp theo?

Hoặc thực hiện bằng cách nào đó 'nhảy' đến phần 500 000 mà không cần phải khớp tất cả trước đó?

Tôi đang cố gắng hiểu mức độ hiệu quả của việc áp dụng này và liệu tôi có thể cải thiện nó bằng cách nào đó hay không. Cho tôi vài lời khuyên được không?

+1

tìm hoạt động tương tự như "select", vì vậy nó đầu tiên của tất cả các trận đấu 500.000 mục và sau đó bỏ qua nó để rõ ràng hiệu suất khôn ngoan của nó không tốt. Bạn nên tìm kiếm về kỹ thuật lập chỉ mục hoặc sắp xếp dữ liệu hiệu quả trước tiên. –

Trả lời

2

Có, nó phù hợp với 500.000 mục nhập trước tiên.

Từ MongoDB Definitive Guide 2nd Edition:

$ bỏ qua mất một số, n, và loại bỏ các văn bản n đầu tiên từ tập kết quả. Cũng giống như truy vấn “bình thường”, việc truy vấn không hiệu quả đối với các lần bỏ qua lớn, vì nó phải tìm tất cả các kết quả phù hợp phải bỏ qua và sau đó loại bỏ chúng.

Bạn có thể kiểm tra truy vấn của bạn một cách chi tiết từ Mongo shell sử dụng giải thích():

https://docs.mongodb.com/manual/reference/method/cursor.explain/

Ex:

// Create a dummy collection 
var tagTypes = ['cats', 'dogs', 'chickens'] 
    for (i=0; i < 1000; i++) { 
     let tag = tagTypes[Math.floor(Math.random()*tagTypes.length)] 
     db.people.insert({"tags" : [tag]}) 
    } 

sau đó giải thích nó

db.people.find({"tags" : "cats"}).skip(100).limit(10).explain("executionStats”) 

totalDocsExamined i s hiển thị cho bạn rằng nó được phù hợp với tất cả mọi thứ mà nó bỏ qua

"executionStats" : { 
... 
    "totalDocsExamined" : 420 

Nếu bạn đã tạo một chỉ mục trên thẻ:

db.people.ensureIndex({ "tags" : 1 }) 

Chạy nó một lần nữa bạn sẽ nhận được:

"executionStats" : { 
... 
    "totalDocsExamined" : 110 
+0

cảm ơn bạn, thưa bạn! Tôi đã trao một người dùng khác với tiền thưởng do nhầm lẫn. Câu trả lời này xứng đáng. Xin lỗi –

+1

Không có vấn đề vui khi được trợ giúp – drew

2

Thú vị. Sự hiểu biết của tôi là Find ở đây là rất tương tự trong chức năng truy vấn để Select, trong đó nó sẽ làm việc không hiệu quả bằng cách đầu tiên đi qua 500.000 giá trị trước khi bỏ qua chúng.

Do đó, những gì tôi đề xuất là triển khai một cái gì đó được gọi là chỉ mục Đa cấp. Về cơ bản tạo ra một hệ thống lập chỉ mục lồng nhau, mặc dù chiếm không gian dữ liệu, rất hiệu quả, đặc biệt đối với các thực hành tìm kiếm tuần tự mà bạn không muốn thực hiện một cây thẳng đứng. Tạo một tập hợp các chỉ mục bên ngoài tổng quát hơn, sau đó liên kết chúng với các chỉ số bên trong tương ứng, trước khi chuyển sang các khối dữ liệu được lưu trữ.

Triển khai điều này không nên quá khó và cần cải thiện đáng kể số lượng vượt qua được thực hiện. Hi vọng điêu nay co ich.

Các vấn đề liên quan