몽구스를 통해 아이템을 몽고 배열로 푸시


185

나는 대답을 찾기 위해 약간을 닦았지만, 내가 따르는 것을 설명하기 위해 올바른 단어를 잃어 버릴 것이라고 확신합니다.

기본적으로 'people'라는 mongodb 컬렉션이 있습니다. 해당 컬렉션의 스키마는 다음과 같습니다.

people: {
         name: String, 
         friends: [{firstName: String, lastName: String}]
        }

이제 데이터베이스에 연결하고 빈 friends 배열로 'people'을 성공적으로 만드는 매우 기본적인 Express 응용 프로그램이 있습니다.

응용 프로그램의 보조 장소에는 친구를 추가 할 수있는 양식이 있습니다. 양식은 firstName과 lastName을 취한 다음 적절한 사람 오브젝트를 참조하기 위해 name 필드를 가진 POST를 취합니다.

내가 겪고있는 일은 새로운 친구 개체를 만든 다음 그것을 friends 배열에 "푸시"하는 것입니다.

mongo 콘솔을 통해이 작업을 수행 할 때 조회 기준 후 두 번째 인수로 $ push와 함께 업데이트 기능을 사용하지만 mongoose 가이를 수행하는 적절한 방법을 찾지 못하는 것 같습니다.

db.people.update({name: "John"}, {$push: {friends: {firstName: "Harry", lastName: "Potter"}}});

업데이트 : Adrian의 답변은 매우 도움이되었습니다. 다음은 목표를 달성하기 위해 내가 한 일입니다.

내 app.js 파일에서 다음을 사용하여 임시 경로를 설정했습니다.

app.get('/addfriend', users.addFriend);

users.js 파일의 어디에

exports.addFriend = function (req, res, next)
{
var friend = {"firstName": req.body.fName, "lastName": req.body.lName};
Users.findOneAndUpdate({name: req.user.name}, {$push: {friends: friend}});
};

잠재적으로 collections.findOneAndUpdate ()를 사용할 수 있지만 어디에서 구현할 지 잘 모르겠습니다. 내 모델에서?
Neurax

답변:


282

가정의 방, var friend = { firstName: 'Harry', lastName: 'Potter' };

두 가지 옵션이 있습니다.

모델 내 메모리를 업데이트하고 저장하십시오 (일반 자바 스크립트 array.push).

person.friends.push(friend);
person.save(done);

또는

PersonModel.update(
    { _id: person._id }, 
    { $push: { friends: friend } },
    done
);

몽구스가 제공하는 많은 이점 (후크, 유효성 검사 등)을 존중하기 때문에 가능한 한 항상 첫 번째 옵션을 찾으려고 노력합니다.

그러나 동시 쓰기를 많이 수행하는 경우 매번 전체 모델을 교체하지 않고 추가 한 이전 친구를 잃지 않도록 불쾌한 버전 오류가 발생하는 경쟁 조건이 발생합니다. 절대적으로 필요한 경우에만 전자에게 가십시오.


1
동시 쓰기 방지 측면에서 두 번째 옵션이 실제로 더 안전한 옵션이라고 생각 했습니까? 전직을 말할 때 실수로 후자를 말했습니까?
윌 브릭 너

37
그래, 난 그냥 확인하고 (년 11 월 2017 년) IS 안전 몽구스 사용하는 update동안, 기능 지지 않습니다 안전 , 문서를 찾기 위해 메모리에 수정 한 다음 전화를 .save()문서에 방법을. 작업이 '안전'하다고 말하면 문서에 하나, 둘 또는 50 개의 변경 사항이 적용 되더라도 모든 변경 사항이 성공적으로 적용되고 업데이트 동작이 예상대로 수행됩니다. 오래된 문서에서 작업 할 수 있기 때문에 기본적으로 메모리 내 조작은 안전하지 않으므로 저장할 때 가져 오기 단계 후에 발생한 변경 사항이 손실됩니다.
윌 브릭 너

2
@Will Brickner의 일반적인 워크 플로는 논리를 재시도 루프로 래핑하는 것입니다 (재시도 가능에는 페치, 수정, 저장 포함). VersionError (낙관적 잠금 예외)가 다시 발생하면 해당 작업을 몇 번 다시 시도하고 매번 새 복사본을 가져올 수 있습니다. 그래도 가능하면 여전히 원자 업데이트를 선호합니다!
애드리안 슈나이더

8
@ZackOfAllTrades 나도 혼란 스럽지만 콜백 함수가 완료되었다고 생각합니다. let done = function(err, result) { // this runs after the mongoose operation }
사용자

콜백에서 친구 개체의 ID를 얻는 방법은 무엇입니까?
Dee Nix

41

$ 누름 조작 배열로 지정된 값을 추가한다.

{ $push: { <field1>: <value1>, ... } }

$ push 는 값을 요소로하여 배열 필드를 추가합니다.

위의 답변은 모든 요구 사항을 충족하지만 다음을 수행하여 작동시킵니다.

var objFriends = { fname:"fname",lname:"lname",surname:"surname" };
Friend.findOneAndUpdate(
   { _id: req.body.id }, 
   { $push: { friends: objFriends  } },
  function (error, success) {
        if (error) {
            console.log(error);
        } else {
            console.log(success);
        }
    });
)

이것이 내가 작동하는 것으로 밝혀 졌으므로 2019 년 현재 가장 최신이라고 생각합니다. 가장 좋은 대답은 어떤면에서 부족하고 아마도 불완전한 / 구식이라고 생각합니다.
Cheesus Toast

코드에 약간의 오류가있을 수 있음을 알려 드리겠습니다. 내 프로젝트에 올바른 변수를 넣었 기 때문에 작동했습니다. Friend.findOneAndUpdate ()가있는 곳은 People.findOneAndUpdate () 여야한다고 생각합니다. 그것은 원래의 질문에 더 부합 할 것입니다. 나는 당신을 위해 그것을 편집 할 수는 있지만 내가 틀렸다면 (나는 노드 / 표현에 약간 익숙하다.) 두 번 확인하기를 원한다.
Cheesus Toast 2018 년

@CheesusToast 내가 틀렸다면 답을 바꿀 수 있다고 생각합니다. 나는 나를 위해 잘 작동하는이 대답을 넣었습니다. 그러나이 답변을 잘못 발견하면이 답변을 변경할 수 있으며 나에게 정정 해 주시면 기쁠 것입니다 :-).
Parth Raval 5

1
좋습니다, 문제 없습니다. 어쨌든 작은 편집이었습니다. 어쨌든 시청자가 어쨌든 어레이를 밀었던 곳에서 운동했을 것이기 때문에 일종의 까다 롭습니다. 나는 아직도 이것이 최선의 대답이라고 생각합니다 :)
Cheesus Toast

9

$push문서를 업데이트하고 배열 안에 새로운 값을 삽입하는 데 사용 합니다.

찾기:

db.getCollection('noti').find({})

찾기 결과 :

{
    "_id" : ObjectId("5bc061f05a4c0511a9252e88"),
    "count" : 1.0,
    "color" : "green",
    "icon" : "circle",
    "graph" : [ 
        {
            "date" : ISODate("2018-10-24T08:55:13.331Z"),
            "count" : 2.0
        }
    ],
    "name" : "online visitor",
    "read" : false,
    "date" : ISODate("2018-10-12T08:57:20.853Z"),
    "__v" : 0.0
}

최신 정보:

db.getCollection('noti').findOneAndUpdate(
   { _id: ObjectId("5bc061f05a4c0511a9252e88") }, 
   { $push: { 
             graph: {
               "date" : ISODate("2018-10-24T08:55:13.331Z"),
               "count" : 3.0
               }  
           } 
   })

업데이트 결과 :

{
    "_id" : ObjectId("5bc061f05a4c0511a9252e88"),
    "count" : 1.0,
    "color" : "green",
    "icon" : "circle",
    "graph" : [ 
        {
            "date" : ISODate("2018-10-24T08:55:13.331Z"),
            "count" : 2.0
        }, 
        {
            "date" : ISODate("2018-10-24T08:55:13.331Z"),
            "count" : 3.0
        }
    ],
    "name" : "online visitor",
    "read" : false,
    "date" : ISODate("2018-10-12T08:57:20.853Z"),
    "__v" : 0.0
}

2

이를 수행하는 쉬운 방법은 다음을 사용하는 것입니다.

var John = people.findOne({name: "John"});
John.friends.push({firstName: "Harry", lastName: "Potter"});
John.save();

0

제 경우에는 이렇게했습니다

  const eventId = event.id;
  User.findByIdAndUpdate(id, { $push: { createdEvents: eventId } }).exec();

-3

나는이 문제에 부딪쳤다. 내 수정은 자식 스키마를 만드는 것이 었습니다. 모델의 예는 아래를 참조하십시오.

---- 사람 모델

const mongoose = require('mongoose');
const SingleFriend = require('./SingleFriend');
const Schema   = mongoose.Schema;

const productSchema = new Schema({
  friends    : [SingleFriend.schema]
});

module.exports = mongoose.model('Person', personSchema);

*** 중요 : SingleFriend.schema-> 스키마에 소문자를 사용해야합니다

--- 자식 스키마

const mongoose = require('mongoose');
const Schema   = mongoose.Schema;

const SingleFriendSchema = new Schema({
  Name: String
});

module.exports = mongoose.model('SingleFriend', SingleFriendSchema);

downvote의 이유는 아마도 이것이 필요하지 않기 때문입니다. Parth Raval의 대답은 충분합니다.
Cheesus Toast
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.