LINUX.ORG.RU

Узнать сколько бутылок пива в магазине

 ,


0

2
Schema {
   shopName: String,
   beers: [{brand: String, vol: Number, alc: Number}]
}

model = new Schema();
model.findOne().countXXX



Нужно узнать сколько бутылок пива (countXXX) в магазинах, не вытаскивая все ящики

★★★★

Последнее исправление: gobot (всего исправлений: 1)

Не совсем понял что значит не вытаскивать все ящики. Тот же aggregate все равно читает этикетки на бутылках:

db.collection.aggregate([
  {
    $unwind: "$beers"
  },
  {
    $match: {
      "beers.brand": "Балтика9"
    }
  },
  {
    $group: {
      _id: null,
      count: {
        $sum: "$beers.count"
      }
    }
  }
])

Если под countXXX вы подразумеваете db.collection.countDocuments() то это буквально обертка, внутри которой тот же самый aggregate:

db.collection.aggregate([
   { $match: <query> },
   { $group: { _id: null, n: { $sum: 1 } } }
])
Obezyan
()

По простому никак.

Если очевидного индекса по магазу и/или бренду (+ запроса агрегатора) недостаточно, нужно делать свой materialized view и обновлять его периодически либо делать свой aggregate запрос c $merge. Можно навернуть дополнительный слой кеша, прямо в монге или соседнем редисе (ну мы же модную распределенную систему делаем, а чо). Но вообще монга старается кешировать результаты запросов, если они достаточно частые.

Если вопрос не из праздного любопытства, добавь больше информации: сколько данных, насколько большие группы, какой паттерн доступа к данным, и что ты вообще уже напрофилировал.

anonymous
()
Ответ на: комментарий от anonymous

Тут скорее стоит начать с вопроса «почему mongodb»? Такие данные просто идеальны для хранения в реляционной БД в третьей нормальной форме с индексацией и получением агрегированных данных с помощью реляционной алгебры. Одно удовольствие же с ними так работать, а не вот это вот все.

Obezyan
()
Ответ на: комментарий от Obezyan

У тебя должны быть очень веские причины, чтобы сегодня выбрать что-то отличное от постгреса. Этот дефолт легко отмасштабировать (если надо конечно) до огромных объемов и трафика. Встроенный json добавляет поддержку «документов».

Но, у ТС монга, и кто я такой, чтобы говорить ему все переделывать.

anonymous
()
Ответ на: комментарий от anonymous

Ну как то странно, срез можно сделать, вернуть частичный список

findOne().slice("beers", [0, 10])


А тупо подсчитать и вернуть количество нет? Мне данные если не нужны.

gobot ★★★★
() автор топика
Ответ на: комментарий от ya-betmen

Отдельную сущность заводить и обновлять ее при каждом добавлении? Мне кажется должно быть просто и очевидно, сделал выборку документов, в каждом из них есть массив, почему нельзя вернуть просто его размер? Размер массива же где то в бинарном виде хранится, тупо счетчик 1 байт, его же не нужно считать, обходя все элементы через for. Просто не могу понять почему нет простого решения без aggregate. Slice есть, а size нет.

gobot ★★★★
() автор топика
Ответ на: комментарий от gobot

Так тебе вроде все комментаторы выше сказали что задача говно и проектировщик - мудак.

Там же и правда нужен постгрес + разработчик уровня 60к рублей в месяц. А ты там кстати чем занимаешься? Не оч понятно.

anonymous
()
Ответ на: комментарий от gobot

Я как понимаю без этой уродливой конструкции с aggregate никак по другому?

Никак, это подход mongodb к получению агрегированных данных. А уродливо это все выглядит потому что для этих данных mongodb не очень подходит.

Мне то желательно документы получить в итоге

Причем тут документы? Вы написали «Нужно узнать сколько бутылок пива». Это число, а не коллекция документов где есть бутылки указанного бренда.

Obezyan
()
Ответ на: комментарий от gobot

Мне то желательно документы получить в итоге

Ну так и создай этот документ и считай бутылки в нем ручками. Вы хотели NoSQL, вы ее получили.

anonymous
()
Ответ на: комментарий от Obezyan

Причем тут документы? Вы написали «Нужно узнать сколько бутылок пива». Это число, а не коллекция документов где есть бутылки указанного бренда.

К каждому документу цеплять поле countBottle... хотя... я начинаю понимать в чем причина, в некотором дизайне, либо документ получай, либо произвольные данные aggregate,а микшировать никак нет

уродливо это все выглядит потому что для этих данных mongodb не очень подходит

ойй да ладно, подходит не подходит

*** MongoDB подходит для следующих применений: ***

регистрация и хранение информации о событиях;
системы управления документами и контентом;
электронная коммерция;
игры;
данные мониторинга, датчиков;
мобильные приложения;
хранилище операционных данных веб-страниц (например, хранение комментариев, рейтингов, профилей пользователей, сеансы пользователей)

gobot ★★★★
() автор топика
Ответ на: комментарий от ya-betmen

Просто select count

просто? Из 2 таблиц данные же будут. select *, (select count from beers where show_id = s_id) as countB from shops

А в монго в 1 документе. Проблем по сути нет, если вытащить все эти бутылки и локально подсчитать array.length, но зачем мне их вытаскивать, если я с этими данными работать сейчас не буду. Собственно мне нужно сделать проверку перед добавлением бутылки в магазин. Если бутылок больше 10, то выгнать поставщика, ибо нет места в магазине.

Просто я не пойму почему бл такое через aggregate только делается! Западло мне так делать. Хочу в документ добавить «инородное поле»

ЗЫ. Есть там $push {$slice}... Но это truncate, старые бутылки будут потеряны, но магаз не переполнится... Но хочется проверку хотя бы перез $push

gobot ★★★★
() автор топика
Последнее исправление: gobot (всего исправлений: 1)

Ладно я спать, завтра продолжим. Пишите пока все решения, которые мне подойдут по проверке бутылок перед добавлением. Если > 10, то не добавлять и дать пинка поставщику который их принес. НО, не вытаскивая все бутылки. $push {$slice} не предлагать

gobot ★★★★
() автор топика
Ответ на: комментарий от gobot

Просто я не пойму почему бл такое через aggregate только делается! Западло мне так делать. Хочу в документ добавить «инородное поле»

Так aggregate это база. Запросов в mongoDB, куча функций буквально обертки над ним.

Мало того что вы используете не правильный инструмент для задачи (допустим, так исторически сложилось до вас), но вы еще и воротите нос от правильного использования этого инструмента. Стреляете себе не только в правую но и левую ногу так сказать. Вы эникейщик самого низкого пошиба, фу таким быть.

Obezyan
()