-
Notifications
You must be signed in to change notification settings - Fork 39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Имаев Альберт #20
Имаев Альберт #20
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,4 +2,14 @@ | |
|
||
module.exports = (sequelize, DataTypes) => { | ||
// Ваша модель юзера | ||
return sequelize.define('users', { | ||
id: { | ||
type: DataTypes.INTEGER, | ||
primaryKey: true, | ||
autoIncrement: true | ||
}, | ||
login: { | ||
type: DataTypes.TEXT | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. и тут индекс, уникальный (не может быть двух юзеров с одинаковым логином) |
||
} | ||
}); | ||
}; |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,25 +3,51 @@ | |
class Queries { | ||
constructor(models) { | ||
// Что-нибудь инициализируем в конструкторе | ||
this.sequelize = models.sequelize; | ||
this.Op = models.sequelize.Op; | ||
this.Cart = models.Cart; | ||
this.Country = models.Country; | ||
this.Review = models.Review; | ||
this.Souvenir = models.Souvenir; | ||
this.Tag = models.Tag; | ||
this.User = models.User; | ||
} | ||
|
||
// Далее идут методы, которые вам необходимо реализовать: | ||
|
||
getAllSouvenirs() { | ||
// Данный метод должен возвращать все сувениры. | ||
return this.Souvenir.findAll(); | ||
} | ||
|
||
getCheapSouvenirs(price) { | ||
// Данный метод должен возвращать все сувениры, цена которых меньше или равна price. | ||
return this.Souvenir.findAll({ | ||
where: { | ||
price: { [this.Op.lt]: price } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. цена должна мыть меньше или равна |
||
} | ||
}); | ||
} | ||
|
||
getTopRatingSouvenirs(n) { | ||
// Данный метод должен возвращать топ n сувениров с самым большим рейтингом. | ||
return this.Souvenir.findAll({ | ||
order: [['rating', 'DESC']], | ||
limit: n | ||
}); | ||
} | ||
|
||
getSouvenirsByTag(tag) { | ||
// Данный метод должен возвращать все сувениры, в тегах которых есть tag. | ||
// Кроме того, в ответе должны быть только поля id, name, image, price и rating. | ||
return this.Souvenir.findAll({ | ||
attributes: ['id', 'name', 'image', 'price', 'rating'], | ||
include: { | ||
model: this.Tag, | ||
where: { name: tag }, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. сравнение лучше делать регистронезависимым |
||
attributes: [] | ||
} | ||
}); | ||
} | ||
|
||
getSouvenirsCount({ country, rating, price }) { | ||
|
@@ -31,36 +57,92 @@ class Queries { | |
|
||
// Важно, чтобы метод работал очень быстро, | ||
// поэтому учтите это при определении моделей (!). | ||
return this.Souvenir.count({ | ||
where: { | ||
rating: { [this.Op.gte]: rating }, | ||
price: { [this.Op.lte]: price } | ||
}, | ||
include: [{ | ||
model: this.Country, | ||
where: { name: country }, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. и тут регистронезависимый |
||
attributes: [] | ||
}] | ||
}); | ||
} | ||
|
||
searchSouvenirs(substring) { | ||
// Данный метод должен возвращать все сувениры, в название которых входит | ||
// подстрока substring. Поиск должен быть регистронезависимым. | ||
return this.Souvenir.findAll({ | ||
where: { | ||
name: { [this.Op.iLike]: `%${substring}%` } | ||
} | ||
}); | ||
} | ||
|
||
getDisscusedSouvenirs(n) { | ||
// Данный метод должен возвращать все сувениры, имеющих >= n отзывов. | ||
// Кроме того, в ответе должны быть только поля id, name, image, price и rating. | ||
return this.Souvenir.findAll({ | ||
attributes: ['name', 'image', 'price', 'rating'], | ||
group: 'souvenirs.id', | ||
having: this.sequelize.where( | ||
this.sequelize.fn('COUNT', this.sequelize.col('reviews.id')), '>=', n | ||
), | ||
include: { | ||
model: this.Review, | ||
attributes: [] | ||
}, | ||
order: ['id'] | ||
}); | ||
} | ||
|
||
deleteOutOfStockSouvenirs() { | ||
// Данный метод должен удалять все сувениры, которых нет в наличии | ||
// (то есть amount = 0). | ||
|
||
// Метод должен возвращать количество удаленных сувениров в случае успешного удаления. | ||
return this.Souvenir.destroy({ | ||
where: { amount: 0 } | ||
}); | ||
} | ||
|
||
addReview(souvenirId, { login, text, rating }) { | ||
async addReview(souvenirId, { login, text, rating }) { | ||
// Данный метод должен добавлять отзыв к сувениру souvenirId | ||
// содержит login, text, rating - из аргументов. | ||
// Обратите внимание, что при добавлении отзыва рейтинг сувенира должен быть пересчитан, | ||
// и всё это должно происходить за одну транзакцию (!). | ||
const user = await this.User.findOne({ where: { login } }); | ||
const souvenir = await this.Souvenir.findById(souvenirId); | ||
|
||
return this.sequelize.transaction(async transaction => { | ||
const review = { userId: user.id, text, rating }; | ||
await souvenir.createReview(review, { transaction }); | ||
|
||
const reviews = await souvenir.getReviews({ transaction }); | ||
rating = (souvenir.rating * (reviews.length - 1) + rating) / (reviews.length); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. не обязательно к исправлению сейчас ты загружаешь в приложение весь список отзывов и обновляешь рейтинг |
||
|
||
await souvenir.update({ rating }, { transaction }); | ||
}); | ||
} | ||
|
||
getCartSum(login) { | ||
async getCartSum(login) { | ||
// Данный метод должен считать общую стоимость корзины пользователя login | ||
// У пользователя может быть только одна корзина, поэтому это тоже можно отразить | ||
// в модели. | ||
return await this.Cart.sum('souvenirs.price', { | ||
group: 'carts.id', | ||
includeIgnoreAttributes: false, | ||
include: [ | ||
{ | ||
model: this.Souvenir | ||
}, | ||
{ | ||
model: this.User, | ||
where: { login } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. тут тоже лучше регистронезависимое сравнение |
||
} | ||
] | ||
}); | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
кажется, что тут нужен индекс (в коде есть выборка по тэгу)