Можно ли отображать повторяющиеся записи по ключу как одну запись и назначать ей массив данных один-ко-многим
Модели
const Quest = sequelize.define('quest' , {
name: {
type: DataTypes.STRING,
allowNull: false,
}
});
const QuestPack = sequelize.define('quest_packs', {
day: {
type: DataTypes.INTEGER,
allowNull: false,
},
questId: {
type: DataTypes.INTEGER,
allowNull: false,
},
videoId: {
type: DataTypes.INTEGER,
allowNull: false,
}
});
const Video = sequelize.define('video', {
url: {
type: DataTypes.INTEGER,
allowNull: false,
}
});
Quest.belongsToMany(Video, {
through: QuestPack,
});
Quest.hasMany(QuestPack, {
foreignKey: 'challengeId',
});
QuestPack.belongsTo(Video, {
foreignKey: 'videoId',
});
Video.belongsToMany(Quest, {
foreignKey: 'videoId',
through: QuestPack,
});
Запрос
const data = await Quest.findByPk(1, {
include: [
{
model: QuestPack,
attributes: ['day'],
include: [{ model: Video }],
}
],
});
Я получаю данные в таком формате:
{
"id": 1,
"name": "Name quest",
"questPacks": [
{
"day": 1,
"video": {
"id": 1,
"url": "youtube link",
}
},
{
"day": 1,
"video": {
"id": 2,
"url": "youtube link",
}
}
]
}
Я хочу, чтобы все мои повторяющиеся записи по ключу day были удалены, и отображалась только одна запись, содержащая массив всех видео, принадлежащих questId.
{
"id": 1,
"name": "Name quest",
"questPacks": [
{
"day": 1,
"videos": [
{
"id": 1,
"url": "youtube link",
},
{
"id": 2,
"url": "youtube link",
}
]
},
]
}
Можно ли это реализовать с sequelize ?
Ответы (1 шт):
Автор решения: Daniil Loban
→ Ссылка
через редьюс создаем новый массив questPacks, далее путем поиска совпадений по дню добавляем остальные видео.
const o = {
"id": 1,
"name": "Name quest",
"questPacks": [
{
"day": 1,
"video": {
"id": 1,
"url": "youtube link",
}
},
{
"day": 1,
"video": {
"id": 2,
"url": "youtube link",
}
},
{
"day": 2,
"video": {
"id": 2,
"url": "youtube link",
}
},
{
"day": 1,
"video": {
"id": 3,
"url": "youtube link",
}
},
]
}
function packDays(packs) {
const result = {
id: packs.id,
name: packs.name,
questPacks: []
}
result.questPacks = o.questPacks.reduce((acc, pack) => {
let nextPack = null;
if (nextPack = o.questPacks.find(days => days.day === pack.day) ){
// первый объект (видео по дню) помещаем в массив
if(nextPack === pack) {
nextPack.video = [nextPack.video]
acc.push(pack)
return acc
}
// при совпадении дней пушим их в один массив
nextPack.video.push(pack.video);
return acc
}
}, [/* инициируем пустой массив */])
return result
}
const inp = document.querySelector('#inp');
const out = document.querySelector('#out');
inp.textContent = JSON.stringify(o, null, 2)
out.textContent = JSON.stringify(packDays(o), null, 2)
<p><b>оригинал:</b></p>
<pre id="inp"></pre>
<p><b>получаем:</b></p>
<pre id="out"></pre>