Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create the following data structure in a NoSQL environment

Intro
I have a FireStore database similar to a social media db, with 3 collections Users, Events, and EventUpdates. My goal is to create a feed with eventUpdates created by me and my friends. So i have to expand my database with friendship connections. But i struggle with 3 problems, and hopefully somebody here can push me in the right direction to solve these.

Problem/Question 1:
I added username and user image to the EventUpdate model so it's easier to query. I've heard denormalise is the way to go in a NoSQL database. But if a user updates his user image, i've to update all eventUpdates created by that user. Sounds like something you don't wanne do. But is there a better way to do this?

Problem/Question 2:
How can i create a data structure that is optimised for performing the following query: get eventUpdates from me and my friends ordered by date.

Problem/Question 3:
How to store likes? I can keep a counter in a eventUpdate. But this becomes a problem when i denormalise eventUpdates (see current solution underneath EDIT)..

Data structure example .

{
  "users": {
    "1": { "name": "Jack", "imageUrl": "http://lorempixel.nl" }
  },
  "events": {
    "A": { 
      "name": "BeerFestival", 
      "date": "2018/09/05",
      "creatorId": "1"
    }
  },
  "eventUpdates": {
    "1": {
      "timestamp": "13243543",
      "creatorId: "1",
      "creatorName": "Jack",
      "creatorImageUrl": "http://lorempixel.nl",
      "eventId": "A",
      "message": "Lorem ipsum"
    }
  }
}

EDIT

OK, after some trial and error i ended up with the following structure. This structure seems work, but my problem with this solution is that i need to make a lot of write calls to update a single eventUpdate because of all the copies in each feed (1000 followers means 1000 copies). And it looks like i need to do that a lot.

I would like for example to add a like button to each event update. This trigger an update on all EventUpdate copies. For me it looks like firebase is not suited for my project and i'm thinking of replacing it with a SQL DB, or can anyone here change my mind with a better solution?

{
  "users": {
    "user1": { "name": "Jack", 
      "imageUrl": "http://lorempixel.nl",
      "followers": ["user1"]
    }
  },
  "feeds": {
    "user1": {
      "eventUpdates": {
        "1": {
          "timestamp": "13243543",
          "creatorId: "1",
          "eventId": "A",
          "message": "Lorem ipsum"
        }
      },
      "following": {
        "user1": { 
          "name": "Jack", 
          "imageUrl": "http://lorempixel.nl",
          "followers": ["user1"]
        }
      }
  },
  "events": {
    "A": { 
      "name": "BeerFestival", 
      "date": "2018/09/05",
      "creatorId": "1"
    }
  }
}
like image 696
Luciano Avatar asked Sep 03 '25 15:09

Luciano


1 Answers

I added username and user image to the EventUpdate model so it's easier to query. I've heard denormalise is the way to go in a NoSQL database.

That's right, denormalization and is a common practice when it comes to Firebase. If you are new to NoQSL databases, I recommend you see this video, Denormalization is normal with the Firebase Database for a better understanding. It is for Firebase realtime database but same rules apply to Cloud Firestore.

But if a user updates his user image, i've to update all eventUpdates created by that user. Sounds like something you don't wanne do. But is there a better way to do this?

Yes, that's also correct. You need to update all the places where that image exists. Because you have chosen google-cloud-firestore as a tag, I recommend you see my answer from this post because in case of many write operations, Firestore might be a little costly. Please also see Firestore pricing plans.

Regarding Firestore, instead of holding an entire object you can only hold a reference to a picture. In this case, there is nothing that you need to update. It's always a trade between these two techniques and unfortunately there is no way between. You either hold objects or only references to objects. For that, please see my answer from this post.

How can i create a data structure that is optimised for performing the following query: get eventUpdates from me and my friends ordered by date.

As I see, your schema is more a Firebase realtime database schema more than a Cloud Firestore. And to answer to your question, yes you can create. So talking about Firestore, you can create a collection named eventUpdates that can hold eventUpdate objects and to query it according to a timestamp, a query like this is needed:

FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference eventUpdatesRef = rootRef.collection("eventUpdates");
Query query = eventUpdatesRef.orderBy("timestamp", Query.Direction.ASCENDING);

But please note that the timestamp field should be of type Date and not long. Please also take a look at my answer from this post, to see how you can add a date property in a Cloud Firestore database.

How to store likes? I can keep a counter in a eventUpdate. But this becomes a problem when i denormalise eventUpdates (see current solution underneath EDIT)

You can simply add likes but I recommend you see the last part of my answer from this post. So you might consider adding that count in a Firebase realtime database rather than in Cloud Firestore. Both databases work very well together.

This structure seems work, but my problem with this solution is that i need to make a lot of write calls to update a single eventUpdate because of all the copies in each feed (1000 followers means 1000 copies). And it looks like i need to do that a lot.

You might also take a look at my answer from this post.

For me it looks like firebase is not suited for my project and i'm thinking of replacing it with a SQL DB, or can anyone here change my mind with a better solution?

I don't think this way. There are many apps out there that have the exact mechanism as yours and are working very well.

like image 175
Alex Mamo Avatar answered Sep 05 '25 09:09

Alex Mamo