Firebase Database Structure For Better Queries - database

I am working on an app that helps the user search for their desired medication in nearby pharmacies then shows a list of the pharmacies that have the drug in stock with prices.
I come from a SQL background and have been having a hard time deciding how to structure Firestore databases for better queries, I think normally you would go through the list of pharmacies and their databases but is there a way to have a single database for all the drugs with maybe a field that has the primary keys of the pharmacies that have it in stock in Firestore?

There are two ways in which you can solve this. The first one would be to create a sub-collection under each pharmacy to hold all available drugs:
Firestore-root
|
--- pharmacies (collection)
|
--- $pharmacyId (document)
|
--- drugs (sub-collection)
|
--- $drugId
|
--- name: "Aspirin"
|
--- inStock: true
To get all pharmacies that have, for example, Aspirin in stock, a collection group query is needed. In Android, the query should look like this:
db.collectionGroup("drugs").whereEqualTo("name", "Aspirin").whereEqualTo("inStock", "true");
The second option that you have is to create a single top-level collection of drugs:
Firestore-root
|
--- drugs (collection)
|
--- $drugId (document)
|
--- name: "Aspirin"
|
--- inStock: true
|
--- pharmacyId: $pharmacyId
And create a simple query that looks like this:
db.collection("drugs").whereEqualTo("name", "Aspirin").whereEqualTo("inStock", "true");
So you can choose to work or one or the other according to the use-case of your app.

Related

How to structure products/orders in a firestore model?

So I'm creating a vue.js app and using Firebase as a back-end service. I have gotten some knowledge now on how one can store data in firestore but I'm asking what way would be the best for my case. At a certain point in the app, users can complete orders where each order has certain products. Every order will have an average of let's say 5/6 products, which are objects. Which of the following ways to strcture this data would you suggest?
orderedProducts as a top-level collection: here every document in this collection would have a reference to the order. Since I only need the products related to one order, I think this would be a bad choice. The relation is somewhat gone?
subcollection: here products can be a subcollection of orders. Nice hierarchy / structure but increases document reads compared to embedded array.
array: products is embedded as an array inside an order document. This is what I have now and is the easiest approach to create.
I thought, since the amount of products per order will be rather slim, I just use an array of products inside my order document. But ofcourse I might be wrong, or missing some important stuff.
I would appreciate any help/pointers on this real-life example on how to structure these products per order.
Thanks!
A possible schema for your app's use-case might be:
Firestore-root
|
--- merchants (collection)
| |
| --- merchantId (document)
| |
| --- //merchant details
|
--- orders (collection)
|
--- orderId (document)
|
--- merchantId: "LongMerchantId"
|
--- products (array)
|
--- 0
| |
| --- productName: "Bacon"
| |
| --- productPrice: 5
|
--- 1
|
--- productName: "Eggs"
|
--- productPrice: 12
Using this structure you can easily query for all orders of a single merchant:
db.collection("orders").whereEqualTo("merchantId", "LongMerchantId");
To get all the products of a particular order, simply use the following reference:
DocumentReference orderIdRef = db.collection("orders").document("orderId");
Now you can attach a listener on this reference, get the document and use the products list. You didn't specify the programming language that you are using so I gave you the examples in Android. It's very simple to transform them in the language you are using. For Android, to get a list of custom objects, please check the following article:
How to map an array of objects from Cloud Firestore to a List of objects?
One more thing to note is that the solution above will work only if you are sure that products in an order will fit in a 1 MiB (1,048,576 bytes). If you are not sure, instead of an array you should use a sub-collection. If you want to be 100% safe, you can always check against the maximum quota, using FirestoreDocument-Android library.

Best way of structuring documents in Cloud Firestore (NoSQL databases)?

I am trying to implement a Firestore Cloud DB but I am new to NoSQL databases.
I want to know whats the best way of arranging these sets into collections/documents:
I have restaurants which have different foods and reservations. What would be the best approach to structure these sets of data into Firestore DB?
Is this a right approach:
Restaurant1 (Collection)
----> Foods (document)
----> Reservations (document)
I think storing Foods and Reservations as top level collections will ultimately yield you more flexibility later on.
It's easy enough to take a restaurantID and stick it in the each document in those collections, so I don't personally think you should nest them in the Restaurants collection. It's a personal preference from working with a lot of nested collections.
I think the optimal structure is:
Restaurants (collection)
--- Name: Chipotle
--- ID: restaurant1
--- Foods: [{ Name: foodItem1 }, { Name: foodItem2 }]
Foods (collection)
--- Name: foodItem1
--- Ingredients: abc
--- Nutrition Facts: xyz
Reservations (collection)
--- User: user1
--- Restaurant: { id: restaurant1, name: Chipotle }
--- Time: 3pm
Users (collection)
--- ID: user1
What you'll notice is there is some redundant info. This is good so if you request all reservations, you'll get the restaurant's name and ID, etc. stuff you would likely want. You will find you'll want to store data multiple times and this to me feels like a good structure for it.
With this structure you can very easily just call:
All reservations by user X or All foods meeting nutrition limits of Y
Instead of a collectionGroup query which would call for all restaurants' sub collection list of reservations. You won't always want to query your reservations by restaurant, maybe you want to pull by user or time, etc.
According to your comment:
the restaurant´s management should be able to see his reservation together with other reservations from other clients, in a list. And each client should be able to see his history of reservations as well.
I'll try to provide you a schema that can help you get that data very easily.
Firestore-rrot
|
--- users (collection)
| |
| --- uid (document)
| | |
| | --- type: "manager"
| |
| --- uid (document)
| |
| --- type: "client"
|
--- reservations (collection)
|
--- reservationIdOne (document)
| |
| --- reservedBy: "uid"
| |
| --- date: September 21, 2019 at 1:15:02 PM UTC+3
|
--- reservationIdTwo (document)
|
--- reservedBy: "uid"
|
--- date: September 21, 2019 at 1:18:42 PM UTC+3
Using this schema, you can simply query the database to get all users or specific users (manager or clients). You can also get all reservations by adding a reference on reservations collection. If you want to get the reservation only of a single type (manager or client), you should use a query that might look like this:
db.collection("reservations").whereEqual("type", "manager");
As you can see, I have also added a date property so you can easily sort them descending (last reservation first).
It really depends on the use-case you are trying to solve, as you should be optimizing for specific queries on those models.
I recommend watching these videos to get a better idea:
Series of What is a NoSQL Database? How is Cloud Firestore structured?
Model Relational Data in Firestore NoSQL
Firestore Data Modeling - Five Cool Techniques

How to structure Dynamodb correctly to have nested or linked properties?

I am getting started with Dynamodb and I am trying to figure out what is the correct way to structure the following:
I have a user, and each user can have multiple pictures (s3 links and some metadata), with no limit to the amount.
Whenever I am calling for a user I would retrieve all their pictures, there would be no reads on a single picture, and each time a user uploads a picture, I need to store it for the user.
In Mongodb I would have created an array called pictures holding objects with each picture's data. Is this also the correct approach in Dynamodb?
Here is how you can do with dynamodb
| pk | sk |
| user1 | metadata | age:24 | name: Jon| ...
| user1 | picture#1234#id1 | url:abc.com/xyz.jpeg | ... some other metadata
| user1 | picture#2456#id2 | url:abc.com/xyz.jpeg | ... some other metadata
| user1 | picture#4567#id3 | url:abc.com/xyz.jpeg | ... some other metadata
where 1234, 2456 may represent epoch time uploading the picture.
Now you can do queries like
get me all the pictures in chronological order.
Select * from table where pk=user1 and sk starts with picture#
get me all the pictures uploaded b/w or after certain date.
Select * from table where pk=user1 and sk starts with picture# and sk>picture#1234
Get me user details
Select from table where pk=user1 and sk=metadata
This will make sure few things
No race condition/lock while uploading the picture
you can decide how many images you want to fetch, And you will read only what you need, instead of loading all of them and then filtering.

Technique to map any number of varying data schemas into a normalised repository

I'm looking for some guidance, what's the best way to transform data from A to B. I.e. if each client has different data but essentially recording the same details, what is the best way to transform this into a common schema?
Simple example showing different schemas
Client A | Id | Email | PricePaid | Date |
Client B | Id | Email | Price | DateOfTransaction |
Result schema
| Id | Email | Price | Order_Timestamp |
This simple example shows two clients record essentially the same things but with different names for the price and date of the order. Is there a good technique to automate this for any future schema but purely through configuration? I.e. maybe something with XML/ XSD perhaps?
Many suggestions welcome.
Thanks,

Modelling a voting poll in a graph database

I've modelled a voting poll for a RDBMS system. The structure is a bit more complicated than a conventional voting poll since users can choose to vote either for an option on the poll or pass on their vote to another user for a given poll.
My structure looks something like this:
Polls
id | title
----------
1 | Who should be president
Options
id | poll_id | title
--------------------
1 | 1 | Obama
2 | 1 | Bush
Vote
id | poll_id | user_id | vote_type | vote_id
--------------------------------------------
1 | 1 | 1 | option | 1
2 | 1 | 2 | user | 1
In this case, option 1 would receive 2 votes since user 2 gave his vote to user 1 who votes for option 1.
I realize that the data I am going to store is going to be fairly complicated to query in a RDBMS system if I want to visualise how the votes move between users. However, I don't have much experience with graph databases and would like some hints as to how I go around modelling this.
It's always preferable, when making a DB model, to start with an information design model, and then transform this into a DB model.
In an information design model for your problem, options would be componenents of polls (so the UML class diagram would have a composition between Option and Poll), and votes would be relationships/links between users and options (so the UML class diagram would have a *many-to-many association between Option and User, the instances of which are the votes). In addition, there is a ternary association User-delegates-his-vote-in-Poll-to-User, the instances of which are the delegations.
From this, I get the following DB model:
Poll( id, question)
Option( poll_id, option_sequence_no, possible_vote)
Vote( user_id, poll_id, option_sequence_no, nmr_of_votes)
Delegation( user_id, poll_id, delegate_id)
Of course, we have to add a constraint that the number of votes by a use in a poll is the number of delegations plus 1.

Resources