2015-06-24 4 views
2

Я новичок в Mongoose и получаю голову вокруг популяций. У меня есть схемы, которая выглядит как ...Добавить для сравнения Население в модели Mongoose

var ProjectSchema = new Schema({ 
    name: { 
     type: String, 
     default: '', 
     required: 'Please fill Project name', 
     trim: true 
    }, 
    created: { 
     type: Date, 
     default: Date.now 
    }, 
    topics: [{ 
     type: Schema.ObjectId, 
     ref: 'Topic' 
    }] 
}); 

Когда я запрашивая проектов я использую .populate («темы») и она отлично работает. Когда проект заполняется, свойство themes хранит фактические объекты, а не ссылки.

P.S. Тема не имеет ссылки на проект (мне было трудно поддерживать отношения между собой в MongoDB).

Мой вопрос: , когда я хочу добавить объект темы к проекту. Я добавляю ObjectId или сам объект?

ответ

3

Я видел это вопрос и ответ, но я не думал, что он действительно объяснил, что вы спросили, поэтому я подумал, что здесь что-то стоит.

Как показано в прилагаемой схеме, свойство «themes» является «ссылочным массивом», который в основном означает, что он будет содержать ссылку (или, по существу, значение 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 представляет объект, который находится в коллекции, и хотя вы знаете, что это значение или другое «уникальное» представляющее свойство, данные объекта на самом деле не были загружены из базы данных через .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 
     } 
    ); 

Это, по сути, разница между «, добавив, ссылку на объект "на массив и" добавление объекта к массиву ". Это зависит от используемых методов и методов «эффективности», которые вы на самом деле выбираете.

Надеюсь, это полезно для вас самих и для тех, кто может наткнуться на ту же тему, которую вы подняли.

+0

Отличный ответ. Только то, что мне было нужно. Спасибо за разъяснения! –

+0

Hi Kira. Не могли бы вы присоединиться к этой чатовой комнате? http://chat.stackoverflow.com/rooms/95345/ –

+0

@BlakesSeven не могли бы вы выслать мне свой адрес электронной почты? Либо здесь, либо по электронной почте: [email protected] - Я хочу пригласить вас в команду MongoDB Slack, которую я создал. –

1

Вам нужно только сохранить ObjectId если Темы схемы имеет проект реф в качестве экономии рефов на другие документы работает так же, как правило, сохранить свойства, просто присвоить значение _id:

var topicSchema = Schema({ 
    _author : { type: Schema.ObjectId, ref: 'Project' }, 
    title : String  
}); 

var Topic = mongoose.model('Topic', topicSchema); 
var Project = mongoose.model('Project', projectSchema); 

var my_project = new Project({ name: 'Test Project' }); 

my_project.save(function (err) { 
    if (err) return handleError(err); 

    var topic1 = new Topic({ 
     title: "My Topic", 
     _author: my_project._id // assign the _id from the project 
    }); 

    topic1.save(function (err) { 
     if (err) return handleError(err); 
     // thats it! 
    }); 
}); 

Обратитесь к docs для получения более подробной информации.


- EDIT -

Если схема Тема не реф проекта, то вам нужно нажать на сам объект:

var Topic = mongoose.model('Topic', topicSchema); 
var Project = mongoose.model('Project', projectSchema); 

var my_project = new Project({ name: 'Test Project' }); 
var topic1 = new Topic({ 
    title: "My Topic"  
}); 

my_project.stories.push(topic1); 
my_project.save(callback); 
+1

Вы сделали здесь совершенно противоположное. Вы сохраняете ссылку на Project in Topics, пока я сохраняю список тем для проекта. Проблема заключается в том, что в интерфейсе «с заполнением» проект поставляется с полными экземплярами экземпляра. Вы предлагаете мне просто добавить Id в список, содержащий объекты? –

+1

@MikeM Ответил на предположение, что в схеме «Тема» также есть «Проект» ref. Можете ли вы обновить свой вопрос с помощью фактической схемы темы? – chridam

 Смежные вопросы

  • Нет связанных вопросов^_^