yopp
поменяйте схему и добавьте какой-то флаг
Vadim
флаг - это количество ключей?
yopp
если вы опираетесь в выборках на количество ключей, вы где-то в схеме свернули совсем не туда
Vadim
лучше тогда на массивы поменяю, спасибо
yopp
количество ключей это не условие выборки
yopp
массивы тоже плохо
yopp
если вы можете заранее добавить какой-то признак, например при вставке документа посчитать ключи, то делайте это при вставке
yopp
динамические подсчёты будут стоить чтение всей коллекции + куча памяти
Vadim
yopp
а если вы будете это делать при вставке, вы сделаете индекс по этому полю и это будет очень быстрая операция
Vadim
Опишу свой кейс, хочу удалить у объекта документа ключ, но проверяю, что бы остался хотя бы 1, документ ищу по ObjectId(_id)
Pavel
Привет сообщество. Есть коллекция документов с метками либо start либо end, и нужно для каждого документа со start найти документ с >= к нему меткой end. Реализовал с помощью aggregate, где матчил сперва документы со start, потом следующим шагом lookup-ом к каждому элементу добавлял массив end меток, которые больше или равны start и брал из полученного массива минимальный и уже выгружал готовые (start, end) отрезки в отдельную "handled" коллекцию. И вроде цель достигнута, но чувство костылизации не покидает и есть проблема в скорости выполнения всего этого. Документов в коллекции может быть больше 1кк, и для каждой метки start найти end таким образом достаточно затратная по времени операция. Можно ли как-то реализовать эту задачу более эффективно, мб есть какие-то общие практики, либо инструменты в монго для решения подобного?
Roman
если в find указат projection, то вернется только то что там указно, или необходимо на ВСЕ что не нужно делать false?
Roman
то есть нужно ли excludить все поля, иначе они вернутся?
yopp
можно и так и так https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/
Nick
Привет сообщество. Есть коллекция документов с метками либо start либо end, и нужно для каждого документа со start найти документ с >= к нему меткой end. Реализовал с помощью aggregate, где матчил сперва документы со start, потом следующим шагом lookup-ом к каждому элементу добавлял массив end меток, которые больше или равны start и брал из полученного массива минимальный и уже выгружал готовые (start, end) отрезки в отдельную "handled" коллекцию. И вроде цель достигнута, но чувство костылизации не покидает и есть проблема в скорости выполнения всего этого. Документов в коллекции может быть больше 1кк, и для каждой метки start найти end таким образом достаточно затратная по времени операция. Можно ли как-то реализовать эту задачу более эффективно, мб есть какие-то общие практики, либо инструменты в монго для решения подобного?
печаль беда, вам прямой путь к изменению структуры документов. самое простое - вынести дату в отедльное поле и добавить флаг начало это или конец, тогда по крайней мере можно будет обычной сортировкой взять нужную пару доков, хотя это всеравно не за один запрос будет
Roman
'business.business_email': {
'$type': 2
}
возвращает и пустые строки, как сделать только непустые и не null?
yopp
Pavel
документы со start приходят раньше документов с end?
Необязательно, бывает и наоборот. реален кейс и когда обе метки есть у документа, и start и end. Но эти документы можно исключить, я думаю, и оставить как есть, а вот между одиночными (либо то, либо то) нужно организовать пары, одно из первых решений что приходит, как раз поиск ближайшего большего или равного для метки start.
Nick
Pavel
Nick
т.е. ест ьвремя, по которому можно отсортировать, есть метки, и нужно просто все склеить в фулл?
Nick
и как я понимаю исходные данные хранить нет необходимости и их можно удалять после склейки
yopp
т.е. у вас есть общий для двух документов c end и start идентификтор?
Nick
а в новой пачке придет чтото со строго большим временем?
Nick
т.е. сохраняется ли монотонность роста времени? или они могут из прошлого приходить, и если могут то на сколько из прошлого?
Nick
а лучше приведите тупо пример данных
Pavel
Nick
причем желательно сразу максимально сложный случай
yopp
т.е. у вас есть временной ряд, разбитый на неупорядоченные отрезки, у которых могут быть указаны только начало, только конец или начало и конец. задача восстановить порядок ряда?
Nick
походу посчитать время активности с датчиков
Pavel
https://docs.google.com/spreadsheets/d/1K5_pEIE1GyQtUomxhnAsG46wKupNlSA8Ry1x0UM0w2k/edit?usp=sharing
Pavel
в таблице это нагляднее
yopp
а что получить надо?
Egor
Привет сообщество. Есть коллекция документов с метками либо start либо end, и нужно для каждого документа со start найти документ с >= к нему меткой end. Реализовал с помощью aggregate, где матчил сперва документы со start, потом следующим шагом lookup-ом к каждому элементу добавлял массив end меток, которые больше или равны start и брал из полученного массива минимальный и уже выгружал готовые (start, end) отрезки в отдельную "handled" коллекцию. И вроде цель достигнута, но чувство костылизации не покидает и есть проблема в скорости выполнения всего этого. Документов в коллекции может быть больше 1кк, и для каждой метки start найти end таким образом достаточно затратная по времени операция. Можно ли как-то реализовать эту задачу более эффективно, мб есть какие-то общие практики, либо инструменты в монго для решения подобного?
Скайлайн прямая, работает за nlogn, может пригодится, загугли
yopp
скайлайн для экстремумов серии же
Pavel
походу посчитать время активности с датчиков
почти в точку, но то, в каком формате данные приходят как раз таки и проблема) и чтобы хотя-бы чуть-чуть нормализовать это все, выбрал способ поиска ближайшего большего.
yopp
тип задачи ещё не ясен до конца
yopp
Egor
Pavel
из этой таблицы что получить то надо? :)
я хочу получить пары. старт - ближайший к нему end. значения, для которых пары не найдется, исключить, будем считать, что они появятся при следующей агрегации
Pavel
и так через n количество минут агрегировать данные в отдельную коллекцию
yopp
yopp
внутри start и end монотонность сохраняется?
Pavel
yopp
если у вас нет гарантии late arrival, то ваша задача не имеет решения
yopp
так как у вас может быть ситуация, когда пришла пара start / end, которая формирует валидный отрезок, но чуть позже придёт другая пара которая попадает внутрь этого отрезка
yopp
либо вам придётся при каждой вставке перестраивать весь ряд
yopp
до какой-то степени задачу можно оптимизировать, перестраивая только «вперёд», но это в любом случае уже не к монге
yopp
сколько таких событий в минуту происходит?
Pavel
если у вас нет гарантии late arrival, то ваша задача не имеет решения
Из-за отсутствия гарантий, что в определенный момент времени все пары существуют, и что они правильно отсортированы и т.д, как раз, мне кажется, и можно допустить такой способ, как нахождение для каждого старта его ближайшей пары.
Да, тут уже кажется обсуждение не самого инструмента пошло)
yopp
вы не можете найти его один раз
yopp
вам сначала пришло
08/12/2018 1:30:41 start
08/12/2018 2:28:58 end
вы сделали отрезок 08/12/2018 1:30:41 по 08/12/2018 2:28:58
а потом пришло
08/12/2018 1:30:41 end
и что вы будете делать? :)
yopp
ваша проблема решается монотонным счётчиком на стороне источника событий
yopp
чтоб вы видели пропуски
yopp
второе решение — буфферизация и постоянный пересчёт
Nick
@pashkapo а как быстро нужен результат? типа можно например подождать пару часов, чтобы иметь боле менее стабильный отрезок времени?
yopp
она не решается
yopp
тьфу
yopp
я ещё раз повторюсть: если у вас нет жесткой гарантии что через N времени вам приедут вообще все события, то вы ничего не можете сделать
yopp
единственная опция: пересчитывать весь ряд при вставке
yopp
и дальше есть оптимизации
Nick
можно зайти с другой стороны, а для чего вам эти результаты?
yopp
но в целом, при late arraival вы будете вынуждены пересчитать весь ряд с временной отметки опоздавшего события
yopp
и добавив буфер вы можете ускорить расчёт «хвоста»
yopp
но если вам приедет точка годовалой давности, то ваш ряд превратится в тыкву
yopp
и эти данные они фундаментально ненадёжные
yopp
т.е. вы не можете полагаться на этот ряд, так как он может изменится
yopp
по этому я сразу и спросил про гарантии «опоздания»
yopp
нет гарантии, нет решения задачи
Pavel
Ладно, кажется мы отошли от обсуждения самого инструмента. В любом случае большое спасибо. Так или иначе нужно на какой-то компромисс пойти. В данном случае это пересчет всего ряда через n времени
yopp
вы не уловили проблему
yopp
ваши расчёты — мусор
yopp
потому что вы не можете гарантировать правильность ряда
yopp
либо жесткий deadline по доставке событий, либо монотонно возрастающий счётчик
yopp
во всех остальных случаях ваш ряд будет в неконсистентном состоянии