Sự khác biệt giữa findAndModify và cập nhật trong MongoDB là gì?


175

Tôi hơi bối rối bởi findAndModifyphương thức trong MongoDB. Lợi thế của nó so với updatephương pháp là gì? Đối với tôi, có vẻ như nó chỉ trả về mục đầu tiên và sau đó cập nhật nó. Nhưng tại sao tôi cần phải trả lại hàng đầu tiên? Tôi đã đọc MongoDB: hướng dẫn dứt khoát và nó nói rằng nó rất tiện cho việc thao tác các hàng đợi và thực hiện các hoạt động khác cần nguyên tử kiểu get-and-set. Nhưng tôi không hiểu làm thế nào nó đạt được điều này. Ai đó có thể giải thích điều này cho tôi?

Câu trả lời:


153

Nếu bạn tìm nạp một mục và sau đó cập nhật nó, có thể có một bản cập nhật bởi một luồng khác giữa hai bước đó. Nếu bạn cập nhật một mục trước và sau đó tìm nạp nó, có thể có một bản cập nhật khác ở giữa và bạn sẽ nhận lại một mục khác so với những gì bạn đã cập nhật.

Thực hiện "nguyên tử" có nghĩa là bạn được đảm bảo rằng bạn sẽ nhận lại chính xác cùng một mục bạn đang cập nhật - tức là không có hoạt động nào khác có thể xảy ra ở giữa.


6
Tôi vẫn còn một chút bối rối. Làm thế nào để findAndModifyđảm bảo rằng không có hoạt động cập nhật nào khác can thiệp vào nó?
chaonextdoor

78
@chaonextdoor findAndModify có được một khóa vào cơ sở dữ liệu khi nó bắt đầu hoạt động để không có hoạt động nào khác có thể xử lý khi nó đang chạy. Khi nó kết thúc hoạt động, nó sẽ giải phóng khóa.
Lycha

4
findAndModify không thực sự có được khóa cho đến khi sửa đổi một phần yêu cầu. Vì vậy, có thể cho nhiều quá trình có thể cập nhật cùng một bản ghi.
Đánh dấu Unsworth

5
@MarkUnsworth mở trường hợp hỗ trợ với 10gen - nếu có lỗi trong khóa với findAndModify tôi có thể đảm bảo rằng các kỹ sư của bạn sẽ muốn sửa nó càng sớm càng tốt. Nếu đó là trường hợp mặc dù chúng ta sẽ thấy rất nhiều người báo cáo hành vi này nhưng findAndModify hoạt động như được thiết kế cho khá nhiều người đang sử dụng nó - những trường hợp có vẻ như nó không được đưa ra logic hoặc lỗi thực thi ở phía máy khách , nhưng tất nhiên trong phần mềm phức tạp luôn có thể có lỗi.
Asya Kamsky

4
@AsyaKamsky Tôi đang cân nhắc việc cãi nhau với bạn nhưng rồi nhận ra bạn đúng nên giờ tôi đang nghĩ mình nên xin lỗi. Lấy làm tiếc!
funkyeah

54

findAndModify trả lại tài liệu, cập nhật không.

Nếu tôi hiểu Dwight Merriman (một trong những tác giả ban đầu của mongoDB), sử dụng cập nhật để sửa đổi một tài liệu duy nhất, nghĩa là ("multi": false} cũng là nguyên tử. Hiện tại, nó cũng phải nhanh hơn so với thực hiện cập nhật tương đương findAndModify.


31

Từ các tài liệu MongoDB (nhấn mạnh thêm):

  • Theo mặc định, cả hai hoạt động sửa đổi một tài liệu duy nhất. Tuy nhiên, phương thức update () với tùy chọn đa có thể sửa đổi nhiều tài liệu .

  • Nếu nhiều tài liệu khớp với tiêu chí cập nhật, đối với findAndModify (), bạn có thể chỉ định một loại để cung cấp một số biện pháp kiểm soát đối với tài liệu nào sẽ cập nhật. Với hành vi mặc định của phương thức update (), bạn không thể chỉ định tài liệu đơn nào sẽ cập nhật khi nhiều tài liệu khớp.

  • Theo mặc định, phương thức findAndModify () trả về phiên bản đã sửa đổi trước của tài liệu . Để có được tài liệu cập nhật, sử dụng tùy chọn mới. Phương thức update () trả về một đối tượng WriteResult có chứa trạng thái của hoạt động. Để trả về tài liệu đã cập nhật, sử dụng phương thức find (). Tuy nhiên, các cập nhật khác có thể đã sửa đổi tài liệu giữa cập nhật của bạn và truy xuất tài liệu. Ngoài ra, nếu bản cập nhật chỉ sửa đổi một tài liệu duy nhất nhưng nhiều tài liệu phù hợp, bạn sẽ cần sử dụng logic bổ sung để xác định tài liệu được cập nhật.

  • Trước MongoDB 3.2, bạn không thể chỉ định mối quan tâm ghi vào findAndModify () để ghi đè mối quan tâm ghi mặc định trong khi bạn có thể chỉ định mối quan tâm ghi cho phương thức update () kể từ MongoDB 2.6.

Khi sửa đổi một tài liệu, cả phương thức findAndModify () và update () đều cập nhật nguyên bản tài liệu.


1
Bạn luôn có thể chỉ định ghi quan tâm để cập nhật hoạt động. Ngoài ra, kể từ 3.2 (3.1.1 về mặt kỹ thuật), bạn cũng có thể chỉ định ghi chú quan tâm đến findAndModify. jira.mongodb.org/browse/SERVER-6558
Asya Kamsky

Tôi đã thấy rằng trong MongDB 3.6, mặc dù các trạng thái tài liệu findAndModify()theo mặc định chỉ sửa đổi một tài liệu và update()có thể cập nhật một hoặc nhiều tài liệu, khi tôi sử dụng arrayFilters, findAndModify()cập nhật tất cả các kết quả khớp. Có lẽ đó là một lỗi ??
WesternGun

Không có lỗi - ArrayFilters cho phép bạn cập nhật nhiều thành phần mảng nhưng chúng vẫn nằm trong một tài liệu duy nhất.
Asya Kamsky

10

Một lớp hữu ích của các trường hợp sử dụng là quầy và các trường hợp tương tự. Ví dụ: hãy xem mã này (một trong những bài kiểm tra MongoDB): find_and_modify4.js .

Do đó, với findAndModifybạn tăng bộ đếm và nhận giá trị tăng của nó trong một bước. So sánh: nếu bạn (A) thực hiện thao tác này theo hai bước và ai đó (B) thực hiện cùng một thao tác giữa các bước của bạn thì A và B có thể nhận được cùng một giá trị bộ đếm thay vì hai khác nhau (chỉ là một ví dụ về các vấn đề có thể xảy ra).


0

Chúng tôi đã sử dụng findAndModify () cho các hoạt động của Counter (inc hoặc dec) và các trường hợp đột biến trường đơn khác. Di chuyển ứng dụng của chúng tôi từ Couchbase sang MongoDB, tôi đã tìm thấy API này để thay thế mã GetAndlock (), sửa đổi nội dung cục bộ, thay thế () để lưu và Get () một lần nữa để lấy lại tài liệu đã cập nhật. Với mongoDB, tôi chỉ sử dụng API đơn này để trả về tài liệu đã cập nhật.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.