Kenya-West
Как хранить вложенные документы, если нужно иметь обновленные версии вложенных документов?
Ситуация такая:
Есть три коллекции документов: events, rooms, users
Есть коллекция bookings, в каждом документе которого будет вложенный документ: по одному от events, rooms, users.
Вопрос: как реализовать хранение вложенных документов в bookings?
1. Вложить полностью все документы events, rooms, users? А потом обновлять их, если изменился документ в оригинальной коллекции?
2. Или просто ссылки на их _id хранить и искать findOne'ом потом по всем коллекциям их?
Требования:
- Highload не нужен
- Инфа о вложенных документах должна обновляться, если изменился соответствующий документ в отдельной коллекции.
Nick
Эм, хранить поле id а не все тело
Kenya-West
Nick
Как хранить вложенные документы, если нужно иметь обновленные версии вложенных документов?
Ситуация такая:
Есть три коллекции документов: events, rooms, users
Есть коллекция bookings, в каждом документе которого будет вложенный документ: по одному от events, rooms, users.
Вопрос: как реализовать хранение вложенных документов в bookings?
1. Вложить полностью все документы events, rooms, users? А потом обновлять их, если изменился документ в оригинальной коллекции?
2. Или просто ссылки на их _id хранить и искать findOne'ом потом по всем коллекциям их?
Требования:
- Highload не нужен
- Инфа о вложенных документах должна обновляться, если изменился соответствующий документ в отдельной коллекции.
делаете без всяких одм, то взгляните на $lookup, он как раз сделает выборку вместо дополнительного find. Если же это какойнить монгус, то взгляните на populate
Dmitriy
подскажите, пожалуйста, а есть ли в монго аналог distinct в рсубд? с фильтром уникальности уже после получения рекордсета и чтобы набор полей в рекордсет при этом сохранить?
Nick
https://docs.mongodb.com/manual/reference/method/db.collection.distinct/
Dmitriy
не совсем то, не могу задать несколько полей для фильтрации
Dmitriy
попробую описать задачу, может так понятнее будет
у меня есть коллекция комиссий в разрезе мерчант, поставщик
что-то вроде этого:
merchant | contractor | commission | strat_date
merchant 1 | contractor 1 | 3% | 2019-01-01
merchant 1 | contractor 1 | 5% | 2019-02-07
merchant 2 | contractor 1 | 7% | 2019-01-01
т.е. коллекция содержит информацию о комиссиях, включая комиссии в будущем, которые должны начать работать с определенной даты.
в рсубд я бы сделал так
select distinct merchant, contractor, commission from table order by strat_date desc
и на выходе получил бы
merchant | contractor | commission
merchant 1 | contractor 1 | 5%
merchant 2 | contractor 1 | 7%
Nick
тогда AF и group
Dmitriy
как сделать такое в mongo пока не понимаю, потому что ag требует в group наличие агрегирующей функции по полю
Dmitriy
т.е. я пока не понял как я могу в ag в group задать что по полю commission не надо ничего делать
Nick
прочитайте все доступные агрегирующие функции https://docs.mongodb.com/manual/reference/operator/aggregation/group/
Nick
и что значит ничего делать ен надо? вы уменьшаете количество объектов - значит вы чтото делаете
Dmitriy
Nick
на $first смотрели?
Nick
поэтмоу и говорю прочитайте про все, причем не краткое описание а как они работают
Oleg
Привет. есть репликасет из трёх нод. к примеру нода3 сейчас мастер. потом происходит бадабум.
хочется поднять одну ноду из трёх из бекапа (сделанной с помощью снапошота вирт.машины). и запустить её как примари.
понял что по сути без 2х нод нельзя чтобы в репликасет были выборы и объявлена примари.
вопрос, возможно ли 1 ноде сделать арбитера и чтобы она себя объявила примари и позволяла работать с клиентами как с репликасет?
yopp
Вам нужно чтоб суммарное количество участников в «видимой» части реплика сета было большинством
Oleg
интересно, а возможно ли на ноде, котора secondary удалить других участников ?
yopp
Нет
yopp
Ваши проблемы начинаются с идеи что какая-то конкретная нода должна быть праймари.
yopp
Но это логически противоречит идеи репликасета
yopp
Расскажите, какой риск у вас под «бадабум» подразумевается?
pplcf
В его сценарии бадабума умер весь реплика сет
pplcf
Как я понял
pplcf
Видимо вопрос как быстро его поднять и стать доступным клиентам
yopp
В случае с частичным восстановлением данных, реконфигурировать не обязательно
yopp
Если у вас есть дамп, то восстанавливаете только нужную коллекцию/ базу. Если у вас delayed hidden member, то делаете с него дамп и восстанавливаете. Если у вас снепшот, поднимаете его в stand-alone, делаете с него дамп и восстанавливаете.
yopp
Если кластер потерял работоспособность и починка не имеет смысла, то наиболее эффективно просто поднять кластер по новой из ближайшего бэкапа.
yopp
Выключаете кластер. Берёте снепшот и из него делаете первую ноду. Дальше либо добавляете пустые ноды, либо чтоб не ждать синхронизации так-же восстанавливаете их из снепшота и по новой добавляете в кластер
yopp
А попыток всунуть в кластер ноду с другими данными лучше избегать.
Oleg
у меня был предварительно сделанный бекап всех баз с помощью mongodump. в т.ч. возможно было поднять одну базу
" /bin/mongodump --username "$DUMPUSER" --password "$DUMPPASS" --authenticationDatabase admin --out ${CURBACKUPDIR} --gzip 2> dump.log "
ну хватило умения его восстановить, т.к. не смог пройти авторизацию на ноде без базы admin.
yopp
Перезапустить ноды без аутентификации за файрволлом и заливать в текущего праймари. Потом перезапусить с включённой аутентификацией
Oleg
Выключаете кластер. Берёте снепшот и из него делаете первую ноду. Дальше либо добавляете пустые ноды, либо чтоб не ждать синхронизации так-же восстанавливаете их из снепшота и по новой добавляете в кластер
@dd_bb
подскажи, как насчёт такого плана disaster recovery в ситуации (было 3 ноды в репликасете, без шардов, полная копия данных у каждой ноды. бадабум. подняли из снапшота вирт.машины одну из нод, считаем что она будет единственным участником репликасет , надо сделать чтобы она принимала на себя всех клиентов которые хотят цепляться к репликасету)
поднимаю ноду без аутентификации и без репликации. захожу локально, удаляю базу local.
потом поднимаю ноду с поддержкой репликации и создаю replicaset с нужным мне именем:
rs.initiate( {
_id : 'rstest',
members: [ { _id : 0, host : '192.168.220.10:27017' } ]
})
вуаля - клиенты могут цепляться к этой ноде, обнаруживать там репликасет rstest, и работать.
потом занимаюсь созданием пустых нод, синхронизацией.
есть в этом плане что я пропустил и чего делать не следует?
yopp
ваша проблема в «бадабум»
yopp
если вы хотите нормальный план, то вы начинаете с модели рисков
yopp
«бадабум» это не модель
yopp
вся суть плейбуков заключается в том, чтоб иметь последовательность простых отработанных шагов для каждого из риска. чтоб в момент отказа задача сводитась к двум этапам: классифицировать отказ, выполнить соотвествующий плейбук
yopp
когда у вас модель состоит из «бадабум» классификация невозможна
Oleg
в данном случае: сбой кластера, при котором сроки восстановления кластера средствами mongorestore/mongoimport - не известны, и приняли решение восстаналиваться из снапшотов виртуальной машины. причем целью сейчас стало побыстрее восстановить одну машину, запустить в работу.
yopp
«сбой кластера» это тоже не достаточно точное определние
yopp
мы говорим о полной потере кластера?
Oleg
да.
Oleg
я столкнулся с тем, что экземпляр стандалон не может быть использован вместо репликасет, потому что приложения лезут на него и запрашивают репликасет (по имени чтоли), и несмотря на то что пользовательские базы у экземпляра - как и должны быть, без создания репликасет приложения не могут с ним работать.
Oleg
для того чтобы переделать секондари из репликасет в стендалон - достаточно закомментировать в конфиге секцию replication и удалить базу local ?
Oleg
а чтобы объявить новый репликасет из стендалон - наоборот раскомментировать - и rs.initiate ( .. ) ?
yopp
в случае восстановления кластера, standalone это режим обслуживания. т.е. пока вы не инициализируете репликасет, ваша инсталяция не должна быть досттупна клиентам
yopp
приучитесь в standalone всегда запускать на отдельном порту
yopp
во-первых это поможет избежать случаев когда например, выключили аутентификацию для обслуживания и монга доступна миру
yopp
во-вторых, это защитит вас от непонятных эффектов типа описываемого
yopp
когда у нас клиенты начали долбиться в ноду, которая ещё не готова к эксплуатации
yopp
Oleg
использованое альтернативного порта при выполнении работ - для меня очень привычное правило
Oleg
спасибо
yopp
👍
Alexey
Добрый день, на сколько я понимаю, стейджи выполняются последовательно, начиная с дочерних, т е в моем случае IXSCAN -> FETCH -> LIMIT, почему ixscan возвращает всего 8 доков, если в данном диапазоне дат их гораздо больше, он каким-то образом возвращает уже отфильтрованное с помощью fetch?
Alexey
Alexey
yopp
стейджи выполняются последовательно, от верхнего к нижнему
Alexey
а каким образом может выполниться limit, если он даже не знает что лимитировать
yopp
мне кажется у вас ошибка в запросе
yopp
yopp
или в данных
yopp
это выглядит как строка, а не как дата, которая число :)
Alexey
да, это я дурак, спасибо, сделал new Date() вместо Date(), но я все равно не понимаю, как последовательность может быть limit -> fetch -> xscan
yopp
он а в обратную сторону читается
yopp
IX -> FETCH -> LIMIT
yopp
inputStage же
yopp
На вход LIMIT попал FETCH
yopp
на вход FETCH попал IXSCAN
yopp
IXSCAN был по полному совпадению со строкой
Alexey
меня сбило то, что я искал по строке дату) пойду перепроверять все, спасибо большое!
Alexey
на сколько я понимаю, монга сама преобразовывает дату в такой формат
yopp
хм. может быть. но вот в самом запросе похоже на правду
Alexey
все равно не понимаю, у меня запрос
db.Event.find({terminal: ObjectId("5bb5ef6c3f43c012d04d5134"), mapData: ObjectId("5bad596aba52d909d8c68cb9"), changedAt: {$lte: new Date('2019-01-09T08:00:58.000Z')}}).sort({changedAt: -1})
записей удовлетворяющих запросу {changedAt: {$lte: new Date('2019-01-09T08:00:58.000Z')}} у меня 150к,
запросу {terminal: ObjectId("5bb5ef6c3f43c012d04d5134"), mapData: ObjectId("5bad596aba52d909d8c68cb9"), changedAt: {$lte: new Date('2019-01-09T08:00:58.000Z')}} у меня 11,
откуда у нее на момент xscan’a nreturned 2, keysExamined: 2, на момент fetch nReturned: 1, docsExamined: 2
используется только индекс по changedAt: -1
Alexey
разве по логике она не должна передать из ixcan в fetch 150к, там еще отфильтровать до 11 и сделать лимит 1
Alexey
я конечно рад, что монга превосходит мои ожидания, но я так никогда в жизни не пойму, как работают индексы
yopp
а покажите executionStats