Py学习  »  MongoDB

更新用户配置文件时,某些信息会从db、mongodb中删除。

Giorgio Martini • 6 年前 • 1763 次点击  

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

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,
    },
  },
});

然后我有一个控制器来更新用户,在那里我有一个更新对象,并且附近不是三个,因为我不想更新它,我只想在寄存器上保存附近,而不是更新它:

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');
};

但每次更新用户配置文件时,邻近字段都会被删除,同时请注意,在我为用户提交更新的表单中,邻近字段没有字段,因此它不会发送任何要更新的数据。

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

 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,
    }

以及它缺失的向量性。数据库试图保存整个location对象,因为它不在附近,所以会被删除。

如果是这样的话……我怎么跟mongo db说保留db上的值而不删除它?谢谢

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/39013
文章 [ 2 ]  |  最新文章 6 年前
Neil Lunn
Reply   •   1 楼
Neil Lunn    6 年前

这是按设计的。

你实际上包括一个“完整的对象” location 在你的论点中 $set ,还有这个 简单地 覆盖 那个物体。这就是MongoDB的工作原理。

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

事实上,这里有一个我很久以前收集到的东西的基本版本:

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 } 只会 部分更新 未覆盖的显式指定的字段。

Vladyslav Usenko
Reply   •   2 楼
Vladyslav Usenko    6 年前

你这样做的原因是你实际上在更新 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' }
);