skip to Main Content

I am trying to add a field to an aggregation called friendshipStatus and it determines whether the user is friend of the requester or no.

i have this whole query

[
        {
          $match: (query) ? query : {}
        },
        {
          $addFields: {
            friendshipStatus: {
              $cond: {
                if: {
                  $in: [vierweruserName || '', "$friends"]
                },
                then: "friend",
                else: {
                  $cond: {
                    if: {
                      $in: [vierweruserName || '', "$friendRequests"]
                    },
                    then: "requested",
                    else: "none"
                  }
                }
              }
            }
          }
        },
        {
          $project: {
            _id: 0,
            firstName: 1,
            lastName: 1,
            userDescription: 1,
            userName: 1,
            imgURL: 1,
            coverURL: 1,
            friendshipStatus: 1 // Include the new field in the output
          }
        },
        {
          $limit: 50
        }
      ]

and i want to modify this addField stage to check if the user name is in the requester friendRequests array or not (that would happen if he sent the requester a friend request)

{
          $addFields: {
            friendshipStatus: {
              $cond: {
                if: {
                  $in: [vierweruserName || '', "$friends"]
                },
                then: "friend",
                else: {
                  $cond: {
                    if: {
                      $in: [vierweruserName || '', "$friendRequests"]
                    },
                    then: "requested",
                    else: "none"
                  }
                }
              }
            }
          }
        }

i am expexting the code should also add the friendshipStatus as ‘requested’ if the User in the array of friendRequests in the viewerUserName document. and I wonder if I can do a subquery in the adFields stage to get the viewerUserName document and then search un it or there is another way.

sample document:

{
"_id": "65034fed2153ebff85f30554",
"userName": "minamelad232",
"firstName": "mina",
"lastName": "melad",
"password": "$2b$10$Sr/cWOWwtAC9AQpHHLjFfuD3TKLIFvjd89QwgIJdz6cMB.rvWFeJy",
"userDescription": "No description",
"friends": ["minamelad123"],
"friendRequests": ["markosami123"],
"imgURL": "http://res.cloudinary.com/dik65evmf/image/upload/v1694726404/widgetUpl...",
"coverURL": "http://res.cloudinary.com/dik65evmf/image/upload/v1694715952/widgetUpl...",
"influence": 0,
"feedOffset": 0,
"commentsOffset": 0,
"friendRequestsOffset": 0,
"__v": 42

}

sample output

{
            "userName": "minamelad232",
            "firstName": "mina",
            "lastName": "melad",
            "userDescription": "No description",
            "imgURL": "http://res.cloudinary.com/dik65evmf/image/upload/v1694726404/widgetUpload/qbegll5tmhumijplqkek.jpg",
            "coverURL": "http://res.cloudinary.com/dik65evmf/image/upload/v1694715952/widgetUpload/f61ztmyvln0c5p0ei1db.png",
            "friendshipStatus": "none"
        }

2

Answers


  1. In your current query, you are checking if the viewerUserName exists in the $friends array or the $friendRequests array to determine the friendshipStatus. If you want to check if the viewerUserName exists in the friendRequests array of the viewerUserName document itself, you can modify the query as follows:

    [
      {
        $match: (query) ? query : {}
      },
      {
        $addFields: {
          friendshipStatus: {
            $cond: {
              if: {
                $in: [vierweruserName || '', "$friends"]
              },
              then: "friend",
              else: {
                $cond: {
                  if: {
                    $in: [vierweruserName || '', "$friendRequests"]
                  },
                  then: "requested",
                  else: {
                    $cond: {
                      if: {
                        $in: [vierweruserName || '', "$$ROOT.friendRequests"] // Check in viewerUserName's own friendRequests array
                      },
                      then: "requested",
                      else: "none"
                    }
                  }
                }
              }
            }
          }
        }
      },
      {
        $project: {
          _id: 0,
          firstName: 1,
          lastName: 1,
          userDescription: 1,
          userName: 1,
          imgURL: 1,
          coverURL: 1,
          friendshipStatus: 1 // Include the new field in the output
        }
      },
      {
        $limit: 50
      }
    ]
    

    In the modified query, I added an additional $cond expression inside the else block of the second $cond expression. This checks if viewerUserName exists in the friendRequests array of the viewerUserName document itself ($$ROOT.friendRequests). If it does, then the friendshipStatus will be set as "requested". Otherwise, it will be set as "none".

    Login or Signup to reply.
  2. Given that these are the sample (minimal) documents:

    [
      {
        "_id": ObjectId("5a934e000102030405000000"),
        "userName": "Alex",
        "friends": [],
        "friendRequests": [
          //"may"
          
        ]
      },
      {
        "_id": ObjectId("5a934e000102030405000001"),
        "userName": "May",
        "friends": [],
        "friendRequests": [
          "Alex"
        ]
      }
    ]
    

    As mentioned you need to search the viewer’s friendRequests, this requires to self join the collection with userName: vierwerUsename

    1. $lookup – Search the document in the same collection with userName: vierwerUsename and return the document in the array as viewer.

    2. $addField – Would recommend using $switch operator for handling multiple conditions instead of nested $cond. For the third condition, you should match the condition with the userName in the document does existed in the friendRequest of the viewer.

    {
        $lookup: {
          from: "collection", // replace with your collection name
          pipeline: [
            {
              $match: {
                $expr: {
                  $eq: [
                    vieweruserName || '',
                    "$userName"
                  ]
                }
              }
            }
          ],
          as: "viewer"
        }
      },
      {
        $addFields: {
          friendshipStatus: {
            $switch: {
              branches: [
                {
                  case: {
                    $in: [
                      vieweruserName || '',
                      "$friends"
                    ]
                  },
                  then: "friend"
                },
                {
                  case: {
                    $in: [
                      vieweruserName || '',
                      "$friendRequests"
                    ]
                  },
                  then: "requested"
                },
                {
                  case: {
                    $in: [
                      "$userName",
                      {
                        $getField: {
                          field: "friendRequests",
                          input: {
                            $arrayElemAt: [
                              "$viewer",
                              0
                            ]
                          }
                        }
                      }
                    ]
                  },
                  then: "requested"
                }
              ],
              default: "none"
            }
          }
        }
      }
    

    Demo @ Mongo Playground

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search