简体   繁体   English

子文档猫鼬中的更新字段

[英]Update field in sub document mongoose

My parent model 我的父母模特

var GameChampSchema = new Schema({
  name: String,
  gameId: { type: String, unique: true },
  status: Number,
  countPlayers: {type: Number, default: 0},
  companies: [
    {
      name: String,
      login: String,
      pass: String,
      userId: ObjectId
    }
  ],
  createdAt: {type: Date, default: Date.now},
  updateAt: Date
})

I need insert userId property in first child where he is not set 我需要在未设置第一个孩子的情况下插入userId属性

So, need this action only on parent with condition ({status: 0, countPlayers: { $lt: 10 }) 因此,仅在具有条件({status:0,countPlayers:{$ lt:10})的父对象上需要执行此操作

Since this is an embedded document it is quite easy: 由于这是一个嵌入式文档,因此非常容易:

If you want to update a document that is the first element of the array, that doesn't have a userId 如果要更新作为数组第一个元素的文档,则该文档没有 userId

db.collection.update(
    { 
        "status": 0,
        "countPlayers": {"$lt": 10 },
        "companies.userId": {"$exists": false }
    },
    { "$set": {"companies.$.userId": userId } }
)

Which would be nice, but apparently this doesn't match how MongoDB processes the logic and it considers that nothing matches if there is something in the array that does have the field present. 这将是很好,但显然这并没有匹配的MongoDB如何处理的逻辑,它认为没有什么,如果有一些 确实有现场数组中存在的匹配。 You could get that element using the aggregation framework but that doesn't help in finding the position, which we need. 可以使用聚合框架获取该元素,但这无助于找到我们需要的位置。

A simplified proposal is where there are no elements in the array at all: 一个简化的建议是数组中根本没有元素:

db.collection.update(
    { 
        "status": 0,
        "countPlayers": {"$lt": 10 },
        "companies.0": {"$exists": false }
    },
    { "$push": {"userId": userId } }
)

And that just puts a new thing on the array. 这只是在阵列上添加了新东西。

The logical thing to me is that you actually know something about this entry and you just want to set the userId field. 我的逻辑是,你确实知道一些关于这个条目,你只是想设置的userId字段。 So I would match on the login: 因此,我将在登录名上进行匹配

db.collection.update(
    { 
        "status": 0,
        "countPlayers": {"$lt": 10 },
        "companies.login": login,
    },
    { "$set": {"companies.$.userId": userId } }
)

As a final thing if this is just updating the first element in the array then we don't need to match the position, as we already know where it is: 最后,如果这只是更新数组中的第一个元素,那么我们不需要匹配位置,因为我们已经知道它在哪里:

db.collection.update(
    { 
        status: 0, 
        countPlayers: {"$lt": 10 }
    },
    { $set: { "companies.0.userId": userId  } }
)

Tracing back to my logical case, see the document structure: 追溯到我的逻辑案例,请参阅文档结构:

{ 
    "_id" : ObjectId("530de54e1f41d9f0a260d4cd"),
    "status" : 0,
    "countPlayers" : 5,
    "companies" : [ 
        { "login" : "neil" },
        { "login" : "fred", "userId" : ObjectId("530de6221f41d9f0a260d4ce") },
        { "login": "bill" },
     ] 
}

So if what you are looking for is finding "the first document where there is no userId ", then this doesn't make sense as there are several items and you already have a specific userId to update. 因此,如果您要查找的是“没有userId的第一个文档”,那么这没有意义,因为有多个项目并且您已经有要更新的特定 userId。 That means you must mean one of them. 那意味着您必须是其中之一。 How do we tell which one ? 我们如何分辨哪一个呢? It seems by the use case that you are trying to match the information that is there to an userId based on information you have. 在用例中,您似乎正在尝试根据所拥有的信息将其中的信息与userId进行匹配。

Logic says, look for the key value that you know, and update the position that matches. 逻辑说,寻找您知道的key value ,并更新匹配的位置

Just substituting the db.collection part for your model object for use with Mongoose. 只需用db.collection部分代替您的model对象即可与Mongoose一起使用。

See the documentation on $exists , as well as $set and $push for the relevant details. 有关相关详细信息,请参见$ exists以及$ set$ push的文档。

Big thanks. 太谢谢了。

I solved his problem 我解决了他的问题

exports.joinGame = function(req, res) {
  winston.info('start method');
  winston.info('header content type: %s', req.headers['content-type']);

  //достаем текущего пользователя
  var currentUser  = service.getCurrentUser(req);
  winston.info('current username %s', currentUser.username);
  //формируем запрос для поиска игры
  var gameQuery = {"status": 0, "close": false};
  gameChamp.findOne(gameQuery, {}, {sort: {"createdAt": 1 }}, function(error, game) {
    if (error) {
      winston.error('error %s', error);
      res.send(error);
    }
    //если игра нашлась
    if (game) {
      winston.info('Append current user to game: %s', game.name);
      //добавляем userId только к одной компании
      var updateFlag = false;
      for (var i=0; i<game.companies.length; i++) {
        if (!game.companies[i].userId && !updateFlag) {
          game.companies[i].userId = currentUser._id;
          updateFlag = true;
          winston.info('Credentials for current user %s', game.companies[i]);
          //если пользовател последний закрываем игру и отправляем в bw, что игра укомплектована
          if (i == (game.companies.length-1)) {
            game.close = true;
            winston.info('game %s closed', game.name);
          }
        }
      }
      //сохраняем игру в MongoDB
      game.save(function(error, game) {
        if (error) {
          winston.error('error %s', error);
          res.send(error);
        }
        if (game) {
          res.send({ game: game })
          winston.info('Append successful to game %s', game.name);
        }
      });
    }
  });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM