2012-03-06 32 views
5

Tôi đang làm việc với MongoDB trên dự án hiện tại của tôi và một chút nhầm lẫn về cách thích hợp để xây dựng hỗ trợ cho các sửa đổi đồng thời.MongoDB Mối quan tâm về nguyên tử - Sửa đổi tài liệu trong bộ nhớ

Tôi có một mảng đối tượng. Khi có yêu cầu, tôi muốn kiểm tra phần tử cuối cùng trong mảng đó và đưa ra quyết định có điều kiện về cách phản hồi. Mã của tôi trông giống như sau:

# Find the last object ID in the array. 
last_element_id = str(document['objects'][-1]) 
if last_element_id != the_element_id_the_request_is_responding_to: 
    db.documents.insert({ 
     ... 
    }) 
else: 
    # Append the response to the end of the array. 
    document['objects'].append(new_element_id) 
    db.documents.save(document) 

Tôi lo ngại về tình hình ở đó:

  1. Trong xử lý yêu cầu A, tôi tìm ra last_element_id là hợp lệ, và phản ứng nên được nối thêm vào cuối danh sách.
  2. Trước khi các hoạt động chắp thêm() và lưu() hoàn tất, một yêu cầu khác, B, là được xử lý.
  3. B cũng thấy last_element_id là hợp lệ, gắn thêm() các phản hồi và tiết kiệm().
  4. Bây giờ, câu trả lời của A được đặt vào cuối của mảng, nhưng phản hồi không còn theo sau được cho là 'last_element_id' vì phản hồi của B bị giật trước.

Cách thích hợp để xử lý loại logic này trong mô hình nguyên tử của Mongo là gì? Tôi không muốn sử dụng khóa nếu tôi có thể tránh chúng, vì ứng dụng WSGI có thể chạy trong nhiều quá trình cùng một lúc.

Cảm ơn!

Trả lời

1

Bạn có thể sử dụng khóa lạc quan .., một cách là thêm trường được gọi là phiên bản vào tài liệu và sau đó tăng nó lên mỗi lần cập nhật và khi bạn cập nhật đảm bảo rằng phiên bản trong tài liệu giống với một bạn đọc ở.

tôi có thể cung cấp chi tiết hơn, nhưng điều này khá cũng là tài liệu tại http://www.mongodb.org/display/DOCS/Atomic+Operations#AtomicOperations-%22UpdateifCurrent%22

Hãy cho tôi biết nếu làm việc này cho bạn,

+0

Dường như điều này có thể phù hợp với những gì tôi đang làm! Cảm ơn! Sẽ báo cáo lại. –

+0

Hoàn hảo. Cảm ơn! –

+0

@Shekar, bạn có thể dễ dàng đạt được điều này với findandmodify (trường hợp này). kiểm tra câu trả lời của tôi để biết thêm thông tin – RameshVel

1

bạn có thể sử dụng findAndModify để atomicallay xử lý giao dịch (ít nhất là trường hợp này).

Lệnh này chấp nhận cờ upsert, mà bạn có thể sử dụng để cập nhật hoặc chèn tài liệu dựa trên existence của nó. Kiểm tra ví dụ dưới đây

> db.upsertTest.find() 
{ "_id" : 1, "arr" : [ 1 ] } 

và ban hành lệnh này với các truy vấn _id:1 sẽ đẩy (append) mục mới vào arr

> db.upsertTest.findAndModify({query: {_id:1},update:{$push:{arr:2}},upsert:true,"new":true}) 
{ "_id" : 1, "arr" : [ 1, 2 ] } 

và điều này sẽ tạo ra một cái mới vì _id:2 không tồn tại đã

> db.upsertTest.findAndModify({query: {_id:2},update:{$push:{arr:2}},upsert:true,"new":true}) 
{ "_id" : 2, "arr" : [ 2 ] } 

> db.upsertTest.find() 
{ "_id" : 1, "arr" : [ 1, 2 ] } 
{ "_id" : 2, "arr" : [ 2 ] } 

Hy vọng điều đó sẽ hữu ích.

+0

Hỗ trợ truy vấn trong findAndModify có đủ phong phú cho những gì tôi đang cố gắng đạt được không?Tôi chỉ muốn đẩy mục mới vào mặt sau của mảng nếu mục cuối cùng trong mảng là một số giá trị đã biết. Giá trị đã biết này được gửi dưới dạng tham số trong yêu cầu POST. –

+0

Bạn có thể làm điều đó với findAndModify. Đó là một sự lựa chọn hoàn hảo. Trong các ví dụ trên, bạn có thể dễ dàng thay thế truy vấn của bạn và đẩy để làm cho nó hoạt động .. – RameshVel

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