Firestore data structure for a hotel reservation system - firebase

I want to build a hotel reservation system that also will push availability to the channel manager. I want to use Firestore to store my data. I read a few articles but still pretty new to this.
I am planning to set up my database using a structure like this:
collection: "reservations"
fields: reservation_id, status, name, email, check-in date, check-out date, room_id, etc
collection: "rooms"
fields: room_id, room_type, room_number,etc
collection: "availability"
fields: room_id, date, isAvailable
examples: {room_id: 1, date: "2018-10-05", isAvailable: true}, {room_id: 1, date: "2018-10-06", isAvailable: true}
These are some situations I will need:
Situation: A new booking is created
I will create a new "reservation" doc and I will also update the "availability" docs for these dates.
Situation: A multi-calendar view of all rooms
I will get all docs for the dates and rooms and display in a grid
My questions are:
(1) Is this the best structure to set up for Firestore?
(2) Do I need to set "availability" as a subcollection of "rooms"?
The only thing is I need to get all rooms' availability quite often so that will cause lots of reading operations.
(3) Do I store Date as a timestamp object or a string? There's no hour/minute time involved so it looks a bit too much for me and I like "2018-10-05" it looks neat.
(4) How do I write the query to update availability when a new booking is created? How to get the date range I want?
Thank you for reading my questions :)

I recommend you to add dateCreated to reservations.
and for rooms you should also add floor(1st/2nd) and where is hotel level(I mean 5/4 stars)
and you also need a hotel Collections for it's id,Name ,location,stars, isRestaurant Available, Parking Available etc..

Related

How do I model this in DynamoDB?

I am testing out DynamoDB for a serverless app I am building. I have successfully modeled all of my application's query patterns except one. I was hoping someone could provide some guidance. Here are the details:
Data Model
There are three simple entities: User (~1K records), Product (~100K), ActionItem (~100/product).
A User has a many-to-many relationship with Product.
A Product has a one-to-many relationship with ActionItem.
The Workflow
There's no concept of "Team" for this app. Instead, a user is assigned a set of products which they (and others) are responsible for managing. The user picks the oldest items from their products' action item list, services the item and then closes it.
The use case I am trying to model is: As a user, show me all action items for products to which I am assigned.
Any help would be greatly appreciated.
Really only two options...
If you can store the list of products within the 400KB limit of DDB record, then you could have a record like so...
Hash Key: userID
Sort KEY: "ASSIGNED_PRODUCTS"
Otherwise,
Hash key: UserID
Sort key: "#PRODUCT#10001-54502"
userID in the above might be the raw userid, or if using a GSI, might be something like "#USER#user-id"

Firestore group collection query using Flutter

I am new in Firestore database. I am using an app using flutter and Firestore. The database structure for my app is like that:
Rooms --Room1-----Reservations.....reservation dates
.....reservation dates
Room2-----Reservations.....reservation dates
Room3
Room4-----Reservations.....reservation dates
Room5-----Reservations.....reservation dates
.....reservation dates
.....reservation dates
'Rooms' is level 1 collection which holds all the room details. Each of the room data holds the 'Reservations' collection to holds all reservation details(check_in and check_out date) for that room. Now I want to get the list of rooms which are available in a specific date span. How to work with 'group collection query' for this requirement? Or it is possible to do the same by 'group collection query'?
Late but, if anyone comes back to this, now in firestore there is something called collectionGroup query where you can get all subcollections if they have same name. Which can be done as
Firestore.instance.collectionGroup('Reservations').getDocuments()
This will give you the list of all the Reservations across all rooms. Please read in detail about collection group query here in the documentation
Now I want to get the list of rooms which are available in a specific date span.
Given that you store reservations, a room is available when there is no reservation for that time. Cloud Firestore cannot query for the absence of data, so in your current model that query won't be possible.
If you'd store the available slots in each room's Reservations collection, you could query across all Reservations collections to get the available slots across all rooms. But note that the result of this query are documents from Reservations, and not the individual rooms; you will need to load each room separately if you need information from that.
Alternatively, you could store a list of still-available slots in each Room document. With that you could do a regular query across all rooms to see which ones are still available, and then perform an update across the Room document and its Reservations collection in a transaction.

Firestore Data Modelling

My app has two Firestore Collection:
Events (collection)
Document
eventId
hostId (userId of organizer)
title
etc.
Users (Collection)
Document
userId
friends (array of userId's)
age
etc.
I would like for a user to query all events created by his friends.
I considered
do a seperate query for each friend and pull each friend events. This could get ugly with sorting on dates.
adding a hostFriends field in the event and use an array-contains user's Id query. But this will be problematic if someone add a friend after having created an event. I would have to sync this across continiously..
doing client side filtering, but this will lead to many unneccesary reads..
Would be happy to hear any additional idea's or if one of the above would make sense? many many thanks!
This is my first post, apologies if I made any formatting mistakes.

When to duplicate data in noSQL?

I'm working on a project where Firebase Firestore will be used. I've not had experience with noSQL so I work on understanding this technology.
The application lets an user to select a movie category and download an associated movie to let him movie edition.
The category and movie won't be change by the users and will be fixed or change by the owner. Think this like a Netflix catalog where the user can only watches the movies
There are several categories but for the moment only one movie is inside a category (may have more later).
Each movie has related metadata.
In the future:
- an user object will be used to rank each user regarding their score (information related to the application).
- some movie will be available with localisation restriction, i.e a movie would be available for US user only.
In my first thought, the data structure will look like this:
// Collection
Category: {
name: "drama" // Could be action, or other
}
// Collection
Movie: {
name: "Matrix"
description: "Best movie ever"
duration: 1321312
url: "https://www....."
allowedCountry: "us" // is it the right place for this field?
category: "drama" // is it ok to duplicate data here?
}
//Collection
user: {
ranking: 3
withMovie: "Matrix" // is it ok to duplicate data here?
}
I'm not sure if it's the right data structure for this problem.
The flow of the app would present in the first time all the possible categories (so I create a separated collection in order to avoid to iterate on all the song to get the categories)
Then when the user select a category the possible movies are display and the app download the selected one.
Is is okay to iterate on all possible movies to show the movies related to the category?
Or should I put the movies as a sub collection of the category collection?
I'd typically indeed keep the category directly in the movie document in this scenario, since it makes the queries much easier to read.
firebase.firestore().collection("movies").where("category", "==", "drama")
In fact, consider if your movies can really only have a single category (as you've modeled it now), or whether they may have multiple categories in the future (as Netflix does as far as I know). You'd model the latter as an array of categories:
categories: ["drama", "sci-fi"]
And then query it with:
firebase.firestore().collection("movies").where("categories", "array-contains", "drama")

Cloud Firestore and data modeling: From RDBMS to No-SQL

I am building an iOS app that is using Cloud Firestore (not Firebase realtime database) as a backend/database.
Google is trying to push new projects towards Cloud Firestore, and to be honest, developers with new projects should opt-in for Firestore (better querying, easier to scale, etc..).
My issue is the same that any relational database developer has when switching to a no-SQL database: data modeling
I have a very simple scenario, that I will first explain how I would configure it using MySQL:
I want to show a list of posts in a table view, and when the user clicks on one post to expand and show more details for that post (let say the user who wrote it). Sounds easy.
In a relational database world, I would create 2 tables: one named "posts" and one named "users". Inside the "posts" table I would have a foreign key indicating the user. Problem solved.
Poor Barry, never had the time to write a post :(
Using this approach, I can easily achieve what I described, and also, if a user updates his/her details, you will only have to change it in one place and you are done.
Lets now switch to Firestore. I like to think of RDBMS's table names as Firestore's collections and the content/structure of the table as the documents.
In my mind i have 2 possible solutions:
Solution 1:
Follow the same logic as the RDBMS: inside the posts collection, each document should have a key named "userId" and the value should be the documentId of that user. Then by fetching the posts you will know the user. Querying the database a second time will fetch all user related details.
Solution 2:
Data duplication: Each post should have a map (nested object) with a key named "user" and containing any user values you want. By doing this the user data will be attached to every post it writes.
Coming from the normalization realm of RDBMS this sounds scary, but a lot of no-SQL documents encourage duplication(?).
Is this a valid approach?
What happens when a user needs to update his/her email address? How easily you make sure that the email is updated in all places?
The only benefit I see in the second solution is that you can fetch both post and user data in one call.
Is there any other solution for this simple yet very common scenario?
ps: go easy on me, first time no-sql dev.
Thanks in advance.
Use solution 1. Guidance on nesting vs not nesting will depend on the N-to-M relationship of those entities (for example, is it 1 to many, many to many?).
If you believe you will never access an entity without accessing its 'parent', nesting may be appropriate. In firestore (or document-based noSQL databases), you should make the decision whether to nest that entity directly in the document vs in a subcollection based on the expect size of that nested entity. For example, messages in a chat should be a subcollection, as they may in total exceed the maximum document size.
Mongo, a leading noSQL db, provides some guides here
Firestore also provided docs
Hope this helps
#christostsang I would suggest a combination of option 1 and option 2. I like to duplicate data for the view layer and reference the user_id as you suggested.
For example, you will usually show a post and the created_by or author_name with the post. Rather than having to pay additional money and cycles for the user query, you could store both the user_id and the user_name in the document.
A model you could use would be an object/map in firestore here is an example model for you to consider
posts = {
id: xxx,
title: xxx,
body: xxx,
likes: 4,
user: {refId: xxx123, name: "John Doe"}
}
users = {
id: xxx,
name: xxx,
email: xxx,
}
Now when you retrieve the posts document(s) you also have the user/author name included. This would make it easy on a postList page where you might show posts from many different users/authors without needed to query each user to retrieve their name. Now when a user clicks on a post, and you want to show additional user/author information like their email you can perform the query for that one user on the postView page. FYI - you will need to consider changes that user(s) make to their name and if you will update all posts to reflect the name change.

Resources