How to design shopping cart data with Firestore? - reactjs

I use Firestore as my back-end. I have designed my data for the shopping cart like this:
cart--
cartid--
product--
id: 'dsdasd',
title: 'New Dress',
price: 10,
images: 'https://someurl/image.jpg
totalPrice: 50,
amount: 5
But I am not sure to use it. I'd like to hear some suggestions for this situation. I built it in React.js. How can I design my shopping cart data with Firestore? What should I use Firebase or Firestore?

I'd personally use Firestore, but it also depends on your needs and your app's requirements. You can read more about differences between the Realtime DB and Firestore here.
Talking about your data model, I'm not sure about your actual implementation (it's not clear from the question), but you may need two different collections: products and carts.
Every cart document will have a field (array/object) with all the products IDs in that cart. This way you can achieve data consistency, fetching product data from the actual product document every time you need it (for example displaying the cart).
The totalPricefield in the cart is probably unnecessary and leads to data inconsistency, because you need to update it when products in the cart change. It might be better to display the total price in the front end with a simple sum.

Related

How to manage Redis relations

The situation might be a bit complex, let's say I have a shopping cart related to items (items has some other relations with other entities) in a relational DB, it does not have any problem of query the shopping cart with all the other related entities by specifying them.
Now I am trying to move the shopping cart to Redis for high performance, if the shopping cart is created, with the items and the other relations will be saved to Redis.
await client.hSet(`shopping-cart:id:${cartId}`, {shoppingCartObj});
shoppingCartObj:
{
cartId: string,
items: [
item1: {
maker:{},
},
item2: {
maker:{},
},
item3: {
maker:{},
},
]
}
My question is the items and the items other related entities are still in DBMS like Postgres. They are still editable for users, like the maker. If the shopping cart is read from Redis always, they are out dated. Any strategy to maintain?
I can think of only maintain the shopping cart and the item relation in Redis with id links like cartId with itemId, if needed query again with the itemId.
Or load the items in the Redis as a copy, but will need to update if the user edited it.
Any other suggestions?

Structuring the Firestore: Should I make another collection to store the changes that were made?

I am using Reactjs and Firestore.
I have this collection of products:
The colorMap is a map then below it are the different colors and their quanty.
Now, I want to create a list or a history whenever a product is added and whenever the quantity in those colors was added more of it.
Should I add another collection that will store when a product is added or whenever quantities are added in the color? I'm also thinking of adding a createdDate
Or there any other way I could do this? As much as possible, I won't be using any cloud functions.
A common way to keep the history of each document is by creating a subcollection under that document (say history) and writing a new document with either the complete, old document data there for every update you perform, or a new document with just the old values of the fields that were modified.
While it is convenient to do this from Cloud Functions, as they already get both the previous and the new data for each document write, you can accomplish the same from client-side code too.

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"
}
}
}
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.
If you want your feed items to be in sync with the real users data (new profile image when the user changes it for example) you can simply store the user ID in the eventUpdate document. This way you don't have to keep them in sync manually, and every time you have to display the item in the feed you could simply fetch user data, and easily query many eventUpdates on userId and created_at fields ( assuming you have them ).
To implement likes in your feed the solution depends on a bunch of things like traffic volume.
The simplest way is to update a likes field with a transaction, but Firestore has a maximum updates frequency on a single document of 1 second. Plus, a transaction can easily fail if more than 5 transactions are trying to update the same document.
To implement a more solid likes system take a look at this page from the official Firebase docs.
Firestore has a different approach to the NoSQL world. Once you know the data you will use (as You already do) there are some very important points about what architecture the data will have. And It depends a lot about how the data grows, what kind of queries you will need and how often you will use them. Some cases You can create a root collection that aggregates data and queries might be easier.
There is a great video from Firebase Channel that might help. Check it out!
How to Structure Your Data | Get to Know Cloud Firestore #5
https://www.youtube.com/watch?v=haMOUb3KVSo
[UPDATED] December 26th
Others videos that might help to model and query your data is these videos:
How to Connect Firebase Users to their Data - 3 Methods
https://www.youtube.com/watch?v=jm66TSlVtcc
How to NOT get a 30K Firebase Bill
https://www.youtube.com/watch?v=Lb-Pnytoi-8
Model Relational Data in Firestore NoSQL
https://www.youtube.com/watch?v=jm66TSlVtcc

Redux Structure Advice

I've built a few React Native apps with Redux and I've traditionally modeled my state after the views/ui. I've come to realize that this isn't the best way to organize Redux state.
Through some recent research, I know now that it's best practice to not store duplicate data in different reducers, as updating them can become tedious. It's better to store data in objects with the keys being the id and the value being the data object itself.
This makes sense for data that will be the same on every screen/page, but what if your app uses the data differently on different screens?
For example:
I have a list of products on a home screen and a list of products on a category screen. Both have pagination and are looking at different subsets of the product data. I could use a selector method here and only select products belonging to the specific category on the category screen, but how would that work with keeping track of pagination data for each one?
If I scroll down on the home screen and load a bunch of product data, then switch to the category screen, I'll have more data already loaded.
Any advice is appreciated, thanks!
You should normalize your data (https://github.com/paularmstrong/normalizr) so you can have your redux state like:
{
home: [...list_of_id_products],
category: [...list_of_id_products],
data: [actual_array_of_objects]
}
then you can have separated lists, all linked to the same set of data

How to retrieve all children from Firebase Database

I'm trying to learn how to use Firebase by creating a simple social media application.
https://i.stack.imgur.com/wfeyw.png (Here is how my database is laid out)
I was able to add data to the database but I'm having trouble understanding how to retrieve data. I want to be able to retrieve all the posts from a certain user and then display each one as an item in a list.
let Posts = firebase.database().ref('Posts').child(userId);
So far thats my query and here is the code I'm using to add the posts to the database. Could someone also tell me what is the term for the Id that is being generated for each post?
firebase.database().ref('/Posts').child(userId).push({
Text: post,
Score: 0
});

Resources