저장 후 몽구스 채우기


98

새로 저장된 개체의 작성자 필드를 수동 또는 자동으로 채울 수 없습니다. 내가 찾을 수있는 유일한 방법은 내가 이미 가지고있는 개체를 다시 쿼리하는 것입니다.

이것은 설정입니다.

var userSchema = new mongoose.Schema({   
  name: String,
});
var User = db.model('User', userSchema);

var bookSchema = new mongoose.Schema({
  _creator: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
  description: String,
});
var Book = db.model('Book', bookSchema);

여기가 제가 머리를 당기는 곳입니다

var user = new User();
user.save(function(err) {
    var book = new Book({
        _creator: user,
    });
    book.save(function(err){
        console.log(book._creator); // is just an object id
        book._creator = user; // still only attaches the object id due to Mongoose magic
        console.log(book._creator); // Again: is just an object id
        // I really want book._creator to be a user without having to go back to the db ... any suggestions?
    });
});

편집 : 최신 몽구스 가이 문제를 해결하고 채우기 기능을 추가했습니다. 새로운 답변을 참조하십시오.

답변:


138

이렇게하려면 모델의 채우기 기능을 사용할 수 있어야합니다. http://mongoosejs.com/docs/api.html#model_Model.populate 책의 저장 처리기에서 다음 대신

book._creator = user;

당신은 다음과 같이 할 것입니다.

Book.populate(book, {path:"_creator"}, function(err, book) { ... });

당신을 돕기에는 너무 늦었을 것입니다. 그러나 나는 최근에 이것에 매달 렸고 다른 사람들에게 유용 할 것입니다.


이것이 가상 속성과 함께 작동하면 좋을 것입니다. 같은creator.profile
chovy

사용자에게 일부 가상 속성이있는 경우 포함되지 않습니다.
chovy

저장하기 직전에 참조를 null로 설정하려고 할 때 몇 가지 문제가 있었지만 이것은 나를 위해 일했습니다. 저장 후 Book.populate를 호출하면 필드가 이전 참조 값으로 잘못 채워졌고 그 이유를 알 수 없습니다. DB에 성공적으로 null이 있습니다.
Daniel Flippance 2014 년

2
그리고 이것은 데이터베이스를 다시 쿼리 하지 않습니까?!
Nepoxx

9
이것은 다시 쿼리 데이터베이스입니다
bubakazouba

36

누군가가 여전히 이것을 찾고 있다면.

Mongoose 3.6은 다음과 같은 많은 멋진 기능을 도입했습니다.

book.populate('_creator', function(err) {
 console.log(book._creator);
});

또는:

Book.populate(book, '_creator', function(err) {
 console.log(book._creator);
});

https://github.com/LearnBoost/mongoose/wiki/3.6-Release-Notes#population 에서 자세히보기

그러나 이렇게하면 사용자를 다시 쿼리 할 수 ​​있습니다.

추가 쿼리없이이를 수행하는 약간의 트릭은 다음과 같습니다.

book = book.toObject();
book._creator = user;

모든 현재 답변 중 유일한 정답이 된 book._creator = user;후에 수행 save()하면 다른 모든 답변에는 추가 쿼리가 필요합니다.
Mr5o1

25

나를 위해이 솔루션은 사용하는 것이었다 execPopulate과 같이,

const t = new MyModel(value)
return t.save().then(t => t.populate('my-path').execPopulate())

3
@Francois에게 감사합니다. 당신은 제 생명을 구했습니다. 저는 이것에 대한 해결책을 찾으려고 노력했습니다. 마침내 그것을 얻었습니다.
Rupesh

21

프라 미스를 반환하는 솔루션 (콜백 없음) :

Document # populate 사용

book.populate('creator').execPopulate();

// summary
doc.populate(options);               // not executed
doc.populate(options).execPopulate() // executed, returns promise

가능한 구현

var populatedDoc = doc.populate(options).execPopulate();
var populatedDoc.then(doc => {
   ... 
});

여기에서 문서 채우기에 대해 읽어보십시오 .


좋은 물건. 감사합니다
Joel H

11

정교하게 설명하고 다른 예를 들었습니다. 이것은 저장 후 부분적으로 채워진 개체를 검색하려는 사용자에게 도움이 될 수 있습니다. 방법도 약간 다릅니다. 올바른 방법을 찾기 위해 한두 시간 이상을 보냈습니다.

  post.save(function(err) {
    if (err) {
      return res.json(500, {
        error: 'Cannot save the post'
      });
    }
    post.populate('group', 'name').populate({
      path: 'wallUser',
      select: 'name picture'
    }, function(err, doc) {
      res.json(doc);
    });
  });

9

나는 나처럼 완전한 멍청이를 위해 일을 명확히하기 위해 이것에 추가 할 것이라고 생각했습니다.

주의하지 않으면 엄청나게 혼란스러운 것은 세 가지 매우 다른 채우기 방법이 있다는 것입니다. 이들은 서로 다른 객체 (모델 대 문서)의 메소드이며, 서로 다른 입력을 취하고 서로 다른 출력을 제공합니다 (문서 대 약속).

당황한 사람들을위한 것입니다.

Document.prototype.populate ()

전체 문서를 참조하십시오.

이것은 문서에서 작동하고 문서를 반환합니다. 원래 예에서는 다음과 같습니다.

book.save(function(err, book) {
    book.populate('_creator', function(err, book) {
        // Do something
    })
});

문서에서 작동하고 문서를 반환하므로 다음과 같이 연결할 수 있습니다.

book.save(function(err, book) {
    book
    .populate('_creator')
    .populate('/* Some other ObjectID field */', function(err, book) {
        // Do something
    })
});

하지만 저처럼 어리석지 말고 이렇게하세요.

book.save(function(err, book) {
    book
    .populate('_creator')
    .populate('/* Some other ObjectID field */')
    .then(function(book) {
        // Do something
    })
});

기억하세요 : Document.prototype.populate ()는 문서를 반환하므로 말도 안됩니다. 약속을 원한다면 ...

Document.prototype.execPopulate ()

전체 문서를 참조하십시오.

이것은 문서에서 작동하지만 문서를 해결하는 약속을 반환합니다. 즉, 다음과 같이 사용할 수 있습니다.

book.save(function(err, book) {
    book
    .populate('_creator')
    .populate('/* Some other ObjectID field */')
    .execPopulate()
    .then(function(book) {
        // Do something
    })
});

그게 낫다. 마지막으로 ...

Model.populate ()

전체 문서를 참조하십시오.

이것은 모델에서 작동 하고 약속을 반환합니다. 따라서 약간 다르게 사용됩니다.

book.save(function(err, book) {
    Book // Book not book
    .populate(book, { path: '_creator'})
    .then(function(book) {
        // Do something
    })
});

다른 신규 이민자들에게 도움이 되었기를 바랍니다.


1

불행히도 이것은 아직 해결되지 않은 몽구스의 오랜 문제입니다.

https://github.com/LearnBoost/mongoose/issues/570

당신이 할 수있는 일은 당신 자신의 사용자 정의 getter / setter를 작성하는 것입니다 (그리고 별도의 속성에 real _customer 을 설정 하십시오). 예를 들면 :

var get_creator = function(val) {
    if (this.hasOwnProperty( "__creator" )) {
        return this.__creator;
    }
    return val;
};
var set_creator = function(val) {
    this.__creator = val;
    return val;
};
var bookSchema = new mongoose.Schema({
  _creator: {
     type: mongoose.Schema.Types.ObjectId,
     ref: 'User',
     get: get_creator,
     set: set_creator
  },
  description: String,
});

참고 : 나는 그것을 테스트하지 않았고 .populate순수 ID를 설정할 때 이상하게 작동 할 수 있습니다 .


문제를 해결하려고하지 않는 것 같습니다.
Pykler 2012

1
이 문제는 3.6에서 해결
mkoryak

당신은 정말이 대답은 더 이상 유효로, 이전의 가장 높은 평가 하나 허용 대답을 변경할 필요가 @Pykler
매트 플레처

1

몽구스 5.2.7

이것은 나를 위해 작동합니다 (그냥 많은 두통!)

exports.create = (req, res, next) => {
  const author = req.userData;
  const postInfo = new Post({
    author,
    content: req.body.content,
    isDraft: req.body.isDraft,
    status: req.body.status,
    title: req.body.title
  });
  postInfo.populate('author', '_id email role display_name').execPopulate();
  postInfo.save()
    .then(post => {
      res.status(200).json(post);
    }).catch(error => {
      res.status(500).json(error);
    });
};

0

아마 sth. 처럼

Book.createAsync(bookToSave).then((savedBook) => savedBook.populateAsync("creator"));

이 작업을 수행하는 가장 좋고 가장 문제가 적은 방법이 될 것입니다 (블루 버드 약속 사용).


0

결국 스키마, query_adapter, data_adapter 함수를 선언하고 미리 문자열을 채우는 커리 가능한 Promise 함수를 작성했습니다. 더 짧고 간단한 구현을 위해 더 쉽습니다.

아마도 매우 효율적이지는 않지만 실행 비트가 매우 우아하다고 생각했습니다.

github 파일 : curry_Promises.js

선언

const update_or_insert_Item = mDB.update_or_insert({
    schema : model.Item,
    fn_query_adapter : ({ no })=>{return { no }},
    fn_update_adapter : SQL_to_MDB.item,
    populate : "headgroup"
    // fn_err : (e)=>{return e},
    // fn_res : (o)=>{return o}
})

실행

Promise.all( items.map( update_or_insert_Item ) )
.catch( console.error )
.then( console.log )
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.