2

Warning: My query would be more theoretical (sorry programmers, please bear with me). I am trying to get some idea on how to define the database structure for use in Firebase.

I am exploring the use of Firebase as a backend for a Review app (in Android) I am trying to build.

The app provides product details and review for products of different kinds. So here is an example use case.

  1. The products displayed in the app are of same type (say smartphones). In this use case, defining the database structure is easier. For every phone, I simply need to save the phone specs to Firebase and retrieve them into my app.
Root
 |
 +--Smartphone
     |
     +--Manufacturer Name
     +--Screen Size
     +--Screen Density
     +--Processor
     +--RAM,...
  1. The products displayed in the app are of different type (say smartphones, Car, Book,...). In this use case, defining the database structure becomes complex. I can simply define the data structure like
Root
 |
 +--Product
     |
     +--Manufacturer Name
     +--Screen Size
     +--Screen Density
     +--Processor
     +--RAM
     +--Fuel type (Petrol/Diesel/Electric)
     +--Vehicle Type (Sedan/Hatchback)
     +--Vehicle Price,...

However, the problem with above data structure is, when I am trying to make a product review for a smartphone, the data related to Car will remain blank. Same will be the case for a product review of a Car.

This problem can be solved by using Flattening the data structure. This is where I am confused.

Root
 |
 +--Smartphone
 |   |
 |   +--Manufacturer Name
 |   +--Screen Size
 |   +--Screen Density
 |   +--Processor
 |   +--RAM
 |
 +--Car
     |
     +--Fuel type (Petrol/Diesel/Electric)
     +--Vehicle Type (Sedan/Hatchback)
     +--Vehicle Price,...

However, all product reviews will be displayed in a single activity/fragment. Hence, there will not be different activities/fragments for every product type. Could someone provide me a clear picture of using flattened data structures in my use case?

Regards

user3314337
  • 341
  • 3
  • 13

2 Answers2

6

You can structure your database like this:

products: {
    smartphones: {
        smartphone1: {
            name: "Best Phone",
            ram: "6 GB",
            screen: "5.5 inch"
            reviews: {
                review1: true,
                review2: true
            }
        }
    },
    cars: {
        car1: {
            name: "Lightning"
            reviews: {
                review3: true,
                review4: true,
                review5: true
            }
        }
    }
},
product-review: {
    review1: {
        submittedBy: "Conqueror",
        message: "Best phone at this price",
        timestamp: 1472405901
    },
    review2: {
        submittedBy: "Magic Blaster",
        message: "Pros: RAM, Cons: Everything else.",
        timestamp: 1472405901
    },
    review3: {
       submittedBy: "Boss",
       message: "Excellent Car",
       timestamp: 1472405901
    },
    ...
}

Every product(smartphone1, car1 etc..) contains a reviews node, so you can easily load the linked reviews of a particular product.

You can generate timestamps for the nodes you want. You can add it for smartphone1, car1 etc.. but it is not required. But reviews by user require timestamp because you should display when the user has posted a review.

Have a look at this answer to know how to generate timestamps and to convert timestamp back into displayable date:

DateFormat sdf = new SimpleDateFormat("MM-dd-yyyy hh:mm:ss a");
Date someDate = (new Date(timestamp));
return sdf.format(someDate);

You can store user reviews in their individual nodes.

users: {
    abcdefghijklm: { // User UID
        name: "Conqueror",
        reviews: {
            review1: smartphone1,
            review7: car1
        }
    },
    nopqrstuvwxyz: {
        name: "Magic Blaster",
        reviews: {
            review2: smartphone1
        }
    }
}

To get the reviews of a specific user, you can get the user's uid and use it to display reviews. Unfortunately, I have never used Firebase on Android, in Javascript, I would do it like this:

firebase.database().ref('users/'+userUID+'/reviews').on('value', function(snapshot) {
    firebase.database().ref('product-review/'+snapshot.key).on('value', function(reviewSnapshot) {
        console.log(reviewSnapshot.val().message);
    });
});

If you want to only see the review of user "Conqueror", set userUID to his unique id. Here is the official documentation on Firebase for Android to retrieve data from database.

Community
  • 1
  • 1
gegobyte
  • 4,945
  • 10
  • 46
  • 76
  • Thanks for the quick response. I have few questions, though. 1. Should the timestamps be manually generated for every node (for smartphone1, car1, comment1)? 2. How to retrieve the list of all reviews provided by a specific user (for example by "Conqueror")? – user3314337 Aug 29 '16 at 15:45
  • I need some clarity. Every 'review' node contains only 'SubmittedBy, Review message and TimeStamp' but no information about "Product" (For which product the review was submitted). Now, in the future, the User can see all the reviews he/she provided. But, how can the user find out which review for what product? Hence, isn't it necessary to include the product ID in the Review node??? – user3314337 Aug 30 '16 at 19:06
  • @user3314337 You can include the product ID in the users node, change `review1: true`, you can do `review1: smartphone1`, this way you can know all the reviews of a particular user and also the category it belongs to. I have updated this in the answer. – gegobyte Aug 31 '16 at 01:22
  • Got it. I was thinking of adding `Article ID` to every Review node(`review1`, `review2`,..) along with `submittedBy`, `message` and `timeStamp`. Is there any difference between the two? Thanks – user3314337 Aug 31 '16 at 02:23
  • 1
    @user3314337 You can add it in review node but I think it is unnecessary because when you are on the review page of a particular product, you will only fetch the reviews that belongs to it and all the products have their own reviews node. The only case where you will actually need product ID is when you want to show the reviews of a particular user on their profile page. Ex - `x user posted a review in `. So, there are 2 cases in fetching reviews. One, where you fetch it on product page, in that case, you already know product id and the other is profile page, in this case, – gegobyte Aug 31 '16 at 02:37
  • @user3314337 every user has their own reviews node along with the category. – gegobyte Aug 31 '16 at 02:38
1

Here is the flattest database structure that I can think of. For the products node, you can also use the third structure in your question, it will only affect the logic on how to map the item in your app.

products: {
    item1: {
        type: "smartphone",
        manufacturer_name: "some value",
        screen_size: "some value",
        screen_density: "some value",
        processor: "some value",
        ram: "some value"
    },
    item2: {
        type: "car",
        fuel_type: "some value",
        vehicle_type: "some value",
        vehicle_price: "some value"
    }
},
users: {
    user1: {
        name: "some value",
        email: "some value"
    },
    user2: {
        name: "some value",
        email: "some value"
    },
},
products_reviews: {
    item1: {
        user1: ewview1,
        user2: review2
    },
    item2: {
        user2: review3
    }
},
users_reviews: {
    user1: {
        item1: review1
    },
    user2: {
        item1: review2,
        item2: review3
    }
},
reviews: {
    review1: {
        text: "this is my review",
        timestamp: 1472488486000
    },
    review2: {
        text: "this is my review",
        timestamp: 1472488486000
    },
    review3: {
        text: "this is my review",
        timestamp: 1472488486000
    }
}

Now you should be able to retrieve all reviews from each user and also retrieve all reviews for each product.

Comment here if you have questions, hope this helps :)

Wilik
  • 7,630
  • 3
  • 29
  • 35
  • Just as I imagined. Thanks for the answer. I have a question. Doesn't the product (item1, item2,...) need a time stamp? Can i query the products based on newest to oldest article without the time stamp? – user3314337 Aug 29 '16 at 17:35
  • 1
    If you need to put the "date added" or "date modified" for each product, then yes. For your second question, no you can't, you have to add a date key for that. @user3314337 – Wilik Aug 29 '16 at 17:39