2013-07-06 32 views
37

Tôi tương đối mới với Node.js và Mongo/Mongoose và tôi đang gặp rất khắc phục sự cố khó khăn trong thời gian khó khăn cụ thể Mongoose:Lỗi "VersionError: Không tìm thấy tài liệu phù hợp" trên Node.js/Mongoose

Phiên bảnError: Không tìm thấy tài liệu phù hợp.

(Entire lỗi dấu vết/ngăn xếp ở dưới cùng của câu hỏi này.)

bài viết trên blog này khá phác thảo rõ ràng làm thế nào một VersionError có thể xảy ra:

(TL; DR - "Mongoose v3 bây giờ thêm khóa phiên bản có thể định cấu hình lược đồ cho từng tài liệu. Giá trị này được tăng lên theo nguyên tắc ver một sửa đổi cho một mảng có khả năng thay đổi bất kỳ vị trí các phần tử của mảng. "Nếu bạn cố gắng lưu một tài liệu, nhưng khóa phiên bản không còn phù hợp với đối tượng bạn đã lấy, bạn có được ở trên VersionError.)

: Có cách nào để hiển thị hoạt động vi phạm save() không? Hoặc tài liệu nào không thể lưu? Hoặc bất cứ điều gì ở tất cả ?! ;)

Thách thức: đây là một cơ sở mã tương đối lớn với nhiều mảng và tôi không chắc chắn cách bắt đầu khắc phục sự cố. Đặc biệt, dấu vết lỗi/ngăn xếp dường như không hiển thị nơi mà vấn đề tồn tại. Xem bên dưới:

VersionError: No matching document found. 
at handleSave (<project_path>/node_modules/mongoose/lib/model.js:121:23) 
at exports.tick (<project_path>/node_modules/mongoose/lib/utils.js:408:16) 
at null.<anonymous> (<project_path>/node_modules/mongoose/node_modules/mongodb/lib/mongodb/collection.js:484:9) 
at g (events.js:192:14) 
at EventEmitter.emit (events.js:126:20) 
at Server.Base._callHandler (<project_path>/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/base.js:391:25) 
at Server.connect.connectionPool.on.server._serverState (<project_path>/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js:558:20) 
at MongoReply.parseBody (<project_path>/node_modules/mongoose/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js:131:5) 
at Server.connect.connectionPool.on.server._serverState (<project_path>/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js:517:22) 
at EventEmitter.emit (events.js:96:17) 
+5

lẽ bật gỡ lỗi ([tài liệu] (http://mongoosejs.com/docs/api.html#index_Mongoose-set)) có thể giúp bạn theo dõi vấn đề này. Gần đây tôi đã có cùng một vấn đề, hóa ra là tôi đã lưu cùng một cá thể tài liệu hai lần, đồng thời. – robertklep

Trả lời

33

Theo yêu cầu, đây là một phác thảo của vấn đề của chúng ta, và làm thế nào chúng ta giải quyết nó:

Trong hệ thống của chúng tôi, chúng tôi đã tạo ra một tài liệu tùy chỉnh khóa thông thường (sử dụng redis-lock), trong đó những sản phẩm sau xảy ra trong chính xác này (không chính xác) theo thứ tự:

TRÌNH tỰ KHÔNG đÚNG ĐỐI VỚI HOẠT ĐỘNG:

  1. yêu cầu khách hàng nhận được
  2. Document khóa
  3. Document lấy
  4. Document sửa
  5. Document mở khóa theo yêu cầu khách hàng
  6. giải quyết
  7. tài liệu lưu

Khi bạn nhìn thấy nó được viết ra, vấn đề là rõ ràng: chúng tôi đã tiết kiệm của chúng tôi Tài liệu bên ngoài khóa Tài liệu của chúng tôi.

Giả sử # 6 mất 100ms trong hệ thống của chúng tôi. Đó là một cửa sổ 100ms trong đó nếu bất kỳ yêu cầu nào khác lấy cùng Tài liệu đó, chúng ta sẽ có một xung đột tiết kiệm (lỗi có tiêu đề trong Câu hỏi này về cơ bản là một IMHO xung đột tiết kiệm).

Nói cách khác/ví dụ: trong hệ thống của chúng tôi, Yêu cầu A đã lấy phiên bản 1 của tài liệu X, chỉnh sửa, sau đó mở khóa, nhưng trước khi yêu cầu A lưu tài liệu, yêu cầu B nắm lấy tài liệu X và tăng nó lên phiên bản 2 (đọc trên các phiên bản Mongo để biết thêm thông tin về điều này). Sau đó, Request A giải quyết yêu cầu Client của nó và đi để lưu Document X, nhưng nó đang cố gắng lưu phiên bản 1, và bây giờ nó thấy nó có Version 2, và do đó là lỗi ở trên.

Vì vậy, việc sửa chữa rất dễ dàng. Lưu tài liệu của bạn bên trong khóa của bạn. (Trong ví dụ trên, di chuyển # 7 đến trướC# 5. Xem bên dưới.)

ĐÚNG/CỐ ĐỊNH TRÌNH TỰ HOẠT ĐỘNG

  1. yêu cầu khách hàng nhận được
  2. tài liệu đã bị khoá
  3. Document lấy
  4. Tài liệu đã chỉnh sửa
  5. Tài liệu được lưu
  6. Document mở khóa
  7. yêu cầu khách hàng giải quyết

(Bạn có thể làm một cuộc tranh cãi rằng # 6 và # 7 nên được hoán đổi, nhưng điều đó nằm ngoài phạm vi của Mongo/Mongoose/câu hỏi này.)

Tôi sẽ để lại câu hỏi này un-trả lời trong một thời gian và xem nếu ai có thể làm sáng tỏ một số cách tốt hơn để cô lập các mã có liên quan và khắc phục sự cố này. Trong trường hợp của chúng tôi, đây là một vấn đề rất hệ thống và rất khó khăn để khắc phục sự cố cho trình độ kỹ năng của chúng tôi vào thời điểm đó.

+2

Tôi đã giải quyết các vấn đề tương tự ở đây và ở đó . Một điều cố định rất nhiều vấn đề là để đảm bảo rằng tất cả.save() có callbacks và đảm bảo save là tuần tự. 'item.save (function() {item.save ([...]);})' Tôi cũng đang làm việc để bắt lỗi và lấy lại/resaving tài liệu post-error ([phần nào dọc theo những dòng này] (https : //gist.github.com/droppedonjapan/5483a81917ea37ef381b)). Vẫn cố gắng tìm ra các chi tiết cụ thể để không chỉ bắt lỗi, mà còn là tài liệu cũ nữa. –

+1

Tôi gặp lỗi này ngay cả khi các cuộc gọi save() của tôi không đồng thời. Có liên quan: https://github.com/Automattic/mongoose/issues/1844 và http://stackoverflow.com/questions/20723474/version-error-on-saving-mongoose-docs – Aaron

+0

@toblerpwn chúng tôi đang gặp vấn đề tương tự trong ứng dụng của chúng tôi. Bạn có nghĩ rằng bằng cách sử dụng redis-lock là một giải pháp mạnh mẽ? Đó là một trong những lựa chọn mà chúng tôi đang xem xét. – PunDefeated

10

Nó có khả năng tiết kiệm cùng một tài liệu đồng thời như robertklep chỉ ra.

Chúng tôi đã gặp sự cố tương tự đang chạy đồng thời lưu trên cùng một tài liệu bằng cách sử dụng async.parallel.

+1

Thật vậy; Tôi nghĩ rằng đây là một vấn đề cụ thể đối với môi trường của chúng tôi, mà tôi chỉ tìm thấy bằng 'console.log'ing phong phú. Tôi nghĩ câu hỏi quan trọng vẫn còn (mà tôi sẽ chỉnh sửa + làm nổi bật tốt hơn): có cách nào để đăng nhập thất bại không trực tiếp từ Mongoose? Điều đó sẽ giúp người tìm kiếm trong tương lai. :) – toblerpwn

+1

@toblerpwn - bạn có thể giải thích về những gì bạn nghĩ gây ra điều này không? – UpTheCreek

+1

@UpTheCreek - chắc chắn. Tôi sẽ tạo ra một câu trả lời cho việc này. Đứng gần. – toblerpwn

5

Lỗi này cũng có thể xảy ra khi quá trình của bạn duy trì một phiên bản lỗi thời của tài liệu trong bộ nhớ và sau đó cố gắng lưu nó tại một số thời điểm sau khi quá trình khác cập nhật.

0

Tôi có vấn đề này trong một ứng dụng NextJS/Express, nhưng sau khi đọc this Mongoose discussion tôi thấy tôi có thể giải quyết vấn đề bằng cách chỉ tháo __v tài sản từ tài liệu tôi đã cố gắng để tiết kiệm:

const fixedDocument = _.pickBy(originalDocument, (val, key) => key !== '__v'); 
Các vấn đề liên quan