yopp
Aggregation Framework + $group + $limit
yopp
https://docs.mongodb.com/manual/reference/operator/aggregation/group/#retrieve-distinct-values https://docs.mongodb.com/manual/reference/operator/aggregation/limit/
Anonymous
Похоже, не обойти.
Anonymous
Как вернуть массив из одного поля? В БД много записей из 3-х полей. Около 300 к записей вида "name": "b64dc661-f977-4fb5-824d-11d5cce526fc", "timestamp": 1567296720, "price": 39900 нужно вернуть только массив price'ов для данного timestamp.
Yaroslav
Выбираешь все по timestamp, и aggregation framework делаешь project по нужному полю
Anonymous
Напишите код, плиз?
Anonymous
Сейчас так: const entries = await Subscription .find({ timestamp: req.params.timestamp }, { $elemMatch: { timestamp: } }) .limit(parseInt(req.params.limit, 10));
Yaroslav
db.collection.aggregate([ {$match:{timestamp : значение }}, {$project :{ price:1 } ])
Yaroslav
Пишу с телефона
Yaroslav
Не могу поверить на корректность
Yaroslav
Но принцип примерно такой как описал
Anonymous
Что есть price:1 ?
Yaroslav
Что есть price:1 ?
Вывести все price из коллекции
Yaroslav
Что есть price:1 ?
https://docs.mongodb.com/manual/reference/operator/projection/positional/
Anonymous
Успел попробовать .aggregate([ { $group: { timestamp: req.params.timestamp } } ]), вернуло ошибку The field 'timestamp' must be an accumulator object.
Anonymous
Множество объектов вида https://t.me/MongoDBRussian/60218.
Yaroslav
Сделай как я показал
Oleg
а robo-t3 поддерживает новые версии монги 4.2.х ?
Anonymous
Сделай как я показал
Сделал const entries = await Subscription .aggregate([ { $match: { timestamp: req.params.timestamp } }, { $project: { price: 1 } } ]) .limit(parseInt(req.params.limit, 10)); ошибок в консоли нет, показывает пустой массив [].
Anonymous
Роут выглядит так: router.post('/prices/:timestamp/:limit', ...).
Anonymous
Вставил timestamp цифрой на место req.params.timestamp, получил массив price'ов для этого timestamp.
Anonymous
Вставил на то же место { $match: { timestamp: [req.params.timestamp] } }, получил пустой массив [].
Anonymous
Пофиксил через { $match: { timestamp: parseInt(req.params.timestamp, 10) } }. Спасибо.
yopp
добавил $limit
yopp
если вы хотите посчитать уникальные цены за время и ограничить
Anonymous
Что есть price:1 ?
Заменил на { price: true }, работает.
Anonymous
добавил $limit
Спасибо.
yopp
если просто все цены, то уберите $match
yopp
4.2.1 (Oct 18) ◦ 4.0.13 (Oct 19) • Плейграунд для запросов • Документация • Официальные курсы по MongoDB Stable: 4.2.1 ◦ Bugfix: 4.0.13 Legacy: 3.6.14 (Aug 26) ◦ EOL: 3.4.23 (Sep 16, 💀 Jan ‘20) По вопросам покупки Enterprise лицензии пишите @dd_bb ☠️: 3.2.21 (Dec ’18), 3.0.15 (May ’17)
Anonymous
если просто все цены, то уберите $match
Все цены для индивидуального timestamp. Фактически, взять возврат от кода Yaroslav Kuznetsov и вместо массива price'ов вернуть сумму этих price'ов.
yopp
https://play.db-ai.co/m/Xbqyos6DoQAB55NU
Anonymous
https://play.db-ai.co/m/Xbqyos6DoQAB55NU
Интересно, однако, сейчас мне не нужны уникальные price, мне нужно просуммировать их для данного timestamp.
yopp
выберите любой аккомулятор и считайте с ним
yopp
не бойтесь читать документацию и самостоятельно экспериментировать
Anonymous
Вот этото код const entries = await Subscription .aggregate([ { $match: { timestamp: parseInt(req.params.timestamp, 10) } }, { $project: { price: true } } ]) .limit(parseInt(req.params.limit, 10)); возращает массив объектов с price, нужно вернуть ответом с роута просто сумму price'ов.
yopp
выберите подходящий вам аккомулятор и попробуйте переписать вот этот запрос с ним: https://play.db-ai.co/m/Xbqyos6DoQAB55NU
yopp
там есть fork кнопочка
yopp
не получится, скиньте что не получилось
Anonymous
$sum не работает с .aggregate, насколько читаю.
yopp
где вы это прочитали?
Anonymous
https://docs.mongodb.com/manual/reference/operator/aggregation/sum/#grp._S_sum
yopp
работает
yopp
вы попробуйте
yopp
плейгрануд всё стерпит
yopp
в худшем случае будет 500)
yopp
и я вам рекомендую прочитать вот этот раздел: https://docs.mongodb.com/manual/core/aggregation-pipeline/
Anonymous
.aggregate([ { $match: { timestamp: parseInt(req.params.timestamp, 10) } }, { $sum: '$price' }, { $project: { price: true } } ]) вернуло Unrecognized pipeline stage name: '$sum'.
Anonymous
Вроде, получил сумму price'ов через const entries = await Subscription .aggregate([ { $match: { timestamp: parseInt(req.params.timestamp, 10) } }, { $group: { _id: null, sum: { $sum: "$price" } } }, { $project: { _id: false, sum: true } } ]) .limit(parseInt(req.params.limit, 10));
yopp
Вместо limit используйте $limit в aggregate
yopp
Я не уверен что через курсор это работает так-же
Konstantin
Здесь есть кто нибудь кто на go пишет?
Konstantin
А в чём у вас вопрос?
Прошу помочь разобраться. Метод добавления документа https://godoc.org/go.mongodb.org/mongo-driver/mongo#Collection.InsertOne возвращает структуру InsertOneResult со свойством InsertedID типа interface{} https://godoc.org/go.mongodb.org/mongo-driver/mongo#InsertOneResult. Так вот не совсем понятно почему используется тип пустого интерфейса, ведь указанные значения без труда приводятся к типу primitive.ObjectID. По всей видимости в каких то случаях InsertedID может иметь значение которое нельзя будет отпарсить как primitive.ObjectID?
yopp
Да. _id может быть любым типом
yopp
_id может быть хоть массивом
Массивом не может :)
yopp
А всеми остальными — может
Vova
ну значит объектом)
Konstantin
Да. _id может быть любым типом
Он же всегда по сути в базе как строка ObjectId([12]byte)
Anonymous
Вместо limit используйте $limit в aggregate
const entries = await Subscription .aggregate([ { $match: { timestamp: parseInt(req.params.timestamp, 10) } }, { $group: { _id: null, sum: { $sum: "$price" } } }, { $project: { _id: false, sum: true } }, { $limit: parseInt(req.params.limit, 10) } ]) Работает, спасибо. С просто limit() после aggregate() тоже работало.
yopp
Он же всегда по сути в базе как строка ObjectId([12]byte)
это по-умолчанию. а так монга поддерживает любой bson тип как значение _id
yopp
кроме массива, потому что по _id уникальный индекс
Konstantin
кроме массива, потому что по _id уникальный индекс
Понял, т.е. туда можно что угодно положить
yopp
да. но поиск будет по полному совпадению с сериализованным в bson объектом. иногда туда складывают например {a: X, b: Y}, думая запросы по _id.a будут использовать индекс, но нет :)
yopp
только $eq по значению
Konstantin
Всем спасибо)
Konstantin
я
Спасибо, вопрос был пустяковый, уже разобрался
RapidCodeLab
Спасибо, вопрос был пустяковый, уже разобрался
👍 ну если что спрашивайте, я монгу в go пять месяцев юзаю
Anonymous
Как в таком поиске const entries = await Subscription .find({ timestamp: req.params.timestamp }) получить длину массива найдённых значений?
Anonymous
Читаю в инетах $size is only available to the aggregation framework. Мне тут не хочется оборачивать этот простой запрос в aggregation, тогда остаётся только снять .length с результата find().