Вставить в определенный индекс для массива mongo
Mongo поддерживает массивы документов внутри документов. Например, что-то вроде
{_id: 10, "coll": [1, 2, 3] }
Теперь представьте, что я хотел вставить произвольное значение при произвольном индексе
{_id: 10, "coll": [1, {name: 'new val'}, 2, 3] }
Я знаю, что вы можете обновлять значения с помощью $и $set, но ничего для вставки. это отстой, чтобы заменить весь массив только для вставки с определенным индексом.
Ответы
Ответ 1
Начиная с версии 2.6, вы, наконец, можете это сделать. Вы должны использовать оператор $position. Для вашего конкретного примера:
db.students.update(
{ _id: 10},
{ $push: {
coll: {
$each: [ {name: 'new val'} ],
$position: 1
}
}}
)
Ответ 2
Следующее выполнит трюк:
var insertPosition = 1;
var newItem = {name: 'new val'};
db.myCollection.find({_id: 10}).forEach(function(item)
{
item.coll = item.coll.slice(0, insertPosition).concat(newItem, item.coll.slice(insertPosition));
db.myCollection.save(item);
});
Если insertPosition
является переменной (т.е. вы точно не знаете, куда вы хотите вставить его, но знаете, что хотите вставить его после элемента с name = "foo"
, просто добавьте цикл for()
до item.coll =
, чтобы найти insertPosition (и добавить 1 к нему, так как вы хотите вставить его ПОСЛЕ name = "foo"
).
Ответ 3
Удобный ответ (не выбран ответ, но самый высокий рейтинг) из этого похожего сообщения:
У вас есть mongo $push preend вместо append?
использует $set для вставки 3 в первую позицию в массиве, называемый "array". Пример из соответствующего ответа Сергея Никитина:
db.test.update({"_id" : ObjectId("513ad0f8afdfe1e6736e49eb")},
{'$set': {'array.-1': 3}})
Ответ 4
Относительно вашего комментария:
Ну.. с параллельными пользователями это будет проблематично с любой базой данных...
Я бы сделал следующее:
Добавьте в документ последнюю измененную временную метку. Загрузите документ, позвольте пользователю изменить его и использовать временную метку в качестве фильтра при обновлении документа, а также обновить метку времени за один шаг. Если он обновляет 0 документов, вы знаете, что он был изменен тем временем, и вы можете попросить пользователя перезагрузить его.
Ответ 5
Используя оператор $position, это можно сделать, начиная с версии 2.5.3.
Он должен использоваться с каждым оператором $. Из документация:
db.collection.update( <query>,
{ $push: {
<field>: {
$each: [ <value1>, <value2>, ... ],
$position: <num>
}
}
}
)