Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

sarmadindhar's avatar

Database Design for Dating Site

I am tasked with designing a dating site in laravel with mysql as the database platform. I have not had a lot of advanced database design experience so I am hoping someone can help me out with this one....

For each user there is a profile (some profile questions might be: nationality, education, age, eye color, etc, etc..). Each of these profile questions could either contain a single value from a radio button (example: are you male or female), multiple values from a list of checkboxes (example: check your hobbies and interests) or text (ex: tell in a short paragraph what you are looking for).

Does anyone have any advice as to the best way to design this. Here are some of the options I am considering:

  1. Create a different table for each profile question: example:

EyeColor

UserId (int or guid) EyeColor (varchar)

Interests

UserId InterestValue

I see this as being a problem because there could be upwards of 50 table joins for each search query and the database would need to be updated if a profile question is added or no longer used.

  1. Put the entire profile in one table: example:

Profile

UserId (int or guid) HairColor (varchar) EyeColor (varchar) LikesMovies (bit) LikesHiking (bit)

I see this a being a problem as this table could contain up to 70 columns and I think serially searching through this one gigantic table could be very slow if the user base gets large. Also as with the above scenario, the DB would need to be changed to accomidate any additions/deletions to the profile questions.

  1. Ideally I would like to design a flexible structure to allow questions of different types (radio, check box, text box) to be added/deleted from an admin interface without having to modify the db structure but I don't know how to design this so it would be efficient for searches.

Could anyone give me some advice on any of the above.

Any advice would be appreciated. Thanks.

0 likes
5 replies
NickeyGod's avatar

Im sorry to say but your idea is not a good habit in setting up a database. Your Design should be looking more like this. Use Pivot Tables.

users table with no Information about the User itself. interests table with all the Information about one interests user_interests Table where there is one foreign key to the users table and the interests table

Same for the habits or like more like information about the user.

thats more like a user property

So lets say.

properties with all the possible propertys user_properties with the id of the user and the property id

etc.

Maybe read about good and bad practices in database design. Could help you.

allw's avatar

Like above I’d do it so you had a users table.

Users could then have many attributes (called properties to minimise issues with naming) and an properties table would contain:

  • ID
  • user_id
  • property_type (could be referencing another table or could be something like an enum that references eye colour hair colour etc)
  • property_payload json column so you can store whatever you need in here.

I’d also be really careful how you did matches and things like that. I’d probably say matches should be a many to many pivot of users and you would think you could do something like:

  • ID
  • User_id_1
  • User_id_2
  • both_matched (bool)
  • time stamps

And that works if user_1 is the only one matching but then what happens when user_2 matches you would get a duplicate in your pivot table. Right now I don’t have an answer, I need to think about it…

PS: sorry for lousy formatting I’m on my phone…

allw's avatar

Right - had time to think this is probably how I would do it.

I would have a users table and make a one to many relationship with Interest. On the interests table I would put

  • id
  • user_id
  • interest_id (foreign of user)
  • type of like maybe an integer/enum that maps to something like superlike, hotty, I wanna do stuff to you etc (yes this is creeping me out writing it, but it's a dating site...)
  • timestamps
  • SoftDelete timestamp.

Then if a user is interested in someone, it can be something like

$user->interests()->updateOrCreate([
'interest_id' => $interestedIn->id,
'interest_type' => Interested::Superlike,
]);

If ($interestedIn->whereHas('interests', fn($query) => $query->where('interest_id', $user->id)))
{
    //Remember that interests are soft-deletable.
    Interest::where('user_id', $user->id)->where('interested_id', $interestedIn->id)->delete();
    Interest::where('user_id', $interestedIn->id)->where('interested_id', $user->id)->delete();

    if($user->id < $interestedIn->id) // "primary" user is the one with the lowest ID to stop duplicates in pivot
    {
        DB::table('matches')->insert([
             'match_id_1' => $user->id,
             'match_id_2' => $InterestedIn->id,
			//timestamps etc
        ]);
    } else {
        DB::table('matches')->insert([
             'match_id_1' => $InterestedIn->id,
             'match_id_2 => $user->id,
			//timestamps etc
        ]);
    }
}

Other things you would need to consider is that when retrieving the matches, you would need to retrieve the match based on the one with the lowest ID in the first column, so your retrieval would need to be something like:

$matchesOfUser = Match::where('match_id_1', $user_id)->orWhere('match_id_2', $user_id)->get();

Other things you might want to look at is if users ever unmatched you would have to deal with the soft delete and they would either have to have the soft delete removed on interests if they rematched, or more likely when you retrieved a list of possible interests you would need to do something like the following (as well as checking that they are even interested in each other in like a gender/sexuality way anyway):

$possibleInterests = User::whereDoesntHave('interests' fn($query) => $query->where('interest_id', $user_id)->withTrashed())->get();

PPS: Check my code there may be errors I've not tested it...

Please or to participate in this conversation.