У меня проблема с организацией моих данных mongoDB для отправки на мою страницу в моем резюме и я не могу понять, как сделать правильный js. Вот упрощенная версия моей схемы
var productSchema = new mongoose.Schema({
medium: String,
brand: String,
group: String
});
Вот как выглядит типичная запись
medium :"Acrylic",
brand :"liquitex",
group :"heavy body"
. В схема, но это единственные, с которыми мне нужно иметь возможность сортировать и организовывать возвращаемые результаты. Проблема в том, что у меня есть маршрут, который возвращает все цвета в моей базе данных, и я хочу иметь возможность отображать их в разделах на моей странице, которые сгруппированы под брендом, а затем отдельные цвета перечислены в правильной группе.
Проблема в том, что есть краски других брендов, которые попадают в группу с тяжелым телом, и поэтому, когда я использую функцию фильтра для сортировки данных по группам, некоторые бренды смешиваются вместе. Я не могу фильтровать по брендам, потому что у некоторых брендов есть акрил c и акварель, поэтому они смешиваются вместе. Мне нужен какой-то способ отфильтровать возвращенные результаты
mongoose.find({})
, который может использовать данные группы в качестве фильтра, но затем отфильтровать эти результаты по брендам, чтобы они были разделены на правильные категории брендов.
Пока у меня есть это:
это урезанная версия моего приложения. js файл:
//finds all colors in the DB
Color.find({}).lean().exec(function( err, colors)
var groups = [];
// find all groups in the databse
colors.forEach( function(color){
groups.push(color["group"]);
});
//returns only unique names to filter out duplicates
var groupTypes = Array.from(new Set(groups));
var tempVariableBrands = [];
// this sorts all returned paints into their respective group, but we get paints from multiple brands under the same group and that is not good
groupTypes.forEach( function(group){
var name = group;
var result = colors.filter(obj => { return obj.group === group });
tempVariable.push( {group : name, result } );
});
// the tempVariable gets sent to my page like so
res.render("landing", {colorEntry:tempVariable} );
и это работает хорошо, что я могу отображать каждую краску по ее группировке, но это не удается, если имеется более одной краски от другого производителя, которая считается одной и той же группой как «тяжелое тело». Это моя e js на моей странице, которая отлично работает:
<% colorEntry.forEach( function(entry){ %>
<div class="brandBlock">
<div class="brandTitle">
<span><%=entry.result[0].brand%> - <%=entry.result[0].group%></span>
Я, по жизни, не могу понять комбинацию filter () и, возможно, map (), которая позволила бы такого рода обработки будет сделано. В моей базе данных около 600 документов, цветов от разных производителей, и я не знаю, как получить это как возвращаемую структуру: допустим, это несколько цветов в БД, которые возвращаются из mon goose find:
[{ medium: "Oil",
brand: "Gamblin",
group: "Artists oil colors"},
{ medium: "Acrylic",
brand: "Liquitex",
group: "Heavy Body"},
{ medium: "Acrylic",
brand: "Golden",
group: "Heavy Body"}
]
Мне нужно организовать это так или что-то подобное. Это может быть что угодно, что просто сортирует эти данные в базовую c структуру, подобную этой, я не ограничен каким-либо установленным стандартом или чем-то еще, это только для личного использования, и сайт, который я пытаюсь создать, чтобы узнать больше.
returnedColors = [ { brand: "Gamblin", group: "Artists oil colors", { 50 paints colors returned} },
{ brand: "liquitex" , group: "heavy body", { 20 paint colors returned } },
{ brand: "golden" , group: "heavy body",{ 60 paint colors returned} }
];
Я не веб-разработчик и пишу какой-то веб-код каждые 6 месяцев или около того, и пытался выяснить это в течение последних 2 дней. Я не могу обернуть голову вокруг некоторых удивительных комбо фильтров и карт, которые я видел, и не могу заставить это работать. Любая помощь или совет будут великолепны. Я уверен, что есть много областей для улучшения этого кода, но все работало до тех пор, пока я не ввел краски от разных брендов, имеющих одинаковый тип группы, и мне пришлось попытаться переписать этот код сортировки, чтобы справиться с ним. Это сводится к необходимости иметь возможность перебирать весь набор возвращаемых документов из БД, а затем сортировать их по двум значениям.
ОБНОВЛЕНИЕ: Мне удалось получить что-то, что работает и возвращает данные в формате, который мне нужен, чтобы иметь возможность отправить их в мой файл e js и правильно отобразить их. Код довольно уродливый и, вероятно, очень избыточный, но он технически работает. Он начинается с использования значения группы для запуска над красками, поскольку каждый набор красок будет иметь имя группы, но иногда может использовать имя группы совместно с краской другой марки, такой как «тяжелое тело».
groupTypes.forEach( function(group){
var name = group;
var result = colors.filter(obj => { return obj.group === group });
// this gets brand names per iteration of this loop so that we will know if more than one brand of paint
// has the same group identity.
var brands = [];
result.forEach( function(color){
brands.push(color["brand"]);
});
// This filters the brand names down to a unique list of brands
var brandNames = Array.from(new Set(brands));
// if there is more than one brand, we need to filter this into two separate groups
if( brandNames.length > 1){
//console.log("You have duplicates");
brandNames.forEach( x => {
var tmpResult = [...result];
var resultTmp = result.filter(obj => { return obj.brand === x });
result = resultTmp;
//console.log("FILTERED RESULT IS: ", result);
tempVariable.push( {brand: x ,group : name, result } );
result = [...tmpResult];
});
}else{
tempVariable.push( {brand: result[0].brand ,group : name, result } );
}
});
если кто-то может свести это к чему-то более эффективному, я хотел бы увидеть «лучший» или «правильный» способ сделать что-то подобное.
UPDATE2
Благодаря ответу ниже, я был на правильном пути и смог переписать кучу этого длинного кода следующим образом:
Color.aggregate([
{
$sort: { name: 1}
},
{
$group: {
_id: { brand: '$brand', group: '$group' },
result: { $push: '$$ROOT' }
}
},
{ $sort: { '_id.brand': 1 } }
], function( err, colors){
if(err){
console.log(err);
}else{
res.render("landing", {colorEntry:colors, isSearch:1, codes: userCodes, currentUser: req.user, ads: vs.randomAds()} );
}
});
Значительно чище и, похоже, достиг того же результата.