yopp
Если ты знаешь что гуглить, то вместо того чтоб оставлять человека один на один с поисковыми результатми, потрать 30 секунд и дай ссылку на конкретный материал, который отвечает на вопрос
yopp
Потому что не факт что поисковых результатах будет ответ на вопрос, не факт что это будет правильный ответ на вопрос и не факт что ответ будет понятный
Artem [GMT+2]
@Yopp @icerly спасибо!
Dmitriy
Добрый день. Мне нужно отобразить на фронте таблицу данных с пагинацией. Ищу пример пагинации в Монге, чтобы отсылать туда запросы с фронта. Наподобие https://stackoverflow.com/a/44857996/5524590, см. конец кода.
на самом деле все довольно просто. в самом простом случае это делается через limit + skip и пока не упретесь в производительность, то я бы не придумывал ничего другого. т.е. фронт вам присылает 2 доп параметра на какой-то endpoint: limit - количество записей которое надо отобразить на странице page - номер страницу на которую перешел пользователь а вы на бэке выполняете просто запрос к коллекции: db.some_collection.find().skip(page * limit).limit(10)
Dmitriy
работает просто и эффективно
Anonymous
Спасибо. Мне пока нравится моя ссылка больше, там $slice кусочка коллекции от и до от+число строк на страницу.
Anonymous
Но: читал, что $push: '$$ROOT' при большой коллекции вызывает в Монго некую ошибку. У меня 300 000 доков.
Mike
Спасибо. Мне пока нравится моя ссылка больше, там $slice кусочка коллекции от и до от+число строк на страницу.
вот нормальный туториал если еще нужно https://evdokimovm.github.io/javascript/nodejs/mongodb/pagination/expressjs/ejs/bootstrap/2017/08/20/create-pagination-with-nodejs-mongodb-express-and-ejs-step-by-step-from-scratch.html
Anonymous
Есть способ вернуть часть коллекции от и до, помимо skip и limit? Пытаюсь приспособить для этого $slice.
Dmitriy
Есть способ вернуть часть коллекции от и до, помимо skip и limit? Пытаюсь приспособить для этого $slice.
а поясните, что вы хотите сделать? считать в слайс все 300К документов и работать уже со смещением слайса?
Anonymous
При перемещении по пагинации таблицы, т. е. при кликах по кнопках пагинации, отправлять запрос в БД и подбирать очередные 10 (пока фиксированное число) записей. Сейчас для начала пишу запрос, который бы возвращал документы с индексами от и до, хочется написать его без использования skip и limit, т. к. они пробегают по всей коллекции.
Dmitriy
вы делаете преждевременную оптимизацию, о которой я говорил выше)
Dmitriy
вообще ваша задача решается через использование $lt и $gte по какому-то ключу, но подозреваю, что этого ключа у вас в документе сейчас нет
Anonymous
Возможно передать в $match в aggregate пустой объект {}? Чтобы получить все документы в коллекции. Аналогичнo коллекция.find({}).
Anonymous
Судя по первому блоку кода в https://stackoverflow.com/a/53220591/5524590, можно.
Mike
Что то не пойму речь о паджинации идёт или нет. Сколько не видел разных вариантов, все skip и limit используют. Хоть в мускуле хоть в оракле
Dmitriy
Dmitriy
Что то не пойму речь о паджинации идёт или нет. Сколько не видел разных вариантов, все skip и limit используют. Хоть в мускуле хоть в оракле
Потому что он самый простой и в большинстве случаев достаточный. Оптимизацию с ограничивающей выборкой по ключу от и до имеет смысл делать только если действительно упёрся в производительность, потому что её правильная архитектурная реализация сама по себе довольно сложна
Anonymous
А зачем вам вообще стейдж с матчем в пайплайне, если вам нужны все документы?)
Сейчас пробую получать очередные 10 документов по клику на кнопку пагинации. Цифра на этой кнопке, т. е. номер текущей страницы, это const currentPage в коде ниже. router.get('/test/subs/:current_page', async (req, res) => { const RESULTS_PER_PAGE = 10; const currentPage = req.params.current_page; try { const docs = await Subscription .aggregate([ { "$facet": { "records": [ { "$match": {} }, { "$skip": (currentPage - 1) * RESULTS_PER_PAGE }, { "$limit": RESULTS_PER_PAGE } ], "count": [ { "$count": "count" } ] } } ]); res.status(200).json({ docs }); } catch(ex) { console.log('error fetching docs from Subscription:', ex.message); res.status(500).json({ message: 'error fetching docs from Subscription' }); } }); Этот серверный роут будет получать запросы от фронта и возвращать текущий кусочек коллекции и размер всей коллекции.
Dmitriy
Сейчас пробую получать очередные 10 документов по клику на кнопку пагинации. Цифра на этой кнопке, т. е. номер текущей страницы, это const currentPage в коде ниже. router.get('/test/subs/:current_page', async (req, res) => { const RESULTS_PER_PAGE = 10; const currentPage = req.params.current_page; try { const docs = await Subscription .aggregate([ { "$facet": { "records": [ { "$match": {} }, { "$skip": (currentPage - 1) * RESULTS_PER_PAGE }, { "$limit": RESULTS_PER_PAGE } ], "count": [ { "$count": "count" } ] } } ]); res.status(200).json({ docs }); } catch(ex) { console.log('error fetching docs from Subscription:', ex.message); res.status(500).json({ message: 'error fetching docs from Subscription' }); } }); Этот серверный роут будет получать запросы от фронта и возвращать текущий кусочек коллекции и размер всей коллекции.
Честно выглядит как лютый оверхэд. Фасет, пустой матч, зачем? Вы меряли производительность и эти замеры показали, что ваш АФ работает эффективней чем 2 маленьких коротких запроса на count и find?
Anonymous
Вероятно, вы правы.
Anonymous
Правильная идея на фронте при перемещении по пагинации таблицы на каждом запросе помимо данных для таблицы получать размер всей коллекции?
Dmitriy
Правильная идея на фронте при перемещении по пагинации таблицы на каждом запросе помимо данных для таблицы получать размер всей коллекции?
Данные не на фронте, а на бэке вы получаете, а в остальном да. Фронт вам передаёт страницу и возможно лимит документов на страницу. Вы на бэке получаете на каждое изменение данных на фронте count и делаете find. Если данные в коллекции меняются не часто, то count можно кэшировать
Anonymous
Размер коллекции не меняется. Лимит документов на страницу таблицы на фронте будет чуть позже, это будет выпадающиее меню "столько-то строк" (отображать). Как кешиpовать count?
Dmitriy
Размер коллекции не меняется. Лимит документов на страницу таблицы на фронте будет чуть позже, это будет выпадающиее меню "столько-то строк" (отображать). Как кешиpовать count?
Все зависит от ЯП и вашей архитектуры. Если ЯП работает в одном процессе и имеет всего одну ноду, то можете сделать мапу с которой храните стейт. Если нод несколько или вы работаете с ЯП, который на каждый http запрос создаёт новый процесс, то проще всего хранение стейта вынести в редис например (т.е. независимое хранилище с быстрым доступом)
Anonymous
Node.js на сервере, React на фронте.
Dmitriy
Node.js на сервере, React на фронте.
Нода вроде работает с одним процессом и паралеллит уже на уровне виртуалки запросы. Но я не спец в ноде могу наврать
Anonymous
Node.js 1-поточен по дефолту.
Anonymous
Спасибо.
Dmitriy
Node.js 1-поточен по дефолту.
Ну тогда если у вас одна нода, т.е. нет необходимости синхронизации кэша между разными нодами приложения, то сделайте глобальный объект с полем count и в нем храните кэшированное значение количества документов
Anonymous
Глобальный объект на беке?
Dmitriy
Глобальный объект на беке?
Да, я именно это и имел в виду
Dmitriy
зачем
Чтобы избавится от одного запроса, который и так судя по тому что человек пишет будет возвращать одно и тоже значение
yopp
зачем
Dmitriy
Экономия на спичках, но это не обязательно конечно, об этом я тоже выше писал)
Anonymous
Спасибо всем за участие и информацию. Хорошего завтра.
Artem
Всем привет. Подскажите как лучше хранить данные из 1-20 тысячи элементов массива (цифры, спарсенные айди)? У меня в голове крутятся такие варианты: текстовый файл, mongodb таблица где будет тип Object и туда загонять, но не знаю разумно ли это, ну или создавать для каждого элемента свой документ в таблице. Использоваться это будет только в скрипте, одновременно будет работать с этими данными 1 процесс. Что скажете?
yopp
чтоб монгу с собой не таскать
yopp
в npm скорее всего есть биндинги
Artem
в npm скорее всего есть биндинги
Есть, но что выбрать лучше? SQLite или RocksDB?
yopp
зависит от выборок, которые вы хотите делать
yopp
если вам не нужен поиск по значению, а доступ по ключам простой, key/value хранилища типа rocksdb или другое embedded будет достаточно. возможно в ноду уже что-то встроено если у вас сложные запросы, разные измерения по которым вы хотите делать выборки, то sqlite
yopp
rocksdb это просто key/value хранилище
yopp
это бибилиотека, так что вы его встраиваете в своё прилоежние
yopp
но оно ничего кроме put/get/scan/delete не умеет
Artem
это бибилиотека, так что вы его встраиваете в своё прилоежние
Для меня это больше минус, чем плюс, так как будет проблема с масштабированием
yopp
в вашей задаче было про 1 процесс
Artem
в вашей задаче было про 1 процесс
Да, наверное это мой косяк, не указал это. Процессов может быть хоть тысяча
Dmitriy
Роксдб это про один инстанс на одну ноду, если нужно масштабирование, то встанет вопрос про синхронизацию. Если смотрите на кей валуе хранилище с замахом на масштабирование, то либо редис (и возможно редис кластер), либо аероспайк. Других хороших вариантов не особо на рынке
yopp
сомневаюсь
yopp
что проблема масшабировния у вас всего вообще стоит в ближайшем времени. вам нужно определиться только с тем, какое количество потребителей данных у вас будет. если у вас будет множество потребителей, то какое-то сетевое хранилеще будет удобнее. если у вас это какой-то скрипт, бот или ещё какое-то приложение работающее в единственном экземпляре, то можно и сетевое, и встроенное хранилище
yopp
пытаться оптимизировать то, чего у вас ещё нет — бессмыслено
yopp
для ваших объёмов подойдёт абсолютно любое хранилище. выбирайте по тому, насколько хранилище помогает легко получить доступ к тем данных, которые вам нужны
yopp
проблемы с масштабированием это хороший вид проблем, которй говорит что у вас есть нужный кому-то продукт. а это очень поздняя стадия, до которой 99% продуктов просто не доходят
Artem
В ближайшие пару месяцев может и не будет больших объемов, но потом будет и что, переписывать логику всю?
Dmitriy
В ближайшие пару месяцев может и не будет больших объемов, но потом будет и что, переписывать логику всю?
Зачем, один адаптер переписать надо?! Это же вопрос организации вашего кода
yopp
http://wiki.c2.com/?PrematureOptimization
Dmitriy
В первую очередь смотрите на дешевизну запуска, как начнут идти реальные деньги и проблемы с ними. Вы будете за эти деньги решать эти проблемы
Dmitriy
Иначе вы работаете в минус себе или компании
yopp
Радует что я не один про это теперь ною
yopp
TL;DR: возьмите то, с чем вы знакомы и быстро запилите то, что вы хотите
yopp
быстрее запилите, быстрее поймёте что вам реально надо
yopp
если пилить быстро, инвестиции минимальные
yopp
а значит и выкинуть если что не жалко
Dmitriy
быстрее запилите, быстрее поймёте что вам реально надо
Даже не так, надо ли оно кому-то кроме вас, вот так оно вернее будет звучать ;)
yopp
у меня обычно это выглядит как-то так
Artem
у меня обычно это выглядит как-то так
Почему не гитхаб?) Выбрал редис)
yopp
это в гит репозитории