feat(vocab): add logic to aggregate and clean up duplicate SRS items based on answer patterns
This commit is contained in:
@@ -95,6 +95,90 @@ module.exports = {
|
||||
transaction
|
||||
});
|
||||
|
||||
await queryInterface.sequelize.query(`
|
||||
WITH candidates AS (
|
||||
SELECT id, user_id,
|
||||
ENCODE(DIGEST(CONCAT_WS(
|
||||
'|',
|
||||
course_id::text,
|
||||
COALESCE(lesson_id::text, 'course'),
|
||||
UPPER(direction),
|
||||
:normalizedCombinedAnswer,
|
||||
:normalizedTarget
|
||||
), 'sha1'), 'hex') AS new_item_key,
|
||||
correct_count, wrong_count, lapse_count, stage, interval_days,
|
||||
last_reviewed_at, next_due_at
|
||||
FROM community.vocab_srs_item
|
||||
WHERE learning = :shortAnswer
|
||||
AND reference = :target
|
||||
), ranked AS (
|
||||
SELECT *, ROW_NUMBER() OVER (PARTITION BY user_id, new_item_key ORDER BY id) AS position
|
||||
FROM candidates
|
||||
), aggregates AS (
|
||||
SELECT user_id, new_item_key, MIN(id) AS keeper_id,
|
||||
SUM(correct_count) AS correct_count,
|
||||
SUM(wrong_count) AS wrong_count,
|
||||
SUM(lapse_count) AS lapse_count,
|
||||
MAX(stage) AS stage,
|
||||
MAX(interval_days) AS interval_days,
|
||||
MAX(last_reviewed_at) AS last_reviewed_at,
|
||||
MIN(next_due_at) AS next_due_at
|
||||
FROM ranked
|
||||
GROUP BY user_id, new_item_key
|
||||
)
|
||||
UPDATE community.vocab_srs_item AS keeper
|
||||
SET correct_count = aggregates.correct_count,
|
||||
wrong_count = aggregates.wrong_count,
|
||||
lapse_count = aggregates.lapse_count,
|
||||
stage = aggregates.stage,
|
||||
interval_days = aggregates.interval_days,
|
||||
last_reviewed_at = aggregates.last_reviewed_at,
|
||||
next_due_at = aggregates.next_due_at,
|
||||
updated_at = NOW()
|
||||
FROM aggregates
|
||||
WHERE keeper.id = aggregates.keeper_id;
|
||||
`, {
|
||||
replacements: {
|
||||
target: TARGET,
|
||||
shortAnswer: SHORT_ANSWER,
|
||||
normalizedCombinedAnswer: NORMALIZED_COMBINED_ANSWER,
|
||||
normalizedTarget: NORMALIZED_TARGET
|
||||
},
|
||||
transaction
|
||||
});
|
||||
|
||||
await queryInterface.sequelize.query(`
|
||||
WITH candidates AS (
|
||||
SELECT id, user_id,
|
||||
ENCODE(DIGEST(CONCAT_WS(
|
||||
'|',
|
||||
course_id::text,
|
||||
COALESCE(lesson_id::text, 'course'),
|
||||
UPPER(direction),
|
||||
:normalizedCombinedAnswer,
|
||||
:normalizedTarget
|
||||
), 'sha1'), 'hex') AS new_item_key
|
||||
FROM community.vocab_srs_item
|
||||
WHERE learning = :shortAnswer
|
||||
AND reference = :target
|
||||
), ranked AS (
|
||||
SELECT id, ROW_NUMBER() OVER (PARTITION BY user_id, new_item_key ORDER BY id) AS position
|
||||
FROM candidates
|
||||
)
|
||||
DELETE FROM community.vocab_srs_item AS duplicate
|
||||
USING ranked
|
||||
WHERE duplicate.id = ranked.id
|
||||
AND ranked.position > 1;
|
||||
`, {
|
||||
replacements: {
|
||||
target: TARGET,
|
||||
shortAnswer: SHORT_ANSWER,
|
||||
normalizedCombinedAnswer: NORMALIZED_COMBINED_ANSWER,
|
||||
normalizedTarget: NORMALIZED_TARGET
|
||||
},
|
||||
transaction
|
||||
});
|
||||
|
||||
await queryInterface.sequelize.query(`
|
||||
UPDATE community.vocab_srs_item
|
||||
SET learning = :combinedAnswer,
|
||||
|
||||
Reference in New Issue
Block a user