(многие-ко-многим). При попытке вручную добавить сначала новую article, потом несколько article_tag, а затем их id в article_tag_many - всё ок, с базой проблем нет.
Использую Knex.js + Bookshelf.js. На вход метода add (article) одним из параметров попадает tags - это масив объектов вида [{tag: "тег1"}, {tag: "тег2"}, {tag: "тег3"}]. Далее создается article. Следующим шагом - article_tags. И теперь мне необходимо сохранить в article_tag_many значения id передаваемых в метод тегов.
Т.e. теги в таблицу с тегами записались, как теперь средствами ORM получить их id , чтобы записать в article_tag_many?
Пробовал такое: const tagId = await knex.raw(`select nextval('article_tag_id_seq')`);
И далее - Number(tagId.rows[0]['nextval']) - idOffset как значение id тега (где idOffset - количество объектов в передаваемом массиве)
Но такой подход мне не нравится + к тому же он еще и не работает: в консоли я вижу правильные значения идентификаторов (в базе ровно такие же значения после вызова метода):
ArticleId 197
TagId 415
ArticleId 197
TagId 416
ArticleId 197
TagId 417
Но в итоге появляется ошибка:
UnhandledPromiseRejectionWarning: error: insert or update on table "article_tag_many" violates foreign key constraint "article_tag_many_tag_id_fkey"
Вот код:
export async function add(<SomeAttrs here>, tags, <SomeAttrs here>) {
try {
const myArticle = new Article({ <SomeAttrs here> });
await myArticle.save();
for (const tag of tags) {
await new Tags({ tag: tag['tag'] }).save();
}
const articleId = await knex.raw(`select nextval('article_id_seq')`);
tags.forEach(async (_tag) => {
const tagId = await knex.raw(`select nextval('article_tag_id_seq')`);
try {
await myArticle.related('tags').create({
articleId: Number(articleId.rows[0]['nextval']) - 1,
tagId: Number(tagId.rows[0]['nextval']) - 3
});
} catch (err) {
throw err;
}
});
return myArticle;
} catch (error) {
throw new BadRequestError(error.message);
}
}
Оно не работает ни с for ... of, ни с for await ... of, более того, в методе add есть еще такая логика (sections - массив чисел, тоже связь там many-to-many), эта часть кода работает: sections.forEach(async section => { try { await myArticle.related('section').create({ sectionId: section }); } catch (err) { throw err; } });
работать-то она работает, но forEach не ждет await.
В общем, мой метод не работал, потому что я неправильно прописал логику в моделях, теперь всё работает. По поводу 'не ждёт await' - а как правильно? Вот так? for await (const section of sections) { await myArticle.related('section').create({ sectionId: section }); }
без for await, просто for или через await Promise.all
Понятно, благодарю!
Обсуждают сегодня