몽구스, 객체 배열의 값 업데이트


94

개체의 값을 업데이트하는 방법이 있습니까?

{
  _id: 1,
  name: 'John Smith',
  items: [{
     id: 1,
     name: 'item 1',
     value: 'one'
  },{
     id: 2,
     name: 'item 2',
     value: 'two'
  }]
}

id = 2 인 항목의 이름과 값 항목을 업데이트하고 싶다고 가정 해 보겠습니다.

나는 몽구스와 함께 다음을 시도했습니다.

var update = {name: 'updated item2', value: 'two updated'};
Person.update({'items.id': 2}, {'$set':  {'items.$': update}}, function(err) { ...

이 접근 방식의 문제점은 전체 개체를 업데이트 / 설정한다는 것이므로이 경우에는 id 필드가 손실됩니다.

몽구스에서 배열의 특정 값을 설정하고 다른 값은 그대로 두는 더 좋은 방법이 있습니까?

나는 또한 Person에 대해 쿼리했습니다.

Person.find({...}, function(err, person) {
  person.items ..... // I might be able to search through all the items here and find item with id 2 then update the values I want and call person.save().
});

답변:


162

당신은 가깝습니다. $업데이트 연산자 를 사용하려면 점 표기법을 사용해야 합니다.

Person.update({'items.id': 2}, {'$set': {
    'items.$.name': 'updated item2',
    'items.$.value': 'two updated'
}}, function(err) { ...

안녕하세요, 제가 정확히 할 때 당신이 제안했습니다. board.update ({_id : board._id, "users.username": req.user.username}, {$ set : { "users. $. lastViewed": new Date ()}}, function (err) {} ); 오류가 발생했습니다. 요소 ({users : [{username : "nlm", _id : ObjectId ( '583c8cc3813daa6c29f69cb0'), 상태 : "invited", role : ")를 탐색하기 위해 부분 (users.username))을 사용할 수 없습니다. 검토 자 "}]}). 내가 다르게 한 것이 있습니까?
Peter Huang

4
잘 작동합니다. 감사합니다. 그러나 항목이 배열에 없으면 항목을 만드는 방법이 있습니까?
Sergey Mell

@SergeyMell 나는 그 해결책이 될 수있다 생각하는 경우 : stackoverflow.com/a/33577318/6470918
그르 Brzęczyszczykiewicz

컬렉션의 모든 문서에서 id = 2의 이름을 어떻게 업데이트합니까?
Rod

1
배열 안에 객체 배열이 있다면 어떻게 작동할까요? 그냥 대신에 items.$.name, 당신은 items.users.$.status했습니까? 작동할까요?
Stevie Star


12

몽구스 방법이 있습니다.

const itemId = 2;
const query = {
  item._id: itemId 
};
Person.findOne(query).then(doc => {
  item = doc.items.id(itemId );
  item["name"] = "new name";
  item["value"] = "new value";
  doc.save();

  //sent respnse to client
}).catch(err => {
  console.log('Oh! Dark')
});

이 방법은 부모 문서와 배열 항목에 대해 작업을 수행하는 경우에 편리합니다.
Jeremy

5

각 문서에 대해 업데이트 연산자 $set여러 값을 설정할 수 있으므로 items배열 의 전체 객체를 바꾸는 대신 객체 의 namevalue필드를 개별적으로 설정할 수 있습니다 .

{'$set':  {'items.$.name': update.name , 'items.$.value': update.value}}

3

하나 이상의 조건을 기준으로 배열에서 객체를 검색 할 때 $ elemMatch 를 사용하는 것을 기억해야합니다.

Person.update(
   {
     _id: 5,
     grades: { $elemMatch: { grade: { $lte: 90 }, mean: { $gt: 80 } } }
   },
   { $set: { "grades.$.std" : 6 } }
)

여기에 문서가 있습니다



2

다음은 객체 배열의 값을보다 동적으로 업데이트하는 방법의 예입니다.

Person.findOneAndUpdate({_id: id}, 
{ 
  "$set": {[`items.$[outer].${propertyName}`]: value} 
},
{ 
  "arrayFilters": [{ "outer.id": itemId }]
},
function(err, response) {
  ...
})

이렇게하면 arrayFilters다음과 같이 추가하여 중첩 배열의 더 깊은 수준을 업데이트 할 수 있습니다 .

"$set": {[`items.$[outer].innerItems.$[inner].${propertyName}`]: value} 

"arrayFilters":[{ "outer.id": itemId },{ "inner.id": innerItemId }]

도움이되기를 바랍니다. 행운을 빕니다!


0

몽구스에서는 간단한 배열처럼 업데이트 할 수 있습니다.

user.updateInfoByIndex(0,"test")

User.methods.updateInfoByIndex = function(index, info) ={
    this.arrayField[index]=info
    this.save()
}

4
귀하의 답변은 몇 가지 설명에 더 도움이 될 것입니다. 편집을 고려하십시오.
O. Jones

0

Mongoose에서는 다음과 같이 $setdot ( .) 표기법을 사용하여 배열 값 을 특정 값으로 업데이트 할 수 있습니다.

db.collection.update({"_id": args._id, "viewData._id": widgetId}, {$set: {"viewData.$.widgetData": widgetDoc.widgetData}})

설명과 함께 답변을 수정 하시겠습니까, 아니면 질문과 관련이 있습니까?
NIKHIL CM

1
내 질문을 살펴볼 수 있습니까? mongoose는 CLI에서 작동하지만 $ []를 사용하는 내 쿼리 부분을 제거하고 있습니다. stackoverflow.com/questions/64223672/…
nrmad

0

잘 작동하는 다른 솔루션을 시도했지만 대답의 함정은 이미 존재하는 필드 만 업데이트하면 upsert를 추가하면 아무것도하지 않으므로 이것을 생각해 냈습니다.

 Person.update({'items.id': 2}, {$set: {
    'items': { "item1",  "item2",  "item3",  "item4" } }, {upsert: 
true })
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.