ms-dred
@ms-dred
Вечно что то не то и что то не так...

Как сократить запросы update при учете просмотров документа?

Хочется сократить количество обращений к конге с целью обновления документа.
На сайте есть посты при переходе на пост идет обновление поля stats.view +1, таких запросов в секунду порядка 50 штук.

Выборка в силу своей нагруженности происходит не обычным образом:
1. Самый первый запрос к документу, собирает всю необходимые информацию с 3-х коллекций, одна из которых бывает тяжелой и выполняется более секунды. После всех выборок собирает большой объект со всем необходимым и сохраняется в отдельную коллекцию монги в строковое поле (object.toString()), назовем ее cache
2. Второй и последующие запросы идут непосредственно в коллекцию cache, если в ней находится необходимая информация. Документы практически никогда не меняются и кеш документа может храниться годами

Если на пальцах показать то при запросе к переходе на страницу происходит следующее
const [cache, count] = await Promise.all([getCache(request, response), updateStats(request.params)])
// updateStats - обновляет поле documen.stats.view+1


В идеале хотелось бы следующее, создать какой то контейнер куда складывать ID документа и количество просмотров
[{
    _id: ObjectId("..."),
    count: 2000
},{
    _id: ObjectId("..."),
    count: 1000
}]


И раз в сутки по крону делать обновление необходимых документов, что позволит избежать десятки/сотни тысяч лишних запросов в коллекцию за сутки.

Как вообще такое реализовать, и возможно ли? Делать какой то глобальный контейнер в ноде?
  • Вопрос задан
  • 34 просмотра
Пригласить эксперта
Ответы на вопрос 2
ms-dred
@ms-dred Автор вопроса
Вечно что то не то и что то не так...
В общем пока альтернативы нет, хочу попробовать следующий метод для разгрузки монги
Вместо обновления коллекции решил писать идентификаторы в файл views.log
function updateStats(request) {
    return fs.appendFileSync("views.log", `${request.document}|`, 'UTF-8') // request.document = часть URL по которой идет выборка
}


Ну и собственно дальше по крону буду дергать файл, перебирать данные, перезаписывать все скопом в ночное время
Из файла куски кода
//file.split('|').filter(function (e) { return e })

function setCountObject(request) {
    return documents = [], Promise.all(request.map(async (document) => {
        return (item = documents.find(e => e.url === document)), item && (item.count = item.count + 1) || documents.push({
            url: document,
            count: 1
        })
    })), documents
}

function updateDocuments(request) {
    return Promise.all(request.map(async (document) => {
        return Collection.updateOne({ url: document.url }, { $set: { "stats.view": document.count }})
    }))
}


Монгу в пике трафика конечно разгрузить это, надо смотреть и тестить =)
Ответ написан
Комментировать
@vshvydky
1. создать коллекцию (таблицу) ид чего-то , счетчик просмотров
2. на гет запрос получения данных по этой коллекции вешаешь мидлвару, в ней делаешь инкремент счетчика
3. отдаешь клиенту контент
4. радуешься жизни
ps: про инкремент счетчика
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы