В настоящее время у меня есть запрос, благодаря сообществу здесь, на StackOverflow.
Пользователи могут вести беседы один на один, а также групповые чаты с участием до 25 человек. Идея моей базы данных состоит в том, чтобы сохранить документ разговоров и документ сообщений, которые связаны друг с другом с помощью _id из разговора. Это документ моей беседы:
{
"_id" : ObjectId("5e35f2c840713a43aeeeb3d9"),
"n" : "Example Group Chat",
"members" : [
{
"uID" : "1",
"j" : 1580580922,
"i" : "1",
"r" : "admin",
"a" : 1
},
{
"uID" : "4",
"j" : 1580580922,
"l" : 1581863346,
"i" : "1",
"r" : "member",
"a" : 0
},
{
"uID" : "5",
"j" : 1580581922,
"i" : "1",
"r" : "member",
"a" : 1
},
{
"uID" : "9",
"j" : 1580593922,
"i" : "1",
"r" : "member",
"a" : 1
},
{
"uID" : "3",
"j" : 1580594920,
"i" : "1",
"r" : "member",
"a" : 1
},
{
"uID" : "8",
"j" : 1580594999,
"i" : "1",
"r" : "member",
"a" : 1
}
]
}
{
"_id" : ObjectId("5e39d5d740713a43aeef5b26"),
"members" : [
{
"uID" : "1",
"j" : 1580580922,
"i" : "1",
"r" : "member",
"a" : 1
},
{
"uID" : "2",
"j" : 1580580922,
"i" : "1",
"r" : "member",
"a" : 1
}
]
}
Вы можете видеть групповой чат (первый) и чат один на один (второй). Групповые чаты могут иметь имена (n), индивидуальные чаты - нет. Каждый диалог имеет массив участников, в котором хранятся идентификатор пользователя (uID), дата присоединения (j), оставленная дата (l), поле приглашенного userID (i), поле роли (r) и активное поле ( а). Мне, вероятно, не понадобится поле "active", так как у меня есть отметка времени соединения / оставления, но все же. Я, вероятно, удалю его позже, так что это поле, вероятно, не будет включено.
Далее, у меня есть messages
документ следующим образом:
{
"_id" : ObjectId("5e4917bca59ce44ef2770086"),
"c_ID" : ObjectId("5e35f2c840713a43aeeeb3d9"),
"msg" : "Whats good?",
"fromID" : "1",
"__v" : 0,
"t" : 1582369525,
"d" : {
"4" : 1582369525
},
"r" : {
"4" : 1582369525
}
}
Это содержит само сообщение (msg), пользователь, который его отправил (fromID), отметка времени в UNIX Epoch (t) и подколлекции доставок (d) и reads (r) и, конечно, беседа ObjectID (c_ID).
db.conversations.aggregate([
{
$match: {
"members.uID": "4"
}
},
{
$addFields: {
user: {
$arrayElemAt: [
{
$filter: {
input: "$members",
as: "member",
cond: {
$eq: [
"$$member.uID",
"4"
]
}
}
},
0
]
}
}
},
{
$lookup: {
from: "messages",
let: {
user: "$user",
conversatoinId: "$_id"
},
pipeline: [
{
$match: {
$expr: {
$and: [
{
$eq: [
"$c_ID",
"$$conversatoinId"
]
},
{
$cond: {
if: {
$lt: [
{
$ifNull: [
"$$user.l",
0
]
},
"$$user.j"
]
},
then: true,
else: {
$lt: [
"$t",
"$$user.l"
]
}
}
},
{
$gt: [
"$t",
"$$user.j"
]
}
]
}
},
},
{
$sort: {
"t": -1
},
}
],
as: "messages"
}
},
{
$project: {
lastMessage: {
$arrayElemAt: [
"$messages",
0
]
},
n: 1,
members: 1
}
},
{
$sort: {
"lastMessage.t": 1
}
},
{
$project: {
members: {
$filter: {
input: "$members",
as: "member",
cond: {
$and: [
{
$ne: [
"$$member.uID",
"4"
]
},
{
$or: [
{
$eq: [
"$$member.l",
undefined
]
},
{
$lt: [
"$$member.l",
"$$member.j"
]
}
]
}
]
}
}
},
memberCount: {
$size: {
$filter: {
input: "$members",
as: "member",
cond: {
$and: [
{
$ne: [
"$$member.uID",
"4"
]
},
{
$or: [
{
$eq: [
"$$member.l",
undefined
]
},
{
$lt: [
"$$member.l",
"$$member.j"
]
}
]
}
]
}
}
}
},
n: 1,
lastMessage: 1
}
},
{
$match: {
lastMessage: {
$exists: true
}
}
},
{
$limit: 10
}
])
Теперь проблема:
Представьте, что существует групповой чат с 20 участниками. Название чата - «Веселые пятницы». userID 4 присоединяется к этому групповому чату (я установил для поля j
(join) значение 1582475543
(отметка времени), участвует в течение двух недель, а затем уходит (я установил для поля l
(left) значение 1583685143
(отметка времени)). Это все будет работать нормально. Однако, как я могу снова добавить userID 4 в тот же групповой чат через 1 неделю (отметка времени 1584289943
) и убедиться, что userID 4 может видеть lastMessage, ЕСЛИ это либо между первым подключением / оставил ИЛИ, если он будет опубликован после того, как он снова присоединился? **
Я хотел бы иметь возможность добавлять одного и того же пользователя более одного раза в массив members, но с разными полями j
(и l
) и затем запросите последнее сообщение между одним из них, что позволило бы выполнить то, что я хочу сделать, как описано выше.
Таким образом, я хотел бы получить документ conversations
следующим образом:
{
"_id" : ObjectId("5e35f2c840713a43aeeeb3d9"),
"n" : "Example Group Chat",
"members" : [
{
"uID" : "1",
"j" : 1580580922,
"i" : "1",
"r" : "admin",
"a" : 1
},
{
"uID" : "4",
"j" : 1580580922,
"l" : 1581863346,
"i" : "1",
"r" : "member",
"a" : 0
},
{
"uID" : "5",
"j" : 1580581922,
"i" : "1",
"r" : "member",
"a" : 1
},
{
"uID" : "9",
"j" : 1580593922,
"i" : "1",
"r" : "member",
"a" : 1
},
{
"uID" : "3",
"j" : 1580594920,
"i" : "1",
"r" : "member",
"a" : 1
},
{
"uID" : "8",
"j" : 1580594999,
"i" : "1",
"r" : "member",
"a" : 1
},
{
"uID" : "4",
"j" : 1581982392,
"i" : "1",
"r" : "member",
"a" : 0
},
]
}
{
"_id" : ObjectId("5e39d5d740713a43aeef5b26"),
"members" : [
{
"uID" : "1",
"j" : 1580580922,
"i" : "1",
"r" : "member",
"a" : 1
},
{
"uID" : "2",
"j" : 1580580922,
"i" : "1",
"r" : "member",
"a" : 1
}
]
}
Итак, userID 4 присоединился, принял участие в чате, ушел и позже присоединился снова. Я хочу, чтобы он мог видеть чат в обзоре всех своих бесед.
Любые идеи о том, как я могу достичь ve this?
РЕДАКТИРОВАТЬ: Основываясь на предложении Джо, я хотел бы go с чем-то вроде ниже. Есть мнения? Мне интересно, как бы я использовал приведенную ниже структуру, чтобы показать только последнее сообщение до последней отметки времени выхода (1581963346
), а не любое сообщение, опубликованное после них. Или, если есть несколько дат присоединения / выхода, я хотел бы показать последнее соответствующее сообщение. Позже я использовал эти даты, чтобы показать сообщения, которые пользователь может видеть. Так что только те, кто присутствовал в групповом чате.
{
"_id" : ObjectId("5e35f2c840713a43aeeeb3d9"),
"n" : "Example Group Chat",
"members" : [
{
"uID" : "1",
"j" : 1580580922,
"i" : "1",
"r" : "admin",
"a" : 1
},
{
"uID" : "4",
"events" : [
{ type: "join", date: 1581863346 },
{ type: "leave", date: 1581963346 }
],
"i" : "1",
"r" : "member",
"a" : 1
},
{
"uID" : "5",
"j" : 1580581922,
"i" : "1",
"r" : "member",
"a" : 1
},
{
"uID" : "9",
"j" : 1580593922,
"i" : "1",
"r" : "member",
"a" : 1
},
{
"uID" : "3",
"j" : 1580594920,
"i" : "1",
"r" : "member",
"a" : 1
}
]
}
РЕДАКТИРОВАТЬ 2: Мой основной источник беспокойства - это запрос между датой вступления в группу и датой ухода из группы. группа. Я приведу пример ниже.
Диалог X
- 10: 00 AM: Человек А присоединяется к беседе и пока не видит сообщений
- 10: 05 AM: человек B отправляет сообщение
- 10: 07 AM: человек C отправляет сообщение
- 10: 10 AM: человек A отправляет сообщение
- 10: 12 AM: человек B отправляет сообщение
- 10: 15 AM: человек A покидает разговор
- 10: 20 AM: человек C отправляет сообщение
На данный момент я хочу, чтобы человек А мог видеть беседу Х все еще в своем обзоре с сообщением от человека Б (10:12 утра) в качестве последнего сообщения. Когда я go участвую в разговоре, я хочу, чтобы все сообщения с 10:00 до 10:15 показывались человеку А. Поэтому не должно отображаться только последнее сообщение от пользователя C (10:20). .
- 10: 30 AM: человек B отправляет сообщение
- 10: 32 AM: человек A снова присоединяется к беседе
- 10: 35 AM : Person C отправляет сообщение
- 10: 37 AM: Person A отправляет сообщение
- 10: 38 AM: Человек C отправляет сообщение
На этом этапе я хочу, чтобы человек А увидел последнее сообщение от человека C в своем обзоре. В самой беседе я хочу показать сообщения с 10:00 до 10:15, а также с 10:32 до 10:38.
Мне просто интересно, как я могу структурировать свои данные И как запросить обзор (на основе моего запроса выше), чтобы добиться этого. Позже я позабочусь о беседах и покажу все соответствующие сообщения для определенного пользователя.