Football Social Media Schema

Hello everyone, im developing a social media app for Footballers, im new to programing and mongoDB, so i would like to hear different opinions on my schema. Thanks!

const { ObjectId } = require("mongodb");
const mongoose = require("mongoose");

const userSchema = new mongoose.Schema(
  {
    first_name: {
      type: String,
      required: [true, "first name is required"],
      trim: true,
      //za search se koristi
      text: true,
    },
    last_name: {
      type: String,
      required: [true, "last name is required"],
      trim: true,
      text: true,
    },
    email: {
      type: String,
      required: [true, "Email is required"],
      trim: true,
      unique: true,
      match: [/^\S+@\S+\.\S+$/, "Please enter a valid email address"],
    },
    password: {
      type: String,
      required: [true, "password is required"],
    },
    //referenca na bazu klubova?
    current_club: {
        club: {
          type: ObjectId,
          ref: "Club",
          required: [true, "Club is required"],
        },
        start_date: {
          year: {
            type: Number,
            required: [true, "Start year is required"],
          },
          season: {
            type: String,
            enum: ["Leto", "Zima"],
            required: [true, "Start season is required"],
          },
        },
      },
    primary_position: {
      type: String,
      enum: [
        "Golman",
        "Štoper",
        "Levi Bek",
        "Levi Krilni Bek",
        "Desni Krilni Bek",
        "Desni Bek",
        "Zadnji Vezni",
        "Centralni Vezni",
        "Prednji Vezni",
        "Levo Krilo",
        "Desno Krilo",
        "Špic",
      ],
      required: true,
    },
    secundary_position: {
      type: String,
      enum: [
        "Golman",
        "Štoper",
        "Levi Bek",
        "Levi Krilni Bek",
        "Desni Krilni Bek",
        "Desni Bek",
        "Zadnji Vezni",
        "Centralni Vezni",
        "Prednji Vezni",
        "Levo Krilo",
        "Desno Krilo",
        "Špic",
      ],
      validate: [
        (arrayLimit) => arrayLimit.length <= 2,
        "Positions array must contain no more than 2 elements",
      ],
    },
    picture: {
      type: String,
      //ovde nemoj da zaboravis da ubacis link ka slici
      default: "defaultpicture",
      trim: true,
    },
    cover: {
      type: String,
      trim: true,
    },
    gender: {
      //zasto string zasto ne enum?
      type: String,
      enum: ["Muški", "Ženski", "Ostalo"],
      required: [true, "gender is required"],
      trim: true,
    },
    birthday: {
      year: {
        type: Number,
        required: true,
      },
      month: {
        type: Number,
        required: true,
      },
      day: {
        type: Number,
        required: true,
      },
    },
    verified: {
      type: Boolean,
      default: false,
    },
    open_for_transfer: {
      type: {
        play_for_free: {
          type: Boolean,
          required: [true, "Play for free is required"],
        },
        salary: {
          type: {
            minimum: {
              type: Number,
            },
            contract: {
              type: String,
            },
          },
          required: [true, "Salary is required"],
        },
      },
      required: [true, "Open for transfer is required"],
    },
    //obrati paznju ovde verovatno ti ne trebaju sva 3 vec samo connections posebno za pocetak
    connections: {
      type: Array,
      default: [],
    },
    following: {
      type: Array,
      default: [],
    },
    followers: {
      type: Array,
      default: [],
    },
    requests: {
      type: Array,
      default: [],
    },
    searchHistory: [
      {
        user: {
          type: ObjectId,
          ref: "User",
        },
      },
    ],
    details: {
      bio: {
        type: String,
      },
      phone: {
        type: {
          number: {
            type: String,
            trim: true,
          },
          show_number: {
            type: Boolean,
            default: false,
          },
        },
      },
      strongerFoot: {
        type: String,
        enum: ["Right", "Undefined", "Left"],
      },
      player_qualities: {
        type: String,
        enum: [
          "Šut",
          "Dribling",
          "Komunikacija",
          "Liderstvo",
          "Vazdušni duel",
          "Brzina",
          "Snaga",
          "Kondicija",
          "Igra glavom",
          "Defanziva",
          "Prekid",
          "Tehnika",
          "Penali",
          "Kreator",
          "Završnica",
          "Igra leđima",
          "Duga lopta",
          "Dodavanje",
          "Agresivnost",
          "Slabija noga",
          "Centaršut",
        ],
      },
      goalkeeper_qualities: {
        type: String,
        enum: [
          "Odbrana penala",
          "Refleksi",
          "Istrčavanje",
          "Komunikacija",
          "Liderstvo",
          "Fizička sprema",
          "Pozicioniranje",
          "Timski igrač",
          "Distribucija lopte",
          "Fokus",
          "Slabija noga",
          "Rad nogu",
          "Brzina",
          "Praćenje igre",
          "Igra nogom",
        ],
      },
      experience: {
        type: [
          {
            club: {
              type: ObjectId,
              ref: "Club",
              required: [true, "Club is required"],
            },
            start_date: {
              year: {
                type: Number,
                required: [true, "Start year is required"],
              },
              season: {
                type: String,
                enum: ["Leto", "Zima"],
                required: [true, "Start season is required"],
              },
            },
            end_date: {
              year: {
                type: Number,
                required: [true, "End year is required"],
              },
              season: {
                type: String,
                enum: ["Leto", "Zima"],
                required: [true, "End season is required"],
              },
            },
          },
        ],
        default: [],
      },
      height: {
        type: Number,
      },
      weight: {
        type: Number,
      },
      current_location: {
        city: {
          type: ObjectId,
          ref: "City",
        },
      },
      nationality: {
        type: ObjectId,
        ref: "Nationality",
      },
      contract_with_club: {
        type: Boolean,
        default: false,
      },
      videos: {
        type: Array,
        default: [],
      },
    },

    next_game: {
        location: {
          city: {
            type: {
              name: {
                type: ObjectId,
                ref: "City",
                required: [true, "City name is required"],
              },
            },
            required: [true, "City is required"],
          },
          country: {
            type: {
              name: {
                type: ObjectId,
                ref: "Nationality",
                required: [true, "Country name is required"],
              },
            },
            required: [true, "Country is required"],
          },
        },
        club: {
          type: {
            name: {
              type: ObjectId,
              ref: "Club",
              required: [true, "Club name is required"],
            },
          },
          required: [true, "Club is required"],
        },
        date: {
          type: Date,
          required: [true, "Date is required"],
        },
        time: {
          type: String,
          required: [true, "Time is required"],
        },
      },
      
    savedPosts: [
      {
        post: {
          type: ObjectId,
          ref: "Post",
        },
        savedAt: {
          type: Date,
          default: new Date(),
        },
      },
    ],
  },
  {
    timestamps: true,
  }
);

module.exports = mongoose.model("User", userSchema);

Hey @Filip_Trivan,

Welcome to the MongoDB Community Forums! :leaves:

Going over your schema, it seems to be well thought out and comprehensive. You have included validation for most fields to ensure data integrity and correctness which seems great too. As a next step, I would recommend you start figuring out the kind of queries that you will be using in your app the most. This will help you decide if any changes to your schema are needed or not since schema design is very much dependent on the query you would be using. This would also help you figure out which fields you need to index and the indexing strategy that you can use, as this will improve your query performance.

Feel free to reach out for anything else as well.

Regards,
Satyam

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.