Цель -
У меня есть приложение чата, в котором у каждого пользователя есть список друзей, который хранится в коллекциях пользователей, и для каждого разговора с другом детали хранятся в коллекции чатов. В настоящее время я извлекаю список друзей из одного запроса (из коллекции «Пользователи») и сведения о чатах / chatId из другого (из коллекции «Чаты»), теперь я хочу получить список друзей по списку друзей с помощью одного запроса.
Обзор схемы пользователей и коллекции чатов -
//Users collection
Users = [
//invidual users
{
username: "john_doe",
manageFriends: {
//friends-list
friends: [
// individual friend
{
username: "jane_doe"
},
...more_friends
]
},
...other_fields,
},
{
username: "jane_doe",
manageFriends: {
friends: [{ username: "john_doe" }, ...more_friends]
},
...other_fields,
},
...
]
//Chatrooms collection
Chatrooms = [
//per conversation unique chatId along with participants details and messages
{
chatId: "abc_def",
participants: ["john_doe", "jane_doe"], //username of two friends involved in conversation
...other_fields,
}, {
chatId: "abc_def",
participants: ["john_doe", "someone_else"],
...other_fields,
}
]
// query to fetch friends list(ignore pendingRequests stuffs)
let users = await User.aggregate([
{
$match: { username }
},
{
$project: {
"manageFriends": 1,
"username":1,
_id: 0
}
},
{
$unwind: {
path: "$manageFriends.friends",
preserveNullAndEmptyArrays: true
}
},
{
$lookup: {
"from": "chatrooms",
"pipeline" : [
{ $match: { participants: { $all : [username, "$manageFriends.friends.username"] }}},
{ $project : {chatId : 1} }
],
"as": "chatDetails"
}
},
{
$lookup:{
"from":"users",
"localField":"manageFriends.friends.username",
"foreignField":"username",
"as":"friendsRef"
}
},
{
$unwind: {
path: "$manageFriends.pendingFriendList",
preserveNullAndEmptyArrays: true
}
},
{
$project: {
"friends": {
$cond : ["$manageFriends.friends", {
"username":"$manageFriends.friends.username",
"name":"$manageFriends.friends.name",
"chatId": "$chatDetails.chatId",
"isOnline": {$eq:[{$arrayElemAt: ["$friendsRef.status", 0 ]}, 'online']},
"lastSeen": {$arrayElemAt: ["$friendsRef.lastSeen", 0 ]},
"friendStatus":{
"isFriend":{$toBool:true},
"pendingStatus":null
}
}, '']
},
"username":1,
"pendingFriendList": {
$cond : ["$manageFriends.pendingFriendList", {
"username":"$manageFriends.pendingFriendList.username",
"name":"$manageFriends.pendingFriendList.name",
"friendStatus":{
"isFriend":{$toBool:false},
"pendingStatus": { "sentBy": "$manageFriends.pendingFriendList.sentBy"}
}
}, '']
},
}
},
{
$group: {
_id:"$username",
"friends":{$addToSet: "$friends"},
"pendingFriendList":{$addToSet:"$pendingFriendList"}
}
},
{
$project: {
_id:0,
"users":{$concatArrays:["$friends", "$pendingFriendList"]}
}
}
]);
Довольно долго, но, наконец, вопрос - как передать имя пользователя друга в запросе ниже и получить только совпадающий chatId, потому что передача $ manageFriends.friends.username или $ username не возвращать результаты, но возвращать строки с жестким кодом?
{
$lookup: {
"from": "chatrooms",
"pipeline" : [
{ $match: { participants: { $all : [username, "$manageFriends.friends.username"] }}},
{ $project : {chatId : 1} }
],
"as": "chatDetails"
}
}
С уважением и счастливым кодированием, Принц