Свяжите две базы данных Мангуста в приложении Express - PullRequest
0 голосов
/ 20 февраля 2019

У меня есть две схемы DB mongoose: User и Profile:

var userSchema = new mongoose.Schema({
    username: String,
    password: String,
    type:     String
});

userSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User", userSchema);

var profileSchema = new mongoose.Schema({
    username: { 
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User'
    },
    email: { 
        type: String,
        default: ""
    },
    skill: { 
        type: String,
        default: ""
    }
});

module.exports = mongoose.model("Profile", profileSchema);

Сначала я регистрирую и аутентифицирую пользователя, используя passport-js, и, если это успешно, я хочу создать Profile db с username и type.Затем я разрешу пользователям обновлять этот Profile дБ (но не Users).После документов я пытаюсь использовать .populate, чтобы создать запись в Profile с той же информацией, что и в User:

router.post("/signup", function(req, res) {
    var newUser = new User({username: req.body.username, type: req.body.type});

    User.register(newUser, req.body.password, function(err, user){
        if(err){
            console.log(err.message);
            return res.render("signup");
        }
        passport.authenticate("local")(req, res, function(){
            Profile.findById(newUser._id).populate("username").exec(function(err, foundUser){
                if(err){
                    console.log("Problem populating the profiles DB");
                }
                else{
                    console.log("New user:" + newUser._id);
                    res.redirect("profile/" + newUser._id);
                }
            });
        });
    });
});

Это проходит без ошибок,но мой Profiles дБ пуст.

Кто-нибудь может увидеть, что я здесь делаю не так?

Я также пытался (по тому же маршруту):

Profile.create(newUser, function(err, newlyCreated){
    if(err){
        console.log(err);
    } else {
        console.log("Added user to profile db:" + newUser._id);
        console.log("New user:" + newUser._id);
        res.redirect("profile/" + newUser._id);
     }
 });

Но это не с ошибкой:

{ DocumentNotFoundError: No document found for query "{ _id: 5c6d9512a4a301b73b565681 }"

Еще один подход, который я пробую, заключается в следующем:

Profile.create({username:req.body.username, type: req.body.type}, function(err, pro){
  if(err){
      console.log("Profile error: " + err);
  } else {
      console.log("Added user to profile db:" + newUser._id);
      console.log("New user:" + newUser._id);
      res.redirect("profile/" + newUser._id);
  }
});

, который проходит, но создает запись в Profiles с _id отличается от соответствующей записи в Users.

Кто-нибудь сможет указать мне правильное направление?

1 Ответ

0 голосов
/ 20 февраля 2019

Некоторые части вашего кода проблематичны.

Вы позвонили newUser._id, однако newUser является экземпляром модели mongoose User.Поле _id создается MongoDB при сохранении документа в БД, поэтому логично, что поле не заполняется при создании экземпляра объекта.Он создается при сохранении его в БД.Таким образом, вы можете получить правильный _id на user._id, с user из обратного вызова.

router.post("/signup", function(req, res) {
    var newUser = new User({username: req.body.username, type: req.body.type});

    User.register(newUser, req.body.password, function(err, user){
        if(err){
            console.log(err.message);
            return res.render("signup");
        }
        passport.authenticate("local")(req, res, function(){
            Profile.findById(user._id).populate("username").exec(function(err, foundUser){
                if(err){
                    console.log("Problem populating the profiles DB");
                }
                else{
                    console.log("New user:" + user._id);
                    res.redirect("profile/" + user._id);
                }
            });
        });
    });
});

Более того, в вашем коде есть странные части:

  • Вы не создаете новый профиль в своей коллекции profiles при создании пользователя.Итак, как вы думаете, он может найти документ, который не был создан.
  • Вы вызываете .findById в Профиле и передаете ему _id из пользовательского документа, тогда как это не _id этого БД, поэтому нет документа с запрашиваемым _id вэта коллекция.
  • Вы должны запросить Profile.findOne({username: user.name}) и затем попытаться заполнить поле: Profile.findOne({username: user.name}).populate('user') с profile.user = user._id при сохранении профиля.
  • Более того, если у вас могут быть конфликты имен пользователей, вам следует использовать user._id для поиска связанных документов, поэтому сохраните уникальное значение в своем профиле, чтобы легко его найти.

Итак, ваша схема должна выглядеть немного иначе:

var profileSchema = new mongoose.Schema({
    user: { 
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User'
    },
    email: { 
        type: String,
        default: ""
    },
    skill: { 
        type: String,
        default: ""
    }
});

, и при заполнении этого вызова Profile.findOne({user: user._id}).populate('user') в результате вы получите:

{
    user: {
        username,
        password,
        type
    },
    email,
    skill
}

Помните:

  • Вы не можете назначить строку для mongoose.Schema.Types.ObjectId,
  • Не забудьте создать профиль при создании пользователя и ссылаться на user._id внутри вашего profile.userАтрибут.
  • Collection.findById(id) будет искать документ внутри коллекции с document._id === id
  • Если вы хотите заполнить поле, которое не введено в качестве objectIdВы должны определить virtual .Документ Mongoose хорошо объясняет это: https://mongoosejs.com/docs/populate.html#populate-virtuals
  • Если вы не хотите отправлять пароль при заполнении, вы можете ограничить поля: Profile.findOne({user user._id}).populate({path: 'user', select: "-password"}).Этот запрос удалит поле пароля, чтобы уменьшить риск утечки данных.
...