更新用户个人资料时,某些信息将从DB,Mongodb中删除

时间:2019-03-21 08:39:48

标签: node.js mongodb express mongoose

当我更新用户配置文件时,将删除用户模型中位置内部的字段附近,这是我的用户模型,您可以在其中看到附近位置的内部区域:

const userSchema = new Schema({

  name: {
    type: String,
    required: 'Please supply a name',
    trim: true
  },
   location: {
    type: {
      type: String,
      default: 'Point'
    },
    coordinates: [{
      type: Number,
      required: 'You must supply coordinates!'
    }],
    address: {
      type: String,
      required: 'You must supply an address!'
    },
    vicinity: {
      type: String,
    },
  },
});

然后我有一个用于更新用户的控制器,我有一个更新对象,附近不th,因为我不想更新它,我只是想在寄存器中保存附近,而不是更新它:

exports.updateAccount = async (req, res) => {
  req.body.location.type = 'Point';

  const updates = {
    email: req.body.email,
    name: req.body.name,
    photo: req.body.photo,
    genres: req.body.genres,
    musicLinks: req.body.musicLinks,
    location: {
      type: req.body.location.type,
      coordinates: [
        req.body.location.coordinates[0],
        req.body.location.coordinates[1],
      ],
      address: req.body.location.address,
      // vicinity: req.body.location.vicinity,
    }
  };

  if(!updates.photo) delete updates.photo

  const user = await User.findOneAndUpdate(
    { _id: req.user._id },
    { $set: updates },
    { new: true, runValidators: true, context: 'query' }
  );
  req.flash('success', 'Updated the profile!');
  res.redirect('back');
};

但是,每次我更新用户个人资料时,附近区域都会被删除,还请注意,在我为用户提交更新的表单中,没有附近区域,因此它不发送任何要更新的数据。 / p>

我猜是因为在控制器上我有一个更新对象,如:

 location: {
      type: req.body.location.type,
      coordinates: [
        req.body.location.coordinates[0],
        req.body.location.coordinates[1],
      ],
      address: req.body.location.address,
      // vicinity: req.body.location.vicinity,
    }

及其缺失的附近。数据库会尝试保存整个位置对象,并且由于没有附近而被删除。

如果是这种情况..我如何对mongo db保留该值而不删除它?谢谢

2 个答案:

答案 0 :(得分:2)

之所以会这样,是因为您实际上是在用新对象更新location字段。 location对象下的每个键都将被擦除然后重新写入-这就是vicinity丢失的原因。

要实现目标,可以使用嵌套键语法:

const updates = {
  $set: {
    email: req.body.email,
    name: req.body.name,
    photo: req.body.photo,
    genres: req.body.genres,
    musicLinks: req.body.musicLinks,
    'location.type': req.body.location.type,
    'location.coordinates': [req.body.location.coordinates[0], req.body.location.coordinates[1]],
    'location.address': req.body.location.address,
  }
};

之后:

const user = await User.findOneAndUpdate(
  { _id: req.user._id },
  updates,
  { new: true, runValidators: true, context: 'query' }
);

答案 1 :(得分:1)

这是设计使然。

实际上,您在$set的参数中包含了location的“完整对象”,而这样做只是覆盖该对象。基本上,这就是MongoDB的工作方式。

MongoDB工作原理的另一部分是当您打算部分使用“嵌套路径”更新文档时,您需要将该对象结构处理为"Dot Notation"形式。 / p>

实际上,这是我很久以前拼凑起来的东西的基本版本:

var data = {
    email: "bill@example.com",
    name: "Bill S Preston",
    photo: "",
    genres: "Music, Lyrics",
    musicLinks: "",
    location: {
      type: "Point",
      coordinates: [
        0,
        0
      ],
      address: "somewhere"
    }
};

一个简单的功能:

function dotNotate(obj,target,prefix) {
  target = target || {},
  prefix = prefix || "";

  Object.keys(obj).forEach(function(key) {
    if ( Array.isArray(obj[key] )) {
      return target[prefix + key] = obj[key];
    } else if ( typeof(obj[key]) === "object" ) {
      dotNotate(obj[key],target,prefix + key + ".");
    } else {
      return target[prefix + key] = obj[key];
    }
  });

  return target;
}

运行该函数会产生:

var updates = dotNotate(data);

{
        "email" : "bill@example.com",
        "name" : "Bill S Preston",
        "photo" : "",
        "genres" : "Music, Lyrics",
        "musicLinks" : "",
        "location.type" : "Point",
        "location.coordinates" : [
                0,
                0
        ],
        "location.address" : "somewhere"
}

当然,{ $set: updates }仅会部分更新明确指定的字段而不会被覆盖。