2012-07-10 14 views
10

Tôi đang sử dụng trình điều khiển mgo cho MongoDB trong Go.MongoDB trong Go (golang) với mgo: Làm cách nào để cập nhật bản ghi, tìm hiểu xem bản cập nhật có thành công hay không và lấy dữ liệu trong một hoạt động nguyên tử duy nhất?

Ứng dụng của tôi yêu cầu một tác vụ (chỉ với một bản ghi được chọn trong Mongo từ bộ sưu tập có tên là "công việc") và sau đó đăng ký chính nó như một người nhận hàng để hoàn thành tác vụ đó (bản cập nhật cho bản ghi "công việc" đó) như người được giao).

Chương trình sẽ chạy trên một số máy, tất cả đều nói chuyện với cùng một Mongo. Khi chương trình của tôi liệt kê các tác vụ sẵn có và sau đó chọn một nhiệm vụ, các trường hợp khác có thể đã nhận được nhiệm vụ đó và nhiệm vụ hiện tại sẽ không thành công.

Làm cách nào để đảm bảo rằng bản ghi tôi đọc và sau đó cập nhật hoặc không có giá trị nhất định (trong trường hợp này, người được chuyển nhượng) tại thời điểm được cập nhật?

Tôi đang cố gắng để nhận một bài tập, bất kể đó là gì, vì vậy tôi nghĩ trước tiên tôi nên chọn một nhiệm vụ đang chờ xử lý và cố gắng chỉ định nó, giữ nó chỉ trong trường hợp cập nhật thành công.

Vì vậy, câu hỏi của tôi nên được một cái gì đó như:

"Từ tất cả hồ sơ trên 'công việc' bộ sưu tập, cập nhật chỉ là một có asignee = null, thiết lập ID của tôi là bên nhận chuyển nhượng Sau đó, cho tôi. bản ghi đó để tôi có thể thực hiện công việc. "

Làm cách nào để diễn tả điều đó bằng trình điều khiển xe tải cho Go?

Trả lời

2

Tôi hy vọng bạn đã thấy các nhận xét về câu trả lời bạn đã chọn, nhưng cách tiếp cận đó không chính xác. Thực hiện lựa chọn và sau đó cập nhật sẽ dẫn đến một chuyến đi khứ hồi và hai máy và tìm nạp cho cùng một công việc trước khi một trong số họ có thể cập nhật assignee. Bạn cần sử dụng phương pháp findAndModify để thay thế: http://www.mongodb.org/display/DOCS/findAndModify+Command

+0

Trên thực tế, giải pháp tôi cần là một trong những tux21b được cung cấp. Tôi cần phải retreve tất cả "tùy chọn" sau đó chọn một, sau đó cố gắng để gán nó cho bản thân mình. Nếu không thành công, tôi sẽ thử với người khác. –

+0

Tại sao bạn cần chọn TẤT CẢ các tùy chọn? Bạn có nói rằng bạn chỉ cần chọn trên đó không được thực hiện (aka assignee == null)? –

+0

Bạn nói đúng. Nhu cầu của tôi hóa ra khác với những gì tôi nghĩ khi tôi viết câu hỏi, nhưng câu trả lời của bạn phù hợp với câu hỏi tốt hơn. –

2

Các MongoDB chàng trai mô tả một kịch bản tương tự như trong các tài liệu chính thức: http://www.mongodb.org/display/DOCS/Atomic+Operations

Về cơ bản, tất cả các bạn phải làm là lấy bất kỳ công việc với assignee=null. Hãy giả sử bạn nhận được công việc với hậu tố _id=42. Sau đó, bạn có thể tiếp tục và sửa đổi tài liệu cục bộ, bằng cách đặt assignee="worker1.example.com" và gọi Collection.Update() bằng công cụ chọn {_id=42, assignee=null} và tài liệu được cập nhật của bạn. Nếu cơ sở dữ liệu vẫn có thể tìm thấy một tài liệu phù hợp với bộ chọn này, nó sẽ thay thế tài liệu một cách nguyên tử. Nếu không, bạn sẽ nhận được một ErrNotFound, chỉ ra rằng một chủ đề khác đã tuyên bố nhiệm vụ. Nếu đúng như vậy, hãy thử lại.

+4

Performing chọn tiếp theo là một bản cập nhật không phải là nguyên tử; nó thực hiện hai chuyến đi khứ hồi! Lệnh findAndModify sẽ thực hiện thao tác này một cách nguyên tử. Tài liệu Mongo cho lệnh này có tại đây: http://www.mongodb.org/display/DOCS/findAndModify+Command Tài liệu hướng dẫn để thực hiện việc này trong Go ở đây: http://go.pkgdoc.org/labix .org/v2/mgo # Truy vấn.Áp dụng – jorelli

+1

Việc chọn + cập nhật không cần phải là nguyên tử cho thuật toán cụ thể này. Miễn là bản cập nhật chính nó là nguyên tử (về cơ bản là một hoạt động CompareAndSwap/CompareExchange) mọi thứ đều ổn. – tux21b

+1

Nếu hai máy chọn cùng một công việc trên truy vấn đầu tiên, một trong số chúng sẽ thất bại khi cập nhật. Chắc chắn, kết quả cuối cùng luôn luôn có thể là dữ liệu trong cơ sở dữ liệu không bao giờ trở nên không nhất quán, nhưng trường hợp thất bại với việc sử dụng hai hoạt động riêng biệt gây ra rất nhiều không cần thiết qua lại. Đây là ... toàn bộ lý do lệnh findAndModify tồn tại. – jorelli

41

Đây là câu hỏi cũ nhưng chỉ trong trường hợp ai đó vẫn đang xem ở nhà, điều này được hỗ trợ độc đáo qua phương thức Query.Apply. Nó chạy lệnh findAndModify như được chỉ ra trong một câu trả lời khác, nhưng nó thuận tiện ẩn đằng sau Go goodness.

Ví dụ trong tài liệu phù hợp với khá nhiều chính xác câu hỏi ở đây:

change := mgo.Change{ 
     Update: bson.M{"$inc": bson.M{"n": 1}}, 
     ReturnNew: true, 
} 
info, err = col.Find(M{"_id": id}).Apply(change, &doc) 
fmt.Println(doc.N) 
Các vấn đề liên quan