2015-05-19 13 views
5

Tôi đang sử dụng chồng Có nghĩa là. Tôi không thoải mái mới với điều này và đã có bản thân mình trong một dưa chua. Tôi đã nhìn thấy ví dụ về cập nhật hồ sơ bằng cách sử dụng thiết lập hoặc đẩy nhưng bởi vì tôi đang cố gắng cập nhật một đối tượng json trong một đối tượng json trong một mảng các đối tượng json Tôi đang gặp rắc rối.MongoDB. Cách cập nhật thuộc tính json bên trong một mảng

Cân nhắc Schema sau

token: { 
    type: String, 
    required: "FB access token required." 
}, 
fbId: { 
    type: String, 
    required: "FB id required.", 
    unique: true 
}, 
accounts: { 
    type: Array, 
    default: [] 
} 

Tài khoản của tôi mảng bao gồm các đối tượng json, mỗi trong số đó trông như thế này:

{ 
    "name": "some name", 
    "credentials": { 
     "username": "some username", 
     "password": "some password" 
} 

Tôi đang cố gắng để cập nhật tài khoản mỗi khi người dùng thêm một cái mới. Vì vậy, trong trường hợp này tôi có thể sử dụng $ đẩy tốt. Nhưng tôi không muốn tên trùng lặp, và $ đẩy không thành công ở đây. Vì vậy, tôi đã thử sử dụng $ set, nhưng $ set không chèn các đối tượng có tên mới vào tài khoản. Vì vậy, tôi đã thử sử dụng upsert: true với $ set, nhưng bây giờ tôi nhận được lỗi trùng lặp.

Đây là ví dụ mà tôi cố gắng lập chỉ mục tên trong tài khoản. Tôi giả sử tôi đang vặn vẹo truy vấn của tôi một số cách.

var name = "some name"; 
var fbId = "some fb Id"; 
var token = "some token"; 
var username = "some other username"; 
var password = "some other password"; 

var query = { 
    fbId: fbId, 
    token: token, 
    "accounts.name":name 
}; 
var update = { 
    $set: { 
     accounts: [{ 
      name: name, 
      credentials: { 
       username: username, 
       password: password 
      } 
     }] 
    } 

}; 
var options = { 
    upsert: true 
}; 
User.update(query, update, options, 
    function (err, numberAffected, rawResponse) { 
     //handle it 
    }); 
); 

Để tổng hợp câu hỏi của tôi, có hợp lý để nghĩ rằng tôi có thể cập nhật điều này bằng một cuộc gọi và nếu có thì làm cách nào? Hoặc tôi nên tìm đối tượng, thay thế các giá trị của nó và sau đó lắp lại nó vào cơ sở dữ liệu?

Trả lời

4

Bạn có thể sử dụng $ mảng cập nhật điều hành:

var query = { 
    fbId: fbId, 
    token: token, 
    "accounts.name":name 
}; 
var update = { 
    $set: { 
     "accounts.$": [{  //The $ operator goes into the update object 
      name: name, 
      credentials: { 
       username: username, 
       password: password 
      } 
     }] 
    } 
}; 

Theo documentation:

Các $ điều hành theo vị trí xác định một phần tử trong một mảng để cập nhật không xác định rõ vị trí của phần tử trong mảng .

EDIT:

Theo MongoDB JIRA page này, sử dụng upsert với toán tử vị trí $ vẫn là một vấn đề mở.

Tôi đã tìm kiếm xung quanh và tìm thấy một giải pháp khả thi, tiếc là đánh bại mục tiêu của bạn để đạt được điều này chỉ bằng một cuộc gọi. Nó có thể được tìm thấy here.

Để tóm tắt câu trả lời đó, trước tiên bạn sẽ phải gửi truy vấn cập nhật mà không có cờ upsert. Sau đó kiểm tra phản hồi để xem liệu tài liệu đã được cập nhật chưa, nếu không (điều này có nghĩa là tài liệu phụ không tồn tại), hãy gửi truy vấn khác với toán tử $push để chèn một subdocument mới vào mảng.

+0

Nhận phản hồi lỗi sau. Toán tử vị trí không tìm thấy kết quả cần thiết từ truy vấn. Cập nhật chưa được mở rộng: tài khoản $ – zafrani

+0

Ồ, bạn cũng cần đặt cờ upsert thành true. – ZeMoon

+0

Đó là. Khi tôi nhận xét ra cờ upsert tôi nhận được không có lỗi nhưng nó cũng cập nhật không có gì. – zafrani

0

Nếu $push đang hoạt động cho bạn nhưng bạn muốn tránh thêm các bản sao vào mảng, hãy thử $addToSet. Nó sẽ thêm một giá trị vào một mảng, miễn là giá trị đó chưa có trong nó. Xem tài liệu $addToSet.

Cập nhật

Từ bài gốc của bạn:

Tôi đang cố gắng để cập nhật tài khoản mỗi khi người dùng thêm một hình mới. Vì vậy, trong trường hợp này tôi có thể sử dụng $ đẩy tốt. Nhưng tôi không muốn tên trùng lặp, và $ đẩy không thành công ở đây.

var uniqueAccount = { 
    name:'unique account', 
    credentials: { 
    username:'new username', 
    password:'some secret password' 
    } 
}; 

db.accounts.update({fbId: fbId, token: token}, 
    {accounts: {$addToSet: uniqueAccount}}); 
+0

Vâng, nhưng nếu nó đã tồn tại, nó sẽ không cập nhật nó. – zafrani

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