Я видел этот вопрос и данный ответ, но я не думал, что он действительно объясняет то, что вы спросили, поэтому я подумал, что здесь что-то стоит.
Как показано в предоставленной схеме, свойство «topics» представляет собой «ссылочный массив», что в основном означает, что оно будет содержать «ссылку» (или, по сути, значение ObjectId
) на документ, который находится в другой коллекции. Как вы должны знать, определение «схемы» мангуста связывает это с «ассоциированной» моделью, в которой находится этот объект.
Поставленный вопрос: «Нажимаю ли я объект или просто нажимаю значение _id
», что само по себе вызывает некоторые вопросы о том, «что вы действительно хотите здесь делать?».
Для последнего примера возьмите следующий пример кода (предполагая, что модель и схема определены):
var project = new Project({ "name": "something" });
var topic = new Topic({ "name": "something" });
project.topics.push(topic); // this actually just adds _id since it's a ref
// More code to save topic and project in their colllections
Итак, согласно комментарию в коде, мангуст на самом деле только добавляет значение «_id» в родительский документ, даже если вы попросили его «подтолкнуть» весь «объект». Просто получается, что «это то, что вы хотели сделать» через представленный интерфейс схемы к модели. На самом деле это не сложно сделать в коде, просто чтобы вы понимали основную механику.
В качестве альтернативы вы можете «просто использовать значение _id
» из созданного объекта (после того, как оно будет лучше всего сохранено в целях безопасности) и добавить его в массив аналогичным образом. Это почти тот же результат:
var project = new Project({ "name": "something" });
// Yes we saved the Project object, but later...
var topic = new Topic({ "name": "something" });
topic.save(function(err,topic) {
if (err) throw (err): // or better handling
project.topics.push(topic._id); // explicit _id
});
Этот метод хорош, если, конечно, в той или иной форме у вас действительно есть «Объекты в памяти» во время обработки как для Project
, так и для Topic
с соответствующими данными.
С другой стороны, давайте предположим, что Project
представляет собой объект, который находится в коллекции, и хотя вы знаете, что это _id
значение или другое «уникальное» представляющее свойство, данные этого объекта фактически не были загружены из базы данных с помощью .findOne()
типа операции. или похожие.
Давайте тогда предположим, что у вас нет резидентных данных модели Project
в памяти. Итак, как добавить новую тему?
Здесь в игру вступают нативные операторы для MongoDB. В частности, есть $push
, который Конечно, аналогично оператору массива .push()
в JavaScript, но с особым действием «на стороне сервера».
Как указывалось ранее, у вас нет загруженных данных модели Project
, но вы хотите изменить конкретный элемент Project
в хранилище, «подтолкнув» желаемый объект Topic
к чему-то, определенному в вашей коллекции объектов Project
по его идентификатору:
var topic = new Topic({ "name": "something" });
topic.save(function(err,topic) {
if (err) throw err; // or much better handling
Project.update(
{ "_id": projectId },
{ "$push": {
"topics": topic._id
}},
function(err,numAffected) {
// and handle responses here
}
);
})
Механика «обновления» может быть .findOneAndUpdate()
или даже .findByIdAndUpdate()
по вашему усмотрению (оба этих метода возвращают измененный объект по умолчанию, где .update()
нет) к тому, чего вы хотите достичь в результате вашей операции здесь.
Основное отличие от предыдущих подходов заключается в том, что, поскольку объект для Project
, который необходимо изменить, не находится в памяти кода вашего приложения, вы используете эти методы, чтобы просто изменить его на сервере. Это может быть "хорошо", так как вам не нужно "загружать" эти данные только для внесения изменений. Операторы MongoDB позволяют вам $push
загружать содержимое массива без предварительной загрузки.
Этот подход на самом деле является лучшим подходом для «одновременных обновлений» с системами с высоким уровнем транзакций. Причина в том, что «нет гарантии», что между .findOne()
или подобной операцией в вашем приложении и модификациями с возможным действием .save()
«данные не были изменены» в хранилище сервера между этими действиями.
Оператор $push
«обеспечивает», чтобы данные, измененные на сервере, оставались «такими, какими они были» во время выполнения с, конечно, добавлением новых данных, которые вы добавили в массив.
Другая очевидная вещь здесь заключается в том, что, поскольку операция использует собственный оператор MongoDB для достижения этой эффективности, правила схемы мангуста игнорируются. Таким образом, вы, конечно, не можете просто «втолкнуть» весь объект «темы» в массив, не получая, конечно, «целого» объекта темы в хранилище:
Project.update(
{ "_id": projectId },
{ "$push": {
"topics": topic // Oops, now that would store the whole object!
}},
function(err,numAffected) {
// and handle responses here
}
);
По сути, в этом разница между «добавлением ссылки на объект» в массив и «добавлением объекта в массив». Это зависит от используемых методов и методов «эффективности», которые вы на самом деле выбираете.
Надеюсь, это будет полезно вам и тем, кто может наткнуться на ту же тему, которую вы подняли.
person
Blakes Seven
schedule
24.06.2015