2012-04-23 30 views
11

Tôi hiện đang có số liệu sau:'upsert' trong một tài liệu nhúng

{ 
    'component_id':1, 
    '_locales':[ 
     { 
      'url': 'dutch', 
      'locale': 'nl_NL' 
     } 
    ] (etc) 
} 

Nếu tôi muốn cập nhật hàng với locale tôi sẽ chạy một cái gì đó tương tự như:

db.components.update(
    {'component_id': 1, '_locales.locale': 'nl_NL'}, 
    {$set: {'_locales.$': {'url': 'new url','locale':'nl_NL'}}, 
    true 
); 

tác phẩm này cho đến khi miền địa phương không tồn tại:

db.components.update(
    {'component_id': 1, '_locales.locale': 'en_US'}, 
    {$set: {'_locales.$': {'url': 'new url','locale':'en_US'}}, 
    true 
); 

vì có chỉ mục duy nhất trên component_id này sẽ ném một excep tion phàn nàn về một khóa trùng lặp.

Có cách nào để tự động thêm 'tài liệu' mới bằng ngôn ngữ khác và cập nhật nếu nó đã tồn tại? Theo tài liệu sử dụng toán tử vị trí sẽ không hoạt động với 'upserting'.

Trả lời

10

Bạn có thể sử dụng $addToSet để thêm vào bộ đảm bảo không có phần tử mảng trùng lặp, nhưng điều đó sẽ không hoạt động đối với trường hợp "cập nhật" của bạn.

Để làm được những gì bạn muốn, bạn sẽ cần phải thay đổi cấu trúc dữ liệu của bạn để một cái gì đó như:

{ 
    "_id" : ObjectId("4f9519d6684c8b1c9e72e367"), 
    "component_id" : 1, 
    "_locales" : { 
     "nl_NL" : { 
      "url" : "dutch" 
     } 
    } 
} 

Bây giờ bạn có thể làm một bản cập nhật trên locale nl_NL chỉ:

db.components.update({ component_id: 1 }, { $set: { '_locales.nl_NL.url' : 'new url' } }, true); 

Và một ngôn ngữ mới cũng sẽ hoạt động, chẳng hạn như:

db.components.update({ component_id: 1 }, { $set: { '_locales.en_US.url' : 'American' } }, true); 

Bạn có thể muốn xem er để có vị trí như một phần của đối tượng lồng nhau cũng có thể, như trong:

{ 
    "_id" : ObjectId("4f9519d6684c8b1c9e72e367"), 
    "component_id" : 1, 
    "_locales" : { 
     "nl_NL" : { 
      "url" : "dutch" 
      "locale" : "nl_NL"     
     } 
    } 
} 

Điều này giúp dễ dàng truy xuất dữ liệu trong một số trường hợp.

+1

Xin chào Derick, cảm ơn bạn đã trả lời. Đề xuất của bạn thực sự là cơ sở hạ tầng ban đầu của tôi mà tôi đã thay đổi ở trên. Một lý do đã tạo các chỉ mục trên: _locales.url thay vì trên mọi ngôn ngữ: _locales.nl_NL.url, _locales.en_US.url, v.v. Hiện tại tôi đã giải quyết được điều này bằng cách lấy tất cả dữ liệu _locales và sửa đổi/thêm ngôn ngữ tôi đang làm việc với 'thủ công'. Khi tôi làm xong, tôi thay thế '_locales' hiện tại bằng cái mới. Để bây giờ điều này sẽ đủ, hiệu suất khôn ngoan này có thể không phải là một ý tưởng rất tốt. –

+0

Tôi đồng ý, có khóa "không được xác định" thường không phải là điều tốt để làm do các chỉ mục. Đôi khi, tốt hơn là thực hiện hai truy vấn để thực hiện cập nhật đó nếu điều đó cải thiện hiệu suất do các chỉ mục/các lý do khác trong các trường hợp khác. Không có thực sự "đúng cách" hầu hết thời gian. Chơi với nó, và nếu nó không thực hiện thay đổi nó trở lại và chạy hai truy vấn để cập nhật. – Derick

+0

@Derick: Tôi đang gặp phải sự cố tương tự. http://stackoverflow.com/questions/32038606/defining-a-map-with-objectid-key-and-array-of-strings-as-value-in-mongoose-schem –

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