Is my database design acceptable?

Hello All,

I have a very simple use case, in which I have some Places and some Users who can write some Reviews.

I have implemented the code using java, springboot and mongodb. Here are my main classes:

      @Document(collection = "user")
public class User {

    @Id
    private String id;
    @Indexed(unique = true, direction = IndexDirection.DESCENDING, dropDups = true)
    private String email;
    private String password;
    private String fullname;
    
   private byte[] image;
   private String imagename;
   
    private boolean enabled;
    @DBRef
    private Set<Role> roles;
	private String firstname;
	private String lastname;
	
	@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
	private Date lastPasswordResetDate;
}

Here is the place class:

@Document(collection = "place")
public class Place {

	public Place() {}
	
	private String place_name;
	
	@Id 
	private String id;
	private Double longitude;
	
	private Double latitude;
	
	
	private String municipalitySubdivision;
	private String  municipality;
	private String countrySecondarySubdivision;
	private String countryTertiarySubdivision;
	private String countrySubdivision;
	private String country;
	
	private String category;
	
}

and here is the review class:

@Document(collection = "review")
public class Review {

	public Review() {
	}

	@Id
	private String id;

	@TextIndexed(weight=7)
	private String first_point;

	@TextIndexed(weight=6)
	private String second_point;

	@TextIndexed(weight=5)
	private String third_point;

	@TextIndexed(weight=4)
	private String fourth_point;

	@TextIndexed(weight=3)
	private String fifth_point;

	@TextIndexed(weight=2)
	private String sixth_point;

	@TextIndexed(weight=1)
	private String seventh_point;

	private Place place;
	
	@DBRef
	private User user;

	
	private String date;
	
	@TextScore
	private Float textScore;
}

Here is my Role class:

@Document(collection = "role")
public class Role {

    @Id
    private String id;
    
    @Indexed(unique = true, direction = IndexDirection.DESCENDING, dropDups = true)
    private String role;
}

In this project, the review is not a simple text, but is composed of multiple texts which have different weights.
the user can search for a keyword and the reviews which are more relevant are sorted according to the their scores.

As I am totally new to mongodb, I have read the documentations about DBRef, Textscore, etc. and have designed it as mentioned. I am wondering if I have used them correctly and my implementation is reasonable or if I have to make big changes to it.
I should also mention that the code works without any problem, but I am wondering if it will also work when it is live as a web page and many users want to use it at the same time.

Your help would be appreciated.

Hi @dokhtar_ma,

Your approach is pretty much decent and the models look good. A few points that I would mention, which will make your application better -

  1. Don’t store a big byte array for image in User collection. MongoDB can manage 16MB document size, if the image takes up more it will cause an issue. Even big documents (few MBs) have performance issues when scale of data is large. So you can either try to store the images in some other way - MongoDB GridFS or maybe a cloud store (S3 / Azure ADLS / etc) and you can store the reference (id of doc in mongo / uri of s3 image, etc) in this document.
  2. You modelling is good, where you have 4 collections, but do check the way java is handling the relationships of each of them. I have not used java mongodb package, but it seems you are “embedding” a “Place” and “User” object in your Review document. Similarly it seems you are “embedding” a “Role” object in your “User” collection.
  3. Keep in mind MongoDB does not support primary/foreign key relationships natively, you can check if your package is creating the DBRef and managing it for you. The perfect way I would do, is to refer the “id” field of each document into the others. Say User has an id 1 (ObjectID type be default in mongodb), you can use the same ID to connect your Review to your user like this -
// User collection
{
    "_id": ObjectId("123456"), // ID field of user collection.
    "name": "Hello man"
}

// Review Collection
{
    "_id": ObjectId("2345678"), // ID field of review collection.
    "reviewText": "Hello this is my review.",
    "placeId": ObjectId("123123"), // ID of place document.
    "userID": ObjectID("123456") // ID of User document.
}

Then when you want to fetch the reviews of particular user, you can simply search and do a $lookup to perform join.

Do tell me if your package made the links automatically or did it embed the document.
Cheers…!