Мое приложение становится немного кошмаром, и это нестандартная проблема MongoDB, которую я не смог найти в другом месте.Как предотвратить MongoDB от создания нескольких записей из-за async
Мой поток сервера, как это:
- Пользователь загружает список объектов, содержащих
{names, emails and company domains}
на мой сервер - Мой сервер превращает все это в
Person
объектов. - Как только
Person
был сохранен, я ищу MongoDB, чтобы узнать, существует ли запись для человекаDomain
. - Если он существует, я добавляю Mongo
Person
Mongo_id
к списку пользователей отDomain
. - Если он не существует, я создаю новый документ
Domain
и сохраняю его.
Это работает теоретически, НО, из-за Async, иногда я отправляю тысячи объектов Person
в функцию сохранения домена одновременно. Что означает (по крайней мере, то, что я думаю, что происходит):
- Mongo поисковики для «домена 1», видит, что нет документа, поэтому он создает один, а затем сохраняет его.
- Пока это все еще происходит, Монго ищет «Домен 1» от отдельного пользователя. Документ еще не сохранен, поэтому он не находит и делает новый.
- Теперь у меня есть два документа с тем же идентификатором домена.
Вот код, который я сейчас использую:
Domain.findOne({
domain: domn
}, function(err, rec) {
if (err) {
console.log("Domain finding error: " + err)
bigCount.doneDoms++;
checkCount()
} else if (rec){
var tempObj = {}
tempObj['$addToSet'] = { users: id }
tempObj['$addToSet'].emails = user.email;
if (userDoms.indexOf(rec._id) === -1) {
userDoms.push(rec._id)
}
Domain.update({domain: domn}, tempObj, function(err) {
if (err) {
console.log("Old rec save Error: " + err)
bigCount.doneDoms++;
checkCount();
}else{
// Saved Document
}
});
} else {
var newDom = new Domain();
newDom.domain = user.domain;
newDom.company = user.company;
newDom.users = [];
newDom.users.push(id);
newDom.emails = [];
newDom.emails.push(user.email);
newDom.save(function(err, record) {
if (err) {
console.log("Dom save error: " + err)
} else {
// Saved Document
}
});
}
})
Возможно, урезанная версия вопрос, как я могу справиться somethign так:
var arr = [{dom: 'dom1.com', user: 'James'}, {dom: 'dom1.com', user: "Phil"}, {dom: 'dom1.com', user: "Jess"} ...x1000... {dom: 'dom1.com', user: "Chris"];
for(var i - 0; i< arr.length; i++){
var dom = arr[i]; var user = arr[i].user;
Domain.findOne({domain: dom}, function(err, rec){
if(rec){
// Update old rec
if(rec.users.indexOf(user) === -1){
rec.users.push(user);
}
rec.save();
]else{
// Make a new rec
var rec = New Domain();
rec.users = [user]
rec.save();
}
})
}
Благодаря скорость/Async, здесь будет создано множество записей, когда действительно я хочу только один
Большое спасибо за подробный ответ. Хотя, я должен сказать, я * думал *, я следовал принципам, которые вы описываете. Я создал суть моего кода здесь: https://gist.github.com/jascination/327a9b11c213bb53b79e Это основано на нижеприведенном предложении 'async', но независимо от того, Async все еще создает несколько объектов, которые содержат одни и те же данные (кроме некоторых, есть только один адрес электронной почты в «электронных письмах», в то время как другие имеют все соответствующие письма) – Jascination
@Jascination Если вы следите за тем, что делается в этом ответе, у вас не будет таких проблем. Как сказано, использование '.findOneAndUpate()' с «uspert» в том же шаблоне не может привести к дублированию записей. Это основной принцип разработки, который невозможен при таком шаблоне. –