yopp
Можно ещё Attribute Value, но в данном случае это скорее всего не требуется: { constants: [ {name: 'foo', value: 1}, {name: 'bar', value: 2}, ]}
Anonymous
> db.regions.find(); { "_id" : ObjectId("605338dc9565528893b347b9"), "name" : "Рязанская область" } { "_id" : ObjectId("605338dc9565528893b347ba"), "name" : "Московская область" } > db.cities.find(); { "_id" : ObjectId("605339039565528893b347bb"), "name" : "Рязань", "regionid" : "605338dc9565528893b347b9" } { "_id" : ObjectId("605339039565528893b347bc"), "name" : "Спасск", "regionid" : "605338dc9565528893b347b9" } { "_id" : ObjectId("605339039565528893b347bd"), "name" : "Коломна", "regionid" : "605338dc9565528893b347ba" } > Надо вывести Города (из cities коллекции), чтобы они еще и имели указание Региона (из regions-коллекции): > db.cities.aggregate([ {$lookup: {from: "regions", localField: "regionid", foreignField: "_id", as: "result"}} ]) { "_id" : ObjectId("605339039565528893b347bb"), "name" : "Рязань", "regionid" : "605338dc9565528893b347b9", "result" : [ ] } { "_id" : ObjectId("605339039565528893b347bc"), "name" : "Спасск", "regionid" : "605338dc9565528893b347b9", "result" : [ ] } { "_id" : ObjectId("605339039565528893b347bd"), "name" : "Коломна", "regionid" : "605338dc9565528893b347ba", "result" : [ ] } > В result[], где предполагается выводиться Регион - пустота. Это из-за того, что cities.regionid - это строка. А его аналог foreign-key, regions._id = Объект. Ни $toString(), ни $addFields, ни $project не помогают! Версия 4.2.
Anonymous
Привет!
Anonymous
уже 2 дня трахаюсь...
Vitalii
а переводить regionid в ObjectId?
Vitalii
пробовали?
Anonymous
не пашет
yopp
не пашет
Вам необходимо хранить в cities regoinid в типе ObjectId. Так как $lookup будет делать запрос по _id коллекии регионов, а нам наверняка _id в ObjectId, а не строкой
Anonymous
дык проще уж тогда первичный ключ в regions _id пихать как строку а не объект
Anonymous
но имеем что имеем
Vitalii
https://ibb.co/TvxCn39
Vitalii
я могу ошибаться, но по моему не получится делать агрегацию с коллекции cities, а переводить _id  из коллекции regions в строку
Vitalii
нужно работать с текущей коллекцией
Anonymous
> db.cities.aggregate([ {$addFields: {regObjId: {$toObjectId: "$regionid"}}}, {$lookup: {from: "regions", localField: "regObjId", foreignField: "_id", as: "result"}} ]) { "_id" : ObjectId("605339039565528893b347bb"), "name" : "Рязань", "regionid" : "605338dc9565528893b347b9", "regObjId" : ObjectId("605338dc9565528893b347b9"), "result" : [ { "_id" : ObjectId("605338dc9565528893b347b9"), "name" : "Рязанская область" } ] } { "_id" : ObjectId("605339039565528893b347bc"), "name" : "Спасск", "regionid" : "605338dc9565528893b347b9", "regObjId" : ObjectId("605338dc9565528893b347b9"), "result" : [ { "_id" : ObjectId("605338dc9565528893b347b9"), "name" : "Рязанская область" } ] } { "_id" : ObjectId("605339039565528893b347bd"), "name" : "Коломна", "regionid" : "605338dc9565528893b347ba", "regObjId" : ObjectId("605338dc9565528893b347ba"), "result" : [ { "_id" : ObjectId("605338dc9565528893b347ba"), "name" : "Московская область" } ] }
Anonymous
браво! Виталий спасибо!
Vitalii
👍
Anonymous
кстати а как утт только определенные поля вывести? безо всяких _id? В обычных find(0 запросах это не проблема, но тут...
Vitalii
db.cities.aggregate([{$addFields:{regObjId:{$toObjectId:"$regionid"}}},{$lookup:{from:"regions",localField:"regObjId",foreignField:"_id",as:"result"}},{$project:{_id:0}}])
Vitalii
я обычно вручную выставляю поля в $project
Vitalii
может быть есть какой-то более верный способ
Anonymous
ааа так это в $project указывается - спасибо - прочту про него внимательнее
Anonymous
> db.cities.aggregate([ {$addFields: {regObjId: {$toObjectId: "$regionid"}}}, {$lookup: {from: "regions", localField: "regObjId", foreignField: "_id", as: "result"}}, {$project: {_id: 0, regionid: 0, regObjId: 0}} ]) { "name" : "Рязань", "result" : [ { "_id" : ObjectId("605338dc9565528893b347b9"), "name" : "Рязанская область" } ] } { "name" : "Спасск", "result" : [ { "_id" : ObjectId("605338dc9565528893b347b9"), "name" : "Рязанская область" } ] } { "name" : "Коломна", "result" : [ { "_id" : ObjectId("605338dc9565528893b347ba"), "name" : "Московская область" } ] } - удалил лишнее.... А реально сделать чтобы не было этого resulе, а просто было ...regionname: "Московская Область"
Никита
Может кто сталкивался с подобным: MongoDB 3.6 -> 4.2 в яндексе перенес. После переноса сайт дико тупит. На 3.6 - все норм работает. Монгус 5.11.15 версии (почти свежак). Никак понять не могу в чем дело... может есть инструмент какой-то, который запишет результаты выполнения запросов в файл или в лог для анализа (запросов много, раскопать почему тупить начинает очень сложно)
Anonymous
спасибо! сейчас буду разбираться с этой конструкцией
kk
У меня есть замечательная (нет) идея: есть ли механизм на уровне драйвера/бд который бы откидывал запросы не использующие индексы? Допустим аггрегации не берём, find(). Или это только постфактум можно делать, алертя на логи с COLLSCAN/docsExamined>N ?
yopp
спасибо большое)
там в конце очень важное замечение про использование в продакшене :)
yopp
(== не стоит)
kk
блин, жаль на коллекции нельзя выставить
Google
Всем привет как исправить монгодб
Google
не могу зупустить монгов Centos 8
Melonges
mongoose используется для облачной бд?
Maxim
Всем привет, начал изучать Монго, до этого работал из дома и сейчас пришел в офис и теперь не понимаю как в кластере сменить IP
Maxim
подскажите пожалуйста
Maxim
Да
Максим
Да
Не помню где, но там есть такая настройка. Потыкай в интерфейс. Или может кто подскажет.
Maxim
окей)
Maxim
О, спасибо большое)
Максим
там где нули у меня, напиши свой ип
Maxim
Разобрался
Maxim
А как же тут указать какие параметры?
Maxim
Понимаю что TS, но схема описания для монгуса
Anatoly
Привет. подскажите как правильно работать с транзакциями в монге. Есть такой код session = await mongoose.connection.startSession(); session.startTransaction(); try { updatedWallet = await walletModel.findOneAndUpdate( { accountId, type, }, { $inc: { balance, }, }, { session: session, new: true }, ); createTransaction = await transactionModel.create({ walletId: updatedWallet._id, direction, amount: Math.abs(balance), reason, meta: omitBy(meta, isNil), walletType: type, accountId: updatedWallet.accountId, }, { session: session, new: true }, ); } catch(e) { await session.abortTransaction(); session.endSession(); throw new Error(e); } await session.commitTransaction(); session.endSession(); это работает как ожидается до тех пор пока не делаются параллельные запросы через Promise.All([несколько вызовов сразу]). В этот момент выполняется первый запрос а второй отлетает с ошибкой writeconflict.
yopp
Привет. подскажите как правильно работать с транзакциями в монге. Есть такой код session = await mongoose.connection.startSession(); session.startTransaction(); try { updatedWallet = await walletModel.findOneAndUpdate( { accountId, type, }, { $inc: { balance, }, }, { session: session, new: true }, ); createTransaction = await transactionModel.create({ walletId: updatedWallet._id, direction, amount: Math.abs(balance), reason, meta: omitBy(meta, isNil), walletType: type, accountId: updatedWallet.accountId, }, { session: session, new: true }, ); } catch(e) { await session.abortTransaction(); session.endSession(); throw new Error(e); } await session.commitTransaction(); session.endSession(); это работает как ожидается до тех пор пока не делаются параллельные запросы через Promise.All([несколько вызовов сразу]). В этот момент выполняется первый запрос а второй отлетает с ошибкой writeconflict.
WriteConflict это корректное поведение. Если несколько транзакций изменяют один документ, только одна транзакция сможет сделать коммит, остальные будут отменены с WriteConflict. Разрешение конфликта остаётся на усмотрение приложения
yopp
Самый простой вариант: вынести всю подготовку данных и транзакцию в отдельный метод, так чтоб полностью изолировать вычисление нового состояния, завернуть его в try/catch и делать retry когда случается конфликт.
Ilya
всем привет, почему при передаче в метод .count фильтра с 2 полями - всегда возвращает 0?
Ilya
мб я что-то не так делаю
Ilya
model.countDocuments({ field1: 'test', field2: 'test' })
Anatoly
Самый простой вариант: вынести всю подготовку данных и транзакцию в отдельный метод, так чтоб полностью изолировать вычисление нового состояния, завернуть его в try/catch и делать retry когда случается конфликт.
Спросил потому что нашёл на стеке такую же ситуацию (https://stackoverflow.com/questions/65171579/mongoerror-writeconflict) при этом вопрошающий сказал что типа проблему решил, но не сказал как, вот и думал что может как то это просто решается
yopp
model.countDocuments({ field1: 'test', field2: 'test' })
В данном случае монга будет считать количество документов у которых оба поля одновременно имеют значение test. Это то поведение, которое вы ожидаете?
yopp
countDocuments(query) это эквивалент find(query).count
yopp
Если вы хотите условие ИЛИ, то используйте $or: [cond, cond]
Ilya
я разобрался, не то передавал
Melonges
у кого-нибудь получалось ставить локально бд на mac?
yopp
у кого-нибудь получалось ставить локально бд на mac?
Проще будет поставить через homebrew: https://docs.mongodb.com/manual/tutorial/install-mongodb-on-os-x/
yopp
Вы запускаете команду mongo, а это mongo shell: консольный интерактивный инструмент для взаимодействия с базой, но для него нужен сервер. Сам сервер это mongod, наверное он в этой-же поставке. Необходимо запустить сначала его, а потом уже к нему подключится. Но проще будет поставить из homebrew, так как там не надо будет ничего настраивать и сервер будет запускаться автоматически при старте системы. Плюс обновлять легче
Melonges
понял, спасибо
Melonges
А все пользуются компасом, никто не пользуется datagrip от jetbrains?
Amirbek
Добрый вечер. Кто делал деплой ? Mongoose connect как писать ? В локале норм работает а заливаю на сервер ошибка
Zaur
коллеги, подскажите где можно почитать подробности про вывод explain. Что означает каждый параметр и как вообще читать этот вывод? Это хороший результат или плохо ....
Sharyar
Всем привет. Как можно в модели описать схему координат? например: coords: { lat: xx.xxxxxx, lon: xx.xxxxx, }
yopp
коллеги, подскажите где можно почитать подробности про вывод explain. Что означает каждый параметр и как вообще читать этот вывод? Это хороший результат или плохо ....
Это вывод о том, какую стратегию выбрал планировщик для выполнения запроса. В первую очередь тут интересен сам план, указанный в winningPlan. Читается он в обратном порядке, от конца к началу. У вас первый шаг это IXSCAN, это поиск по индексу. В keyPattern видны поля которые будут использоваться для поиска по индексу. Где-то ниже будет поле shape, которое определяет диапазон ключей индекса по которым будет происходить поиск. FETCH это загрузка полного документа из результата поиска по индексу А SIMPLE PROJECTION это шаг выполняющий проекцию: трансформацию документа с удалением ненужных полей. Но сам план это не самая информативная часть, так как это только план. Интереснее сразу смотреть на то как план реально исполняется: для этого необходимо выполнить эксплейн с таким ключом explain({executionStats:true}) Там вы уже увидите статистику сколько времени занимает выполнение каждого шага. Там будет три ключевые метрики keysScanned, docsScanned и docsReturned. Первое это сколько ключей индекса потреблялось прочитать чтоб найти нужный результат. Второе сколько документов пришлось целиком просмотреть и третье это итоговое время выполнение шага в миллисекундах Наиболее эффективно когда первый шаг IXSCAN. Если первый шаг COLLSCAN то на больших объемах будут проблемы. Общий подход: docsReturned должен стремиться к keysScanned — значит что все условия поиска были покрыты индексом и в дальнейшем выкидывать документы не пришлось. docsScanned должен стремиться к keysScanned. Если docsScanned больше чем keysScanned, значит какая-то часть запроса выполняется мимо индекса Идеально когда docsScanned равен нулю :) Это возможно с covered queries. Ну и чем меньше приходится просматривать документов или индексов, тем быстрее будет запрос
Zaur
Это вывод о том, какую стратегию выбрал планировщик для выполнения запроса. В первую очередь тут интересен сам план, указанный в winningPlan. Читается он в обратном порядке, от конца к началу. У вас первый шаг это IXSCAN, это поиск по индексу. В keyPattern видны поля которые будут использоваться для поиска по индексу. Где-то ниже будет поле shape, которое определяет диапазон ключей индекса по которым будет происходить поиск. FETCH это загрузка полного документа из результата поиска по индексу А SIMPLE PROJECTION это шаг выполняющий проекцию: трансформацию документа с удалением ненужных полей. Но сам план это не самая информативная часть, так как это только план. Интереснее сразу смотреть на то как план реально исполняется: для этого необходимо выполнить эксплейн с таким ключом explain({executionStats:true}) Там вы уже увидите статистику сколько времени занимает выполнение каждого шага. Там будет три ключевые метрики keysScanned, docsScanned и docsReturned. Первое это сколько ключей индекса потреблялось прочитать чтоб найти нужный результат. Второе сколько документов пришлось целиком просмотреть и третье это итоговое время выполнение шага в миллисекундах Наиболее эффективно когда первый шаг IXSCAN. Если первый шаг COLLSCAN то на больших объемах будут проблемы. Общий подход: docsReturned должен стремиться к keysScanned — значит что все условия поиска были покрыты индексом и в дальнейшем выкидывать документы не пришлось. docsScanned должен стремиться к keysScanned. Если docsScanned больше чем keysScanned, значит какая-то часть запроса выполняется мимо индекса Идеально когда docsScanned равен нулю :) Это возможно с covered queries. Ну и чем меньше приходится просматривать документов или индексов, тем быстрее будет запрос
Ух как много интересного) пойду разбираться
yopp
Ух как много интересного) пойду разбираться
https://docs.mongodb.com/manual/reference/explain-results/
Speedy
Класс
Константин
Ребзя, help me please. Пытаюсь подключить монго к nestjs, и настроить простой поиск. В монге для коллекции сделал create search index, но при попытке поиска получаю ошибку MongoError: text index required for $text query. Подскажите пожалуйста что я не так делаю?
Физик-ядерщик
Подскажите пожалуйста, как можно удалить элемент из массива по его индексу?
Deni
Slice+spread