2013-05-27 24 views
8

Tôi có MongoDB với bộ sưu tập "tin nhắn" lớn; tất cả các tin nhắn thuộc về một số cụ thể groupId. Vì vậy, tôi đã bắt đầu với một ấn phẩm như thế này:Làm cách nào để hủy đăng ký nhận một bộ sưu tập?

Meteor.publish("messages", function(groupId) { 
    return Messages.find({ 
    groupId: groupId 
    }); 
}); 

và một thuê bao như thế này:

Deps.autorun(function() { 
    return Meteor.subscribe("messages", Session.get("currentGroupId")); 
}); 

này đã cho tôi gặp rắc rối vì ban đầu currentGroupId là undefined nhưng mongod sill sẽ sử dụng CPU lên để tìm thông điệp với groupId == null (mặc dù tôi biết không có).

Bây giờ, tôi đã cố gắng để viết lại các ấn phẩm như sau:

Meteor.publish("messages", function(groupId) { 
    if (groupId) { 
    return Messages.find({ 
     groupId: groupId 
    }); 
    } else { 
    return {}; // is this the way to return an empty publication!? 
    } 
}); 

và/hoặc viết lại các thuê bao:

Deps.autorun(function() { 
    if (Session.get("currentGroupId")) { 
    return Meteor.subscribe("messages", Session.get("currentGroupId")); 
    } else { 
    // can I put a Meteor.unsubscribe("messages") here!? 
    } 
}); 

mà vừa mang lợi ích ban đầu. Nhưng ngay sau khi currentGroupId trở thành không xác định một lần nữa (vì người dùng điều hướng đến một trang khác), mongod vẫn đang bận xử lý lại cơ sở dữ liệu cho lần đăng ký cuối cùng groupId. Vì vậy, làm thế nào tôi có thể hủy đăng ký từ một ấn phẩm như vậy mà mongod là ngừng được truy vấn?

Trả lời

5

Đơn giản chỉ cần thêm một điều kiện để công bố:

Meteor.publish("messages", function(groupId) { 
    if (groupId) { 
    return Messages.find({ 
     groupId: groupId 
    }); 
}); 

và giữ đăng ký:

Deps.autorun(function() { 
    return Meteor.subscribe("messages", Session.get("currentGroupId")); 
}); 

thực hiện công việc.

Không cần dừng ấn phẩm một cách rõ ràng. Cuối cùng, MongoDB không được truy vấn nữa sau khi kết thúc truy vấn hiện đang chạy và phát hành một truy vấn khác (có vẻ như được xếp hàng đợi ở đâu đó trong hệ thống).

+0

Thật không may, tôi không tìm thấy bất kỳ tài liệu nào để chứng minh khiếu nại này. Một gợi ý sẽ rất được đánh giá cao. – Dejan

7

Theo tài liệu đó phải là http://docs.meteor.com/#publish_stop

this.stop() Gọi bên trong xuất bản chức năng. Dừng đăng ký của khách hàng này; gọi lại onError không được gọi trên máy khách.

Vì vậy, một cái gì đó giống như

Meteor.publish("messages", function(groupId) { 
    if (groupId) { 
    return Messages.find({ 
     groupId: groupId 
    }); 
    } else { 
    return this.stop(); 
    } 
}); 

Và tôi đoán trên các mặt hàng bạn chỉ có thể loại bỏ của bạn if/else như trong ví dụ đầu tiên bạn

Deps.autorun(function() { 
    return Meteor.subscribe("messages", Session.get("currentGroupId")); 
}); 
+2

Tôi đoán bạn có một loại ở đây. 'Messages' không có phương thức' stop'. Tôi đoán nó nên nói 'return this.stop();' thay vào đó. – Dejan

+1

Tôi tin rằng bạn là đúng, theo doc gọi stop() là một phương pháp của Meteor.publish, vì vậy tôi đã thay đổi nó thành this.stop(). – Michael

+0

Bây giờ, điều thú vị là bỏ qua cuộc gọi dừng() không làm thay đổi hành vi. Hãy xem câu trả lời của tôi. – Dejan

0

trong trường hợp của bạn, bạn nên dừng lại autorun

có một ví dụ trong số documentation

autorun của bạn là thực sự được gọi với một tham số cho phép bạn ngăn chặn nó:

Deps.autorun(function (c) { 
    if (! Session.equals("shouldAlert", true)) 
    return; 

    c.stop(); 
    alert("Oh no!"); 
}); 
+0

Ngừng 'autorun' sẽ không giúp ích gì bởi vì tôi cần tải lại (tức là đăng ký lại) một lần khi' currentGroupId' không còn rỗng nữa. – Dejan

6

tôi thấy nó đơn giản hơn và thẳng về phía trước để gọi .stop() chức năng trên bộ xử lý mà được trả về từ các .subscribe() gọi:

let handler = Meteor.subscribe('items'); 
... 
handler.stop(); 
Các vấn đề liên quan