Алексей
не буду душнить гарантиями доставки и идемпотентностью, задам простой вопрос -а как именно Маша понимает что ее сообщение отправленное Пете доставлено/прочитано? в твоем конкретном мессенджере.
Nalik
Я предполагаю, что будет отправляться сокет с идентификатором последнего прочитанного сообщения. Исходя из этого предполагается, что все сообщения выше так же были прочитаны. Ну это такая упрощенная схема )
Nalik
Конечно может быть ситуация когдай я просвайпил чат и не прочитал часть сообщений и т.д. Но я думаю можно упростить до такой схемы.
Алексей
не знаю что такое "отправляться сокет", вот пример -Маша написала "привет" в твоем клиентском ПО и нажала ентер, далее предположу через какой то транспорт например вебсокеты сообщение отправлено на сервер. Что дальше? как клиентское ПО Маши узнает что Петя получил/прочитал сообщение?
Nalik
Пока точно не знаю, но предполагаю следующее:
Когда Маша написала "привет" и нажала "ентер", то по вебсокету на сервер отправился пакет с её сообщением.
Вебсокет отправляет всем участникам конкретного чата это сообщение. Клиенты участников чата в ответ должны отправить ID сообщения если они его прочитали. Этот ID будет заноситься в поле последнего прочитанного сообщения для конкретного клиента.
Nalik
У тебя есть предложения лучше?)
Nalik
Но эта логика уже будет возложена на клиент. Ты вроде негодовал, что клиент не выполняет никакой логики. Вот она 😄
Алексей
У тебя есть предложения лучше?)
я подвожу тебя к мысли, прямым текстом ты ее не всопринял попробую обходными путями. я пока спросил про переписку 1-1, но давай реально возьмем чат, что в твоем понимании означает прочитанное сообщение в чате на 1000 тел? все прочли, 1 прочел и это не автор сообщения, 1 прочел и это автор сообщения?
Nalik
Ничего не понял из твоего посыла и если честно я чувствую какую-то предвзятость, я тут не для того, чтобы продвигать свои убеждения. А чтобы попросить совета, может быть вместе обсудить если другим будет это интересно :)
Алексей
я просто спросил как ты планируешь это делать -не вижу ничего страшного в вопросе. То есть например для чата в 1000 тел порождает ли одно сообщение тысячу сообщений на сервер о доставке и потом тысячу о прочтении?
Nalik
Я вообще не думал еще об этом, но предполагаю, что Маше действительно нужно как-то узнать, что её сообщение прочитали все. По типу синей/серой галочки.
Алексей
Nalik
Nalik
По крайней мере так сейчас это сделано в ТГ например
Nalik
Но есть большая разница между 1000 участников в чате и 1000 участников онлайн в чате)
Nalik
Хотя думаю стоит проектировать с тем учетом, что вся 1000 будет онлайн)
Nalik
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 - пустая?
Just
Vladislav
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
Just
тебе же count возвращает 0, ты именно в notification нужно это получать?
Just
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?
Nick
В данном примере сортировка замедляет процесс в 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',
},
}
100мс не время))
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к
Nick
В случае сортировки по 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
}
вот бы еще indexesUsed было раскрыто
Nick
В случае сортировки по 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
}
ну и нагенерьте уже лямов 10 а то милисекунды не показательны. А чтоб наверняка нормально тестить - данных хотя бы раза в два больше чем оперативы по чистому объему
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
}
Nick
Для 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
Nalik
Я правильно понимаю?
Nalik
Я точно знаю, что msg_id является индексом.
Но видимо pipeline игнорирует отдельные индексы при сортировке. Других объяснений у меня нет.
Nick
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, без неё был как слепой))
Nalik
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
Алексей
так 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