2013-05-16 45 views
9

Tôi có một truy vấn:

db.test.aggregate({$group : { _id : '$key', frequency: { $sum : 1 } } }) 

này sẽ nhận được tần số của mỗi đếm then chốt trong tập kiểm tra. Về cơ bản, tôi đã nhận được sự phân phối của khóa.

Bây giờ hãy tưởng tượng tôi muốn nhận các bản phân phối của key1, key2 và key3 (do đó có ba bản phân phối khác nhau).

Rõ ràng, tôi có thể chạy truy vấn này 3 lần với mỗi khóa riêng biệt, nhưng có vẻ như chúng tôi có thể tối ưu hóa truy vấn bằng cách cho phép nó đếm tất cả 3 khóa cùng một lúc. Tôi đã chơi đùa với nó và tìm kiếm toàn bộ các trang web liên, nhưng cho đến nay, tôi được ủy thác để chạy ba truy vấn tổng hợp riêng biệt hoặc sử dụng chức năng map/reduce.

Có ai có ý tưởng nào khác không?

Trả lời

6

Có một vài phương pháp tiếp cận khác nhau mà bạn có thể sử dụng ở đây:

  1. Sử dụng bản đồ/giảm: không làm điều này. Ngay bây giờ sẽ nhanh hơn nhiều khi chạy khung tổng hợp 3 lần so với sử dụng chức năng giảm bản đồ cho trường hợp sử dụng này.

  2. Chạy tập hợp 3 lần. Đây không phải là tối ưu, nhưng nếu bạn không có ràng buộc về thời gian thì đây là tùy chọn dễ nhất. Nếu tập hợp của bạn đang dùng < một vài giây thì tôi sẽ không lo lắng về việc tối ưu hóa cho đến khi chúng trở thành một vấn đề.

  3. Đây là công việc tốt nhất mà tôi có thể nghĩ đến. Toán tử $group cho phép bạn tạo một _id trên nhiều trường. Ví dụ. {"_id":{"a":"$key1", "b":"$key2", "c":"$key3"}}. Việc này sẽ tạo nhóm cho tất cả các kết hợp hiện có của các khóa khác nhau của bạn. Bạn có khả năng nhóm các khóa của bạn theo cách này và sau đó tổng hợp theo cách thủ công trên các kết quả trong ứng dụng khách.

Hãy để tôi giải thích. Hãy nói rằng chúng tôi có một bộ sưu tập các hình dạng. Những hình dạng này có thể có màu, kích thước và loại (hình vuông, hình tròn, v.v ...). Một tập hợp trên một Id đa-key có thể trông giống như:

db.shapes.aggregate({$group:{_id:{"f1":"$f1", "f2":"$f2", "f3":"$f3"}, count:{"$sum":1}}}) 

và gửi lại:

"result" : [ 
     { 
      "_id" : { 
       "f1" : "yellow", 
       "f2" : "medium", 
       "f3" : "triangle" 
      }, 
      "count" : 4086 
     }, 
     { 
      "_id" : { 
       "f1" : "red", 
       "f2" : "small", 
       "f3" : "triangle" 
      }, 
      "count" : 4138 
     }, 
     { 
      "_id" : { 
       "f1" : "red", 
       "f2" : "big", 
       "f3" : "square" 
      }, 
      "count" : 4113 
     }, 
     { 
      "_id" : { 
       "f1" : "yellow", 
       "f2" : "small", 
       "f3" : "triangle" 
      }, 
      "count" : 4145 
     }, 
     { 
      "_id" : { 
       "f1" : "red", 
       "f2" : "small", 
       "f3" : "square" 
      }, 
      "count" : 4062 
     } 

... và vân vân

Sau đó bạn sẽ tổng hợp kết quả client-side, trên số lượng mục nhập giảm đáng kể. Giả sử số lượng giá trị duy nhất cho mỗi khóa là đủ nhỏ so với tổng số tài liệu, bạn có thể thực hiện bước cuối cùng này trong một khoảng thời gian không đáng kể.

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