Чего я хочу достичь : я хочу создать автомобиль, который должен иметь правильное сопоставление с дилером, а затем сохранить этот автомобиль в списке / массиве моего фирменный документ присутствует в моей коллекции компаний в myKaarma db.
Проблема, с которой я сталкиваюсь: вся логика верна, но проблема возникает из-за асинхронной природы, хотя я использую обратные вызовы.
Я знаю проблему, но не знаю, как ее решить.
Позвольте мне объяснить, в чем проблема :
Моя companies
модель с использованием Mongoose:
// jshint node :true
"use strict";
const MONGOOSE = require("mongoose"),
DB = MONGOOSE.connection;
let companySchema = MONGOOSE.Schema({
company_name: {
type: String, required: true
},
company_location: {
type: String, require: true
},
cars: [{
model: {
type: String,required: true
},
year: {
type: Number, required: true
},
PriceInINR: {
type: Number, required: true
},
trim: {
type: String, required: true
},
engine: {
type: String, required: true
},
body: {
type: String, required: true
},
color: {
type: String, required: true
},
transmission_type: {
type: String, required: true
},
dealer_id: {
type: String, required: true
}
}]
});
let collection_name = "companies";
let CompanyModel = MONGOOSE.model(collection_name, companySchema);
createAscendingIndex_on_company_name(DB);
module.exports = CompanyModel;
// indexing at schema level --> using node js
function createAscendingIndex_on_company_name(DB, callback) {
let collection = DB.collection(collection_name);
// ? Create the index
collection.createIndex({
company_name: 1, // specifies : indexing type is ascending indexing
}, {
unique: true
}, function (err, result) {
if (err) {
console.log("error while setting up indexing on companies collection");
}
console.log("index created ", result, "<<<<<<<<", collection_name, " collection");
// callback("result");
});
}
//? NOTE : Creating indexes in MongoDB is an idempotent operation. So running db.names.createIndex({name:1}) would create the index only if it didn't already exist.
Как вы заметили, я проиндексировал и также сделал company_name
уникальным, поэтому дублирующая запись не может быть там в этом проблема
В моем коде, когда я делаю это: // ? check if the company exists : and if not then create one
, у меня проблема в том, что nodejs асинхронные и очень быстрые: [so suppose I have 5 car records]
, поэтому все пять машин фактически входят в код, где я проверяю:
CompanyModel.find({
company_name: company_name
}, (err, companies) => {.....}
и это так быстро, что все, как и все, идут одновременно, и, разумеется, такой компании сейчас нет в документе компании , поэтому все они проходят условие if
if (companies.length === 0) {...});
так что теперь, когда в моих записях есть 3 машины с одной компанией, все они входят почти одновременно и все снова проходят эти условия одновременно, но как только они преодолевают это вышеупомянутое условие, я прошу Монго создать документ компании
let company = new CompanyModel({
company_name: company_name,
company_location: company_location,
cars: [car]
});
company.save((err) => {...}
но теперь все 3 записи находятся здесь, чтобы создать новый объект компании и добавить в коллекцию. Но здесь, как только один из них создаст документ и добавит его в коллекцию, в то же самое время теперь другие два также создали свои объекты, но теперь, когда объект уже создан и добавлен, Монго выдает здесь уникальное исключение.
То, что я хотел, чтобы произошло - это когда мы нашли дубликат объекта, тогда новый автомобиль той же компании просто вставляется в массив, который есть у документа компании с полем cars
Примечание: этот сценарий имеет место только в случае, когда компания не присутствует в коллекции, но если она уже присутствует, мой код работает нормально, он успешно помещает все автомобили в cars
поле соответствующей компании.
Это функция, которая делает то, что я хочу :
function map_and_save_cars_in_garage() {
let carList = require("./test.json");
let totalCar = carList.length;
console.log(carList);
carList.forEach((carRecord, index) => {
let company_name = carRecord.make.toLowerCase();
let company_location = "USA";
// build a car
let car = {
model: carRecord.model,
year: carRecord.year,
PriceInINR: carRecord.priceInr,
trim: carRecord.trim,
engine: carRecord.engine,
body: carRecord.body,
color: carRecord.color,
transmission_type: carRecord.transmission,
dealer_id: undefined, // --> just for now
};
// ? search for the correct dealer --> for mapping
let dealer_email = "bitBattle_2018_" + carRecord.DealerID + "_@myKarmaa.com";
DealerModel.find({
email: dealer_email
}, (err, dealer) => {
if (err) {
console.log("Error : dealer not found for this car");
throw new Error(err);
}
car.dealer_id = dealer[0]._id; // ? update the dealer_id
// ? check if the company exists : and if not then create one
CompanyModel.find({
company_name: company_name
}, (err, companies) => {
if (err) {
console.log("Error : while finding the compay");
throw new Error(err);
}
console.log(company_name, companies);
if (companies.length === 0) {
console.log("No such Company car exists in the garrage --> creating one");
let company = new CompanyModel({
company_name: company_name,
company_location: company_location,
cars: [car]
});
company.save((err) => {
if (err) {
console.log("Error : while adding company ");
throw new Error(err);
}
console.log(index, "<<<<<<<< INDEX ", totalCar);
if (index === totalCar - 1) {
console.log("done");
res.send("build complete");
// build_complete();
}
});
} else {
console.log("Company already exists in garage : add this car with all other cars of this company");
let company = companies[0]; // ? as its sure that they are unique
let query = {
_id: company._id
};
let updat_command = {
$push: {
cars: car
}
};
CompanyModel.updateOne(query, updat_command, (err) => {
if (err) {
console.log("Error : while pushing car to the compay's cars");
throw new Error(err);
}
console.log(index, "<<<<<<<< INDEX ", totalCar);
if (index === totalCar - 1) {
console.log("done");
res.send("build complete");
// build_complete();
}
});
}
});
});
console.log(index, "<<<<<<<< INDEX--OUTER ", totalCar);
});
}
Выход:
[nodemon] restarting due to changes...
[nodemon] starting `node app.js`
[[20:39:12.519]] [LOG] server live
[[20:39:12.626]] [LOG] Connected to DB : SUCCESS
[[20:39:12.642]] [LOG] index created email_1 <<<<<<<< buyers collection
[[20:39:12.647]] [LOG] index created email_1 <<<<<<<< dealers collection
[[20:39:12.795]] [LOG] index created company_name_1 <<<<<<<< companies collection
[[20:39:42.081]] [LOG] start saving cars
[[20:39:42.084]] [LOG] [ { id: '2',
vin: '5GAKRBKD9EJ323900',
make: 'Buick',
model: 'ENCLAVE',
year: '2014',
priceInr: '2537993',
trim: 'Leather FWD',
engine: 'SPORT UTILITY 4-DR',
body: '3.6L V6 DOHC 24V',
color: 'Silver',
transmission: 'Manual',
DealerID: '103' },
{ id: '4',
vin: '2GKALSEKXD6184074',
make: 'GMC',
model: 'TERRAIN',
year: '2013',
priceInr: '3851710',
trim: 'SLE2 FWD',
engine: 'SPORT UTILITY 4-DR',
body: '2.4L L4 DOHC 16V FFV',
color: 'Yellow',
transmission: 'Manual',
DealerID: '103' },
{ id: '6',
vin: '1GC1KXE86EF127166',
make: 'Chevrolet',
model: 'SILVERADO 2500HD',
year: '2014',
priceInr: '840547',
trim: 'LT Crew Cab 4WD',
engine: 'CREW CAB PICKUP 4-DR',
body: '6.6L V8 OHV 32V TURBO DIESEL',
color: 'Grey',
transmission: 'Automatic',
DealerID: '103' },
{ id: '8',
vin: '1GKKRTED1CJ211299',
make: 'GMC',
model: 'Acadia',
year: '2012',
priceInr: '3805008',
trim: 'Denali FWD',
engine: 'SPORT UTILITY 4-DR',
body: '3.6L V6 DOHC 24V',
color: 'Metallic White',
transmission: 'Automatic',
DealerID: '103' },
{ id: '10',
vin: '1GKKVTKD9EJ282303',
make: 'GMC',
model: 'ACADIA',
year: '2014',
priceInr: '1730235',
trim: 'Denali AWD',
engine: 'SPORT UTILITY 4-DR',
body: '3.6L V6 DOHC 24V',
color: 'Black',
transmission: 'Manual',
DealerID: '103' },
{ id: '12',
vin: '1GKS1AKC0FR200193',
make: 'GMC',
model: 'YUKON',
year: '2015',
priceInr: '3129397',
trim: 'SLE 2WD',
engine: 'SPORT UTILITY 4-DR',
body: '5.3L V8 OHV 16V',
color: 'Silver',
transmission: 'Manual',
DealerID: '103' } ]
[[20:39:42.089]] [LOG] 0 '<<<<<<<< INDEX--OUTER ' 6
[[20:39:42.089]] [LOG] 1 '<<<<<<<< INDEX--OUTER ' 6
[[20:39:42.090]] [LOG] 2 '<<<<<<<< INDEX--OUTER ' 6
[[20:39:42.090]] [LOG] 3 '<<<<<<<< INDEX--OUTER ' 6
[[20:39:42.090]] [LOG] 4 '<<<<<<<< INDEX--OUTER ' 6
[[20:39:42.090]] [LOG] 5 '<<<<<<<< INDEX--OUTER ' 6
[[20:39:42.120]] [LOG] gmc []
[[20:39:42.120]] [LOG] No such Company car exists in the garrage --> creating one
[[20:39:42.134]] [LOG] buick []
[[20:39:42.134]] [LOG] No such Company car exists in the garrage --> creating one
[[20:39:42.138]] [LOG] gmc []
[[20:39:42.138]] [LOG] No such Company car exists in the garrage --> creating one
[[20:39:42.143]] [LOG] chevrolet []
[[20:39:42.143]] [LOG] No such Company car exists in the garrage --> creating one
[[20:39:42.146]] [LOG] gmc []
[[20:39:42.146]] [LOG] No such Company car exists in the garrage --> creating one
[[20:39:42.150]] [LOG] 1 '<<<<<<<< INDEX ' 6
[[20:39:42.150]] [LOG] gmc []
[[20:39:42.151]] [LOG] No such Company car exists in the garrage --> creating one
[[20:39:42.153]] [LOG] 0 '<<<<<<<< INDEX ' 6
[[20:39:42.154]] [LOG] Error : while adding company
events.js:183
throw er; // Unhandled 'error' event
^
Error: MongoError: E11000 duplicate key error collection: myKaarma.companies index: company_name_1 dup key: { : "gmc" }
at company.save (/Users/prashant/Desktop/appathon/route/api.js:179:55)
at /Users/prashant/Desktop/appathon/node_modules/mongoose/lib/model.js:4437:16
at $__save.error (/Users/prashant/Desktop/appathon/node_modules/mongoose/lib/model.js:397:16)
at /Users/prashant/Desktop/appathon/node_modules/kareem/index.js:246:48
at next (/Users/prashant/Desktop/appathon/node_modules/kareem/index.js:167:27)
at next (/Users/prashant/Desktop/appathon/node_modules/kareem/index.js:169:9)
at Kareem.execPost (/Users/prashant/Desktop/appathon/node_modules/kareem/index.js:217:3)
at _handleWrapError (/Users/prashant/Desktop/appathon/node_modules/kareem/index.js:245:21)
at _cb (/Users/prashant/Desktop/appathon/node_modules/kareem/index.js:304:16)
at /Users/prashant/Desktop/appathon/node_modules/mongoose/lib/model.js:258:9
at /Users/prashant/Desktop/appathon/node_modules/kareem/index.js:135:16
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickCallback (internal/process/next_tick.js:180:9)
Как мне выйти из этого?