Home > Enterprise >  mongodb - How to get sorted list of mutual likes from a collection?
mongodb - How to get sorted list of mutual likes from a collection?

Time:01-22

I have two collections: users - All the user info 'partnership` - Users can partner/follow each other.

Goal: To get all partnerships sorted by last partnered date.

When do users become partners: Assuming user_1 liked user_2 AND they become partners only when user_2 also liked user_1 (mutual like)

What is partnered date: The date/time when second like (mutual like) happened.

I started a mongo playground but please ignore my query - Mongo Playground

Here is my sample data

db={
  partnership: [
    {
      _id: "xyz_rrr",
      updated: "2022-10-23T12:35:24.772 00:00",
      users: [
        "xyz",
        "rrr"
      ]
    },
    {
      _id: "rrr_eee",
      updated: "2022-12-23T12:35:24.772 00:00",
      users: [
        "rrr",
        "eee"
      ]
    },
    {
      _id: "eee_rrr",
      updated: "2023-01-21T12:35:24.772 00:00",
      users: [
        "eee",
        "rrr"
      ]
    },
    {
      _id: "mmm_rrr",
      updated: "2023-02-19T12:35:24.772 00:00",
      users: [
        "mmm",
        "rrr"
      ]
    },
    {
      _id: "rrr_mmm",
      updated: "2023-02-21T12:35:24.772 00:00",
      users: [
        "rrr",
        "mmm"
      ]
    },
    
  ],
  users: [
    {
      _id: "abc",
      name: "abc",
      group: 1,
      location: {
        type: "Point",
        coordinates: [
          53.23,
          67.12
        ]
      },
      calculatedDist: 112
    },
    {
      _id: "xyz",
      name: "xyyy",
      group: 1,
      location: {
        type: "Point",
        coordinates: [
          54.23,
          67.12
        ]
      },
      calculatedDist: 13
    },
    {
      _id: "123",
      name: "yyy",
      group: 1,
      location: {
        type: "Point",
        coordinates: [
          54.23,
          67.12
        ]
      },
      calculatedDist: 13
    },
    {
      _id: "rrr",
      name: "rrrrrrr",
      group: 1,
      location: {
        type: "Point",
        coordinates: [
          51.23,
          64.12
        ]
      },
      calculatedDist: 14
    },
    {
      _id: "mmm",
      name: "mmmm",
      group: 1,
      location: {
        type: "Point",
        coordinates: [
          51.23,
          64.12
        ]
      },
      calculatedDist: 14
    },
    {
      _id: "eee",
      name: "eeeee",
      group: 1,
      location: {
        type: "Point",
        coordinates: [
          55.23,
          62.12
        ]
      },
      calculatedDist: 143
    }
  ],
  
}

Expected result

    {
partneredUsers:
{ firstUser :
     {
      _id: "mmm",
      name: "mmmm",
    },
},
secondUser :
    {
      _id: "rrr",
      name: "rrrrrrr",
      
    },
},
partneredDate: "2023-02-21T12:35:24.772 00:00",
},

{
partneredUsers:
{ firstUser :
    {
      _id: "rrr",
      name: "rrrrrrr",
      
    },
},
secondUser :
    {
      _id: "eee",
      name: "eeeee",
      
    }
},
partneredDate: "2023-01-23T12:35:24.772 00:00",
}
}

CodePudding user response:

Starting from partnership collection, create a partition key by $sortArray and $concat to identify mutually liked relationship. (They will share the same key). Use the partition key in $setWindowFields to compute count and rank.

  • count: pair of users mutually like each other when count > 1
  • rank: sort by updated: -1; the latest like will have rank: 1

Finally $lookup from users to get the details of users and $sort by partneredDate.

db.partnership.aggregate([
  {
    $set: {
      partitionKey: {
        "$reduce": {
          "input": {
            $sortArray: {
              input: "$users",
              sortBy: 1
            }
          },
          "initialValue": "",
          "in": {
            "$concat": [
              "$$value",
              "$$this"
            ]
          }
        }
      }
    }
  },
  {
    "$setWindowFields": {
      "partitionBy": "$partitionKey",
      "sortBy": {
        "updated": -1
      },
      "output": {
        "count": {
          $sum: 1
        },
        rank: {
          $rank: {}
        }
      }
    }
  },
  {
    $match: {
      count: {
        $gt: 1
      },
      rank: 1
    }
  },
  {
    "$lookup": {
      "from": "users",
      "localField": "users",
      "foreignField": "_id",
      "as": "userLookup"
    }
  },
  {
    "$project": {
      _id: 0,
      partneredUsers: {
        firstUser: {
          $first: "$userLookup"
        },
        secondUser: {
          $last: "$userLookup"
        }
      },
      partneredDate: "$updated"
    }
  },
  {
    $sort: {
      partneredDate: -1
    }
  }
])

Mongo Playground

  • Related