Алексей
не буду душнить гарантиями доставки и идемпотентностью, задам простой вопрос -а как именно Маша понимает что ее сообщение отправленное Пете доставлено/прочитано? в твоем конкретном мессенджере.
Nalik
Я предполагаю, что будет отправляться сокет с идентификатором последнего прочитанного сообщения. Исходя из этого предполагается, что все сообщения выше так же были прочитаны. Ну это такая упрощенная схема )
Nalik
Конечно может быть ситуация когдай я просвайпил чат и не прочитал часть сообщений и т.д. Но я думаю можно упростить до такой схемы.
Алексей
не знаю что такое "отправляться сокет", вот пример -Маша написала "привет" в твоем клиентском ПО и нажала ентер, далее предположу через какой то транспорт например вебсокеты сообщение отправлено на сервер. Что дальше? как клиентское ПО Маши узнает что Петя получил/прочитал сообщение?
Nalik
Пока точно не знаю, но предполагаю следующее: Когда Маша написала "привет" и нажала "ентер", то по вебсокету на сервер отправился пакет с её сообщением. Вебсокет отправляет всем участникам конкретного чата это сообщение. Клиенты участников чата в ответ должны отправить ID сообщения если они его прочитали. Этот ID будет заноситься в поле последнего прочитанного сообщения для конкретного клиента.
Nalik
У тебя есть предложения лучше?)
Nalik
Но эта логика уже будет возложена на клиент. Ты вроде негодовал, что клиент не выполняет никакой логики. Вот она 😄
Алексей
У тебя есть предложения лучше?)
я подвожу тебя к мысли, прямым текстом ты ее не всопринял попробую обходными путями. я пока спросил про переписку 1-1, но давай реально возьмем чат, что в твоем понимании означает прочитанное сообщение в чате на 1000 тел? все прочли, 1 прочел и это не автор сообщения, 1 прочел и это автор сообщения?
Nalik
Ничего не понял из твоего посыла и если честно я чувствую какую-то предвзятость, я тут не для того, чтобы продвигать свои убеждения. А чтобы попросить совета, может быть вместе обсудить если другим будет это интересно :)
Алексей
я просто спросил как ты планируешь это делать -не вижу ничего страшного в вопросе. То есть например для чата в 1000 тел порождает ли одно сообщение тысячу сообщений на сервер о доставке и потом тысячу о прочтении?
Nalik
я просто спросил как ты планируешь это делать -не вижу ничего страшного в вопросе. То есть например для чата в 1000 тел порождает ли одно сообщение тысячу сообщений на сервер о доставке и потом тысячу о прочтении?
Судя по всему да, при условии, что все 1000 пользователей находятся онлайн и смотрят чат: 1 сообщение порождает 1000 сообщений о прочтении от этих пользователей. Но как я уже говорил я не дошел до реализации этого, потому в каком виде это будет говорить не могу.
Nalik
Я вообще не думал еще об этом, но предполагаю, что Маше действительно нужно как-то узнать, что её сообщение прочитали все. По типу синей/серой галочки.
Nalik
ну и предположу что сервер разошлет всем учтасникам инфу например в виде ивента что сообщение маши прочитано?
Другим участникам не нужно знать, что все прочитали сообщение Маши. Это должна знать только Маша
Nalik
По крайней мере так сейчас это сделано в ТГ например
Nalik
Но есть большая разница между 1000 участников в чате и 1000 участников онлайн в чате)
Nalik
Хотя думаю стоит проектировать с тем учетом, что вся 1000 будет онлайн)
Алексей
Другим участникам не нужно знать, что все прочитали сообщение Маши. Это должна знать только Маша
ок, пусть будет только она, но ведь наверное этот ивент ты отправишь на все клиенты с которых Маша подключена? на ее ноут, мобилу, браузер?
Nalik
К чему вопросы в целом? )
Nalik
Они конечно полезны, с точки зрения общего видения )
Алексей
ну вот, Маша заходит с ноута, он шлет запрос на сервер чтобы получить все новые сообщения, а также и все ивенты. Скажем всего сообщений с ее визита на конкретно этом девайсе 50, но есть ивенты что 25 она прочла на другом девасе (мобиле). не можем ли мы 50-25 прямо на клиенте и показать ей счетчик непрочитанных 25 на чате по монге? и ничего на беке не вычислять?
Nalik
Я предполагаю, что так и должно быть :)
Nalik
Мои вопросы были связаны с API для получения всех чатов. Не новых чатов, а вообще всех.
Nalik
Примерно так
Nalik
Я хочу на бэке подготовить API которое будет дергать клиент по своему усмотрению и руководствуясь своей логикой
Nalik
Этот запрос тянет за собой объект чата, который содержит следующие поля
Nalik
Ладно, уже поздно. Пора отдыхать. Спасибо за общение и советы. Касательно логики на клиенте - спасибо, тоже это обдумаю.
Nalik
Доброе утро 😄 Schema.pre(["save", "update", "updateOne", "updateMany", "replaceOne", "findByIdAndUpdate", "findOneAndUpdate", "findOneAndReplace"], async function (next) Можно ли в Middleware узнать по какому триггеру сработало? UDP: Нашел такие свойства this.$__.op и this.$op которые возвращают название "события" и судя по всему только для save. А свойство this.op существует только для операций update*. Но не знаю правильный ли это способ. В итоге сделал так const eventType = (this.$op ? this.$op : this.op); , если есть способ лучше, скажите пожалуйста :)
Vladislav
привет всем! работаю с mongodb из c# может знаете как мне понять что коллекция которую я запрашиваю у Realm - пустая?
Vladislav
.count()?
не помогает
Just
не помогает
а что возвращает
Vladislav
возвращает 0 суть в том, что обертка c# над realm - возвращает не саму коллекцию, а ссылку на коллекцию а сами данные приходят только потом, чуть позже и получается что var result = realm.All<Entity>(): - // RealmCollection with empty result var count = result.Count(); // == 0 там есть метод SubscribeForNotifications(I R e a l m C o l l e c t i o n < T > s e n d e r , C h a n g e S e t ? c h a n g e s ) туда первый нотификейшн прилетает changes == null и если данные есть, то прилетает второй нотификейшн с changes != null а вот если коллекция пустая, то нотификейшена второго - нет
Just
тебе же count возвращает 0, ты именно в notification нужно это получать?
Vladislav
тебе же count возвращает 0, ты именно в notification нужно это получать?
оно всегда возвращает 0, потому что по факту данные с монги еще не пришли, а обертка уже отдалась вызывающему коду нотификейшн - это одна из мер понять что коллекция пустая, но не прокатило
Vladislav
почему всегда? это случай с realm?
да, это realm возьмем 2 ситуации 1) var result = realm.All<Entity>(): - // RealmCollection with empty result var count = result.Count(); // == 0 2) var result = realm.All<Entity>(): - // RealmCollection with empty result wait 5 seconds var count = result.Count(); // == 5 (for example) в 1 и 2 случаях realm.All - возвращает коллекцию обертку в вызывающий код, в которой нет данных на данный момент далее если сделать пойти по пути (1) и вызывать метод Count(), то вернется 0, потому что данных физически еще нет но если подождать какое-то время, пока запрос выполнится и данные вернутся, то для не пустой коллекции, метод Count() вернет некоторое конкретное число, ну и 0 для пустой соответственно но я ж не могу полагаться на эту задержку
Just
очень странно, может это так для c# и realm не работаю ни на том, ни на другом для меня в result была бы схема, а в count количество данных, то есть обращение в монгу а тут как будто ты объявляешь схему и через какое-то время запрашиваешь количество, хотя количество изначально там какое-то есть
Алексей
я уверен -в доке реалм описано как верно делать
Vladislav
я уверен -в доке реалм описано как верно делать
возможно, но пока не нашел буду дальше искать
Nalik
В данном примере сортировка замедляет процесс в 4 раза. Без сортировки запрос выполняется ~25 ms. С сортировкой ~105 ms. А мне всего-лишь нужно выбрать последнее сообщения чата.. { $lookup: { from: 'messages_list', let: { chatID: '$chat_id' }, pipeline: [ { $match: { $expr: { $and: [{ $eq: ['$chat_id', '$$chatID'] }, { $eq: ['$msg_del_time', 0] }] } } }, //{ $sort: { msg_id: -1 } }, //ЭТО ЗАМЕДЛЯЕТ ПРОЦЕСС { $sort: { _id: -1 } }, //И ЭТО ЗАМЕДЛЯЕТ ПРОЦЕСС //{ $group: { _id: null, maxMsgId: { $max: '$msg_id' } } }, //И ЭТО ТОЖЕ { $limit: 1 }, ], as: 'dbLastMessage', }, }
Nalik
Можно ли выполнить выборку с конца коллекции без использования медленного sort?
Nalik
100мс не время))
Я тут интересную картину обнаружил.. В коллекции messages_list хранится информация обо всех сообщениях с полями: msg_id, msg_local_id,msg_del_time, chat_id, user_id, text и т.д. Поле msg_id содержит глобальный идентификатор сообщения который начинается от 1 и может быть более миллиона. Поле msg_local_id содержит локальный идентификатор сообщения в рамках конкретного чата, обычно это значение меньше чем msg_id. Например если у нас есть 3 чата и в каждом по 10 сообщений. То у самого последнего сообщения будет msg_id равно 30, а msg_local_id равно 10. Я заметил интересную особенность. Если производить сортировку по msg_id то она происходит долго, но если по msg_local_id то быстро. { $lookup: { from: 'messages_list', let: { chatID: '$chat_id' }, pipeline: [ { $match: { $expr: { $and: [{ $eq: ['$chat_id', '$$chatID'] }, { $eq: ['$msg_del_time', 0] }] } } }, //{ $sort: { msg_id: -1 } }, //ЭТО ЗАМЕДЛЯЕТ ПРОЦЕСС { $sort: { msg_local_id: -1 } }, { $limit: 1 }, ], as: 'dbLastMessage', }, } Отсюда вопрос, ВТФ ???
Nalik
Стоит добавить, что поле msg_id является индексом, а поле msg_local_id индексом в связке с полем chat_id. Кстати говоря поле chat_id является так же отдельным индексом.
Nalik
Вопрос "это тут откуда" снимается.
Nalik
В случае сортировки по msg_local_id explain выдает следующее: { '$lookup': [Object], totalDocsExamined: 31, totalKeysExamined: 31, collectionScans: 0, indexesUsed: [Array], nReturned: 30, executionTimeMillisEstimate: 14 } В случае сортировки по msg_id explain выдает следующее: { '$lookup': [Object], totalDocsExamined: 30000, totalKeysExamined: 30000, collectionScans: 0, indexesUsed: [Array], nReturned: 30, executionTimeMillisEstimate: 79 }
Nalik
Вообще непонятно почему в одном случае затронуто 31 документ, а в другом 30к
Nalik
Для msg_local_id { '$lookup': { from: 'messages_list', as: 'dbLastMessage', let: { chatID: '$chat_id' }, pipeline: [ { '$match': { '$expr': { '$and': [ { '$eq': [ '$chat_id', '$$chatID' ] }, { '$eq': [ '$msg_del_time', 0 ] } ] } } }, { '$sort': { msg_local_id: -1 } }, { '$limit': 1 } ] }, totalDocsExamined: 31, totalKeysExamined: 31, collectionScans: 0, indexesUsed: [ 'chat_id_1_msg_local_id_1' ], nReturned: 30, executionTimeMillisEstimate: 13 } Для msg_id { '$lookup': { from: 'messages_list', as: 'dbLastMessage', let: { chatID: '$chat_id' }, pipeline: [ { '$match': { '$expr': { '$and': [ { '$eq': [ '$chat_id', '$$chatID' ] }, { '$eq': [ '$msg_del_time', 0 ] } ] } } }, { '$sort': { msg_id: -1 } }, { '$limit': 1 } ] }, totalDocsExamined: 30000, totalKeysExamined: 30000, collectionScans: 0, indexesUsed: [ 'chat_id_1' ], nReturned: 30, executionTimeMillisEstimate: 75 }
Nalik
думаю ответ теперь очевиден почему с локал быстрее?)
Потому, что индексов в связке chat_id_1_msg_local_id_1 всего 30, а вот почему не используется индекс msg_id я кстати не понял
Nalik
Я правильно понимаю?
Nalik
Я точно знаю, что msg_id является индексом. Но видимо pipeline игнорирует отдельные индексы при сортировке. Других объяснений у меня нет.
Nick
Потому, что индексов в связке chat_id_1_msg_local_id_1 всего 30, а вот почему не используется индекс msg_id я кстати не понял
потому что дороже чем просто считать данные. Потоковое чтение против рендом аксеса
Nalik
потому что дороже чем просто считать данные. Потоковое чтение против рендом аксеса
Можно как чайнику объяснить? Я с монго дай бог, чтобы неделю знаком
Nick
Можно как чайнику объяснить? Я с монго дай бог, чтобы неделю знаком
это не монго, это просто теория работы любой СУБД, которая упирается в работу с файлами, которая упирается в физику дисков. Над этим всем еще надо бы разобраться с работой кэшей как самого диска, так и ОС. И только после уже можно смотреть в сторону конкретных реализаций монги и ее планировщика и как он выбирает какой индекс использовать, да и использовать ли вообще
Nalik
Правильно ли я понимаю, из данных explain в данном примере получается, при сортировке по msg_local_id используется индекс, а при сортировке по msg_id не используется.
Nick
именно это и написано в indexesUsed
Nalik
угу. Для сравнения сделал запрос вообще без сортировки. Результат explain { '$lookup': { from: 'messages_list', as: 'dbLastMessage', let: { chatID: '$chat_id' }, pipeline: [ { '$match': { '$expr': { '$and': [ { '$eq': [ '$chat_id', '$$chatID' ] }, { '$eq': [ '$msg_del_time', 0 ] } ] } } }, { '$limit': 1 } ] }, totalDocsExamined: 30, totalKeysExamined: 30, collectionScans: 0, indexesUsed: [ 'chat_id_1' ], nReturned: 30, executionTimeMillisEstimate: 10 }
Nalik
@yatoba спасибо большое за помощь и за наводку про explain, без неё был как слепой))
Nick
@yatoba спасибо большое за помощь и за наводку про explain, без неё был как слепой))
если что во всех зрелых субд имеется экплейн как раз для целей поиска узких мест при выполнении запросов
Nalik
Кстати вот, что отвечает чатГПТ на вопрос почему в одном случае используется индекс, а в другом нет. Поле msg_id является глобальным идентификатором сообщения, а поле msg_local_id является локальным идентификатором сообщения в рамках конкретного чата. При использовании сортировки по полю msg_id в операторе $lookup, MongoDB не может использовать индекс, так как в данном случае поле msg_id является индексом в коллекции messages_list, а не во внешней коллекции, с которой производится операция $lookup. Однако, при использовании сортировки по полю msg_local_id, MongoDB может использовать индекс, так как данное поле является частью индекса chat_id_1_msg_local_id_1. Поэтому операция $lookup сортируется с использованием индекса, что повышает производительность запроса. В результате, сортировка по полю msg_local_id использует индекс и выполняется более быстро, чем сортировка по полю msg_id.
Dmitr
Dmitr
Здравствуйте объясните пожалуйста мем
Dmitr
Я пользовался монгой раньше но лень разбираться в операторах для мема
Dmitr
@dd_bb
Liber
Здравствуйте объясните пожалуйста мем
Мем в том, что синтаксис такой себе)
Dmitr
Мем в том, что синтаксис такой себе)
ясно. видал интерфейсы и похуже) спасибо!
Алексей
так and лишний)
Nalik
именно это и написано в indexesUsed
Если сделать индекс по двум полям chat_id и msg_id, то индексы будут использованы. Интересная особенность. Schema.index({ chat_id: 1, msg_id: 1 }, { unique: true });
Just
кто-то знает advanced практики профайлинга монги? performance возвращает данные отрывками
Нуриддин
Добрый день всем а чем отличается mongodb от варианта реализации percona если есть опыт работы и с той и с этой субд поделитесь пожалуйста
web
кто-нибудь пробовал устанавливать mongodb на ubuntu на VPS? у меня почему-то как буд-то установилось, но каталог пустой и команда mongo не работает
Алексей
mongod не mongo