MongoDB: слишком много позиционных (то есть "$" ) элементов, найденных в пути

Я только что обновился до Mongo 2.6.1, и один оператор обновления, который работал раньше, не возвращает ошибку. Оператор обновления:

db.post.update( { 'answers.comments.name': 'jeff' },
    { '$set': {
        'answers.$.comments.$.name': 'joe'
    }},
    { multi: true }
)

Ошибка, которую я получаю:

WriteResult({
    "nMatched" : 0,
    "nUpserted" : 0,
    "nModified" : 0,
    "writeError" : {
        "code" : 2,
        "errmsg" : "Too many positional (i.e. '$') elements found in path 'answers.$.comments.$.createUsername'"
    }
})

Когда я обновляю элемент только на один уровень, а не на два (т.е. answers.$.name вместо answers.$.comments.$.name), он отлично работает. Если я уменьшу свой экземпляр mongo ниже 2.6, он также отлично работает.

Ответ 1

Оператор позиционирования может использоваться только один раз в запросе. Это ограничение, есть открытый билет для улучшения: https://jira.mongodb.org/browse/SERVER-831

Ответ 2

Я столкнулся с той же проблемой, так как массив внутри массива требует значительного влияния на производительность. Таким образом, mongo db не поддерживает его. Переработайте свою базу данных, как показано в приведенной ссылке ниже.

https://pythonolyk.wordpress.com/2016/01/17/mongodb-update-nested-array-using-positional-operator/

Ответ 3

Как упоминалось; на данный момент не поддерживается более одного позиционного элемента. Вы можете обновить с помощью метода mongodb cursor.forEach().

db.post
  .find({"answers.comments.name": "jeff"})
  .forEach(function(post) {
    if (post.answers) {
      post.answers.forEach(function(answer) {
        if (answer.comments) {
          answer.comments.forEach(function(comment) {
            if (comment.name === "jeff") {
              comment.name = "joe";
            }
          });
        }
      });

      db.post.save(post);
    }
  });

Ответ 4

db.post.update( { 'answers.comments.name': 'jeff' },
    { '$set': {
        'answers.$.comments.$.name': 'joe'
    }},
    { multi: true }
)

Ответ

db.post.update( { 'answers.comments.name': 'jeff' },
    { '$set': {
        'answers.0.comments.1.name': 'joe'
    }},
    { multi: true }
)