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
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 ?
https://docs.mongodb.com/manual/reference/operator/projection/positional/
Anonymous
Успел попробовать .aggregate([ { $group: { timestamp: req.params.timestamp } } ]), вернуло ошибку The field 'timestamp' must be an accumulator object.
Yaroslav
Anonymous
Множество объектов вида https://t.me/MongoDBRussian/60218.
Yaroslav
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
yopp
добавил $limit
yopp
если вы хотите посчитать уникальные цены за время и ограничить
Anonymous
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
yopp
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
Yaroslav
yopp
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 пишет?
yopp
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 может быть любым типом
Vova
yopp
yopp
А всеми остальными — может
Vova
Vova
ну значит объектом)
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
кроме массива, потому что по _id уникальный индекс
Konstantin
yopp
да. но поиск будет по полному совпадению с сериализованным в bson объектом.
иногда туда складывают например {a: X, b: Y}, думая запросы по _id.a будут использовать индекс, но нет :)
yopp
только $eq по значению
Konstantin
Всем спасибо)
RapidCodeLab
Konstantin
я
Спасибо, вопрос был пустяковый, уже разобрался
Konstantin
Anonymous
Как в таком поиске
const entries = await Subscription
.find({ timestamp: req.params.timestamp })
получить длину массива найдённых значений?
Anonymous
Читаю в инетах $size is only available to the aggregation framework. Мне тут не хочется оборачивать этот простой запрос в aggregation, тогда остаётся только снять .length с результата find().