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

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.

Related

Firebase - copy document to a new collection and update a field

I have a Firebase database with a list of entries. Now, on click, I want to copy a certain document from this database to a user database (create new document in user DB) while at the same time updating one of the fields.
I figured out how to copy the document, but I have problems with updating the field. I think I'm simply using a wrong syntax, but couldn't find this example in Firebase documentation.
This is how the original document looks like: (https://i.stack.imgur.com/ux18x.png)]
And this is how it's copied into the user database: (https://i.stack.imgur.com/QsBVy.png)]
I use this code to make the copy:
setDoc(doc(userSentencesRef, newSentenceIDText), ...newSentence)
And I tried many ways to update the "Level" field, but none of them works:
setDoc(doc(userSentencesRef, newSentenceIDText), ...newSentence, {data: {LEVEL: "exclude"}})
setDoc(doc(userSentencesRef, newSentenceIDText), ...newSentence, {LEVEL: "exclude"})
setDoc(doc(userSentencesRef, newSentenceIDText), {...newSentence, LEVEL: "exclude"})
(the first two do nothing, the last one adds a separate level field).
I also wouldn't want to list every single field that needs to be added { EN: data.EN, DE: data.DE }, etc, because I want to make sure it works even if the other fields change in future.
I will really appreciate your help.

How to store custom sort order in a web app

I am developing a React Firebase web app, and I want to implement a "custom" sort on top of sorting by name and date. How should I go about storing this "sort" information?
Do developers append a "key" property to the components themselves? How will reordering work then (do i shift every component's key values by 1? That seems inefficient). Or should I do a separate file or database entry that just stores the order as an array of component id keys?
Should all of this be resorted on page load or should I reorganize the data in a way where as soon as I request them they're already sorted?
I've tried adding the order key prop to every item but it seems overly complicated for a simple feature. I haven't had much luck searching this online.
Firestore allows you to orderBy and limit queries.
You can also specify a cursor to paginate more data on request.
See This Example in the docs for more info.

Variable value for Amount for Salesforce opportunity API

I'm working on a Magento website. In that, after the customer is done with adding products to the cart he fills a form and once the form is submitted, form data along with product details like SKU, price is sent to Salesforce to create a new opportunity.
The API is working and the Data is going to salesforce, but the issue is that the same product can have different prices based on certain conditions.
the new amount going to salesforce but on the salesforce side, the new amount is not reflecting but the amount when the product is created for the first time is coming.
is there any way to make the amount a variable field so the new amount reflects?
below is an image of the opportunity and the JSON data I'm sending.
{"StageName":"New Opportunity","Name":"test","CloseDate":"2021-06-04","What_are_you_interested_in__c":"Purchase New Trailer","Product_JSON__c":"[{\"Name\":\"Large Trailers\",\"Sku\":\"large-trailers-rent\",\"Quantity\":1,\"Price\":\"1301.0400\"}]","Purchase_Delivery_Contact_Phone__c":"123","On_Site_Contact_Email__c":"test-12#test-12.com","Mailing_Street__c":"test-12","Delivery_Street__c":"","Qty__c":"1","X66969__c":0,"First_Name__c":"test-12","Last_Name__c":"test-12"}
This request looks weird. Vanilla Salesforce doesn't need hacks like a text field to hold serialised JSON in it (Product_JSON__c).
Where do you send it? Normal POST to something like services/data/v51.0/sobjects/Opportunity or some custom endpoint (it'd have "/apexrest" in the URL). Even if it goes to normal endpoint - I guess there's trigger that deserialises this Product_JSON__c and creates OpportunityLineItems out of it. You'll have to chat with developer responsible for that trigger, we can't tell what's going on in there.
In general yes, it's possible to have variable prices. You (or that developer) have to read up about OpportunityLineItem. There's ListPrice,UnitPrice,TotalPrice,Discount, lots of choices to do this right and report properly on the discounts! And there are tips like
Creating an OpportunityLineItem increments the Opportunity Amount
value by the TotalPrice of the OpportunityLineItem
There are ways to do it properly, insert header (Opportunity) and line items in one go, without such hacks. See
https://salesforce.stackexchange.com/questions/155422/using-the-rest-api-to-create-parent-and-child-records-in-a-single-http-request
https://salesforce.stackexchange.com/questions/274694/can-you-upsert-using-composite-sobject-tree
https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/resources_composite_sobject_tree.htm

What's the most efficient and scalable way to handle filtering and sorting of a large collection in cloud firestore?

I have a large collection where each document is of a substantial size and therefore cannot be embedded into a single document. For my feature, I need to sort the collection using orderBy and filter the collection using "array-contains" and "==" where the sort and filter parameters are provided by the user. I was wondering if there was an efficient way to do this by cacheing documents that had already been fetched in previous queries. That being said, does firebase do any cacheing itself and does it already optimize what I'm trying to do in this case, or is there any custom cacheing/optimization I can do?
This is what my implementation looks like right now. This works fine for now however it's not very scalable as it creates a new realtime listener each time any of the filter/sort state changes. Is there any way can I improve this to minimize the total number of documents read?
useEffect(() => {
if (!sort || !status || !search) return;
const unsubscribe = firebase.collection("users")
.where("searchTerms", "array-contains", search)
.where("status", "==", status)
.orderBy(sort)
.onSnapshot((snapshot) => {
// update state hook with snapshot data...
});
return () => unsubscribe();
}, [sort, status, search]);
Thank you for any and all help!
Typically, you will want to use a search indexer to enable functionality like this.
The Firebase documentation recommends using Algolia for full-text search. You want to create a cloud function that indexes the data you want to search on, along with the Firestore document ID. On the frontend, you can use the Algolia API to get search results and then fetch the whole document From Firestore when you need to display it.
An alternative to pagination for "big data" and still supporting complex queries can be done by baking the data for the client into a simplified search collection.
This displays only key information that represents a source document by combining the essential data into a dedicated collection of all the results.
Each document can hold up to 1MB of data each and that can equate to roughly 10k-200k entries based on your data size. It does take some time to set up but it has been effective for handling long-lived data within firebase without additional 3rd party solutions.
The key takeaways are as follows:
This is ideal for data that doesn't update too frequently, multiple changes at once can hit the 1 second limit per document.
All search documents contain two properties, a counter to maintain the current entries and an array of strings that represent your essential data.
Each source document needs to maintain a document ID of its entry document for future updates
On update, you find the search index ID, and use arrayUnion and arrayRemove methods, preferably with a transaction and update the source document.
Optionally, you can use the new Bundle Method to bundle this collection with your app
Resources:
https://firebase.google.com/docs/functions/firestore-events#event_triggers
https://firebase.google.com/docs/firestore/manage-data/add-data#update_elements_in_an_array
https://firebase.googleblog.com/2021/04/firestore-supports-data-bundles.html

Is Firestore a good database for storing many large objects in?

I have been using React/Leaflet to create a choropleth map that can color any country on the map. What I am trying to do is to develop a save/load function that saves the colored countries and later be able to import it from the database. When this object is saved and loaded, it can bring back the exact same countries that were colored. I have been using firebase/firestore but I haven't been getting any luck.
This is how my object of map data looks like
Is Firestore the right database to do it? Or should I approach another database? I need a database that can store multiple objects in the picture above.
If you can convert that file into a JSON of a size smaller than 1MB, which is the Firestore Document size limit, it is possible. In the case you are proposing I would have the following structure, from the information you shared but fell free to adapt it as you see fit:
Map Collection
field1
...
fieldN
CountriesOptions Subcollection
optionObject: {}
Where each object is a separate document in the CountriesOptions subcollection converted to JSON using JSON.stringify(obj).
For more information on how to structure your Firestore with subcollections you can check this link to the documentation.

Resources