I want to create a collection in Firestore through flutter where I can store a quantity variable which gets updated when I stock in and stock out items through my flutter app. However I can't seem to understand how to create that. How should I store that and how should I update the quantity field on stocking in and out items?
A collection is automatically created when its first document is created.
So if you need to manage only one stock you can create (initiate) a unique document in e.g. a stock collection and assign the initial stock. This initialization can very well be done through the Firestore console,
Then, to adapt the stock quantity, it depends on your global functional requirement:
If you just want to increment/decrement the stock quantity without impacting any other document in Firestore you can use the FieldValue.increment() method (use a negative value to decrement).
If your operation must be transactional and involves some other Firestore document (e.g. you modify a bank account, or a e-commerce basket, or another stock in parallel to this stock operation) you should use a Transaction.
You may also consider if you really want to allow this operation from your Flutter app and not from a back-end (e.g. Cloud Functions). To allow end users to do this from an app you'll have to open the write access to one or more collections and a malicious user could change the stock value in an undesired way if you cannot implement a security rule that prevents that.
Related
I have over 3,000 contacts in my phone. My firestore will hold over 1,000,000 contacts.
I can pull contacts from firestore to client to compare, I can push contact from client to firestore to compare. But I do not consider any of the two means effective.
pull over 1,000,000 records from firestore to check against 3,000 records is not efficient as online data may grow to over a billion.
pushing 3,000 records at 10 per request will lead to too much requests to the firestore and incur unnecessary cost.
What is the best way to compare these two data and return common elements?
If I were you, I will do like this way.
Dumping two databases and comparing them with another database.
Add one more flag for 1,000,000 contacts to know which one has the same value inside the database which has 3000 data.
Upload them(1,000,000 contacts) to Firebase,
To set up the filter to get querySnapshot.(Refer to Sample Code1)
When you have a new contact list(from 3000 data that one)
To use that new contact to filter that database(1,000,000 contacts) and remarked them with the flag 'contactExistingFlag'
Sample Code1
QuerySnapshot querySnapshot = await _firestore.collection('contactTable').where('contactExistingFlag', isEqualTo: 0).get();
//isEqualTo: 0 means that contact is new
//isEqualTo: 1 means that contact is existing
Sample Code2
QuerySnapshot querySnapshot = await _firestore.collection('contactTable').where('contactName', arrayContainsAny: ["New Member1", "New Member2"]).get();
//Use the array-contains-any operator to combine up to 10 array-contains clauses on the same field with a logical OR.
Firestore (both Cloud & Firebase) does not have any built-in operator to compare two sets. The only option is to iterate over each number and find if it has a match as recommended in this stackoverflow post. Searching for the Phone Contacts by sending them via Firebase Queries seems like a better approach.
There are ways to design your application in such a way that this kind of operation ( comparing 2 sets of numbers between address book & Firestore) is performed once in a lifetime per user signing up for an application. In future, if there is a new user getting added in Firestore database, we can do a reverse update i.e. check for that newly added number on every user's app (address book) and update that contact accordingly for given user's app if the match is found.
Note: querying the Firestore database for a matching document (with a matching phone number) does not imply billing for read operation against all documents. Please refer to the billing section of Firestore queries for more details.
I am new to NoSQL and I'm trying to figure out a good way to represent my data. I have a series of workers that need to request vacations via mobile app.
When I try to write a Firebase query with Flutter, I can do this:
Firestore.instance
.collection("ferie_permessi")
.document("worker1#test.com")
.snapshot();
It works but there are two main errors:
If I try to create another collection called "Woker info" I cannot use worker1#test.com as document ID as it already esists;
I have to sort data client side because firestore doesn't give me the possibility (with this setup I've made).
I'm quite sure that this structure isn't good at all. Each worker needs to have 2 lists: vacations and other. What is wrong?
My guess is that I should move worker1#test.com together with vacations and other so that I can make a query of this kind:
Firestore.instance
.collection("ferie_permessi")
.where("user", "==", "worker1#test.com)
.snapshot();
But now the id? Is an automatic one good?
I had a chance to recently explore creating an app using a firebase-firestore. A couple of things will help here:
Yes, the autogenerated id is good since it is unique, for example, you can have a collections vacation_requests, users you can then use that user_id as a document in vaccation_requests -> user_id -> vacations, instead of using email as a document key.
Or
You can do it like this collections users, vacation_requests, and requests.
store user details in users.
store requests in requests with from and to dates.
store reference of User and Request in vaccation_requests.
Hope this helps!
I have 2 collections. One of them is named "USERS", and the other one "MATCHES". USERS, can join in the MATCHES, appearing the avatar of the user who has joined in the match. The problem is that when the user changes their avatar image after joining in the match, the match avatar doesn't changed, because the match has the old avatar.
The avatar is saved as Base64 in Firestore, but I will change it to "Storage" in the near future.
I have been trying to set the reference, but that only gives me the path.
If I have to do a Database Api Call for each match which is joined the user, maybe I have to do 20 Api calls updating the matches. It can be a solution, but not the best.
Maybe the solution is in the Google Functions?
I'm out of ideas.
Maybe the solution is in the Google Functions?
Cloud Functions also access Firestore through an SDK, so they can't magically do things that the SDK doesn't allow.
If you're duplicating data and you update one of the duplicates, you'll have to consider updating the others. If they all need to be updated, that indeed requires a separate call for each duplicate.
If you don't want to have to do this, don't store duplicate data.
For more on the strategies for updating duplicated data, see How to write denormalized data in Firebase
I have a set of static and pre-defined to-do's that each user in my app needs to be able to set as completed on their account.
At the moment, I use a map on the todo item that specifies which users has completed the task. My data model at the moment looks like this:
- todos (collection)
- todoA (document)
- title, description etc
- completedBy {
uid1: true,
uid2: true,
uid3: false
}
This allows me to easily set todos as completed/not completed for each user and I can easily filter/query. It does have two drawbacks though:
A single Firestore document can "only" have 20 000 properties. If my app would grow large, this would be an issue.
Document size
I was thinking of maybe creating a similar map on my user document instead, setting todo ID's as true/false. This would get rid of the two drawbacks above but I'd need two database queries whenever I'm getting my todo items, one for the todo and one to check if it's completed.
Is there a better way to achieve the desired functionality in Firestore?
If you are running into either the maximum number of fields or the maximum document size, then typically that means that you should be using a separate collection for "the thing that makes your documents so big".
In your case that'd mean that you store the "user has completed a task" in a separate collection. This can be a subcollection of the user document, a subcollection of the task document, and/or a separate top-level collection. Which one is correct depends on your use-case.
There is no single best data model in NoSQL databases. It all depends on your use-cases, trade-offs, and some personal preferences. For a great introduction read NoSQL data modeling and watch Get to Know Cloud Firestore.
I am using Sitecore 8.1 with xDB enabled (MongoDB). I would like to store the user-roles of the visiting users in the xDB, so I can aggregate on these data in my reports. These roles can change over time, so one user could have one set of roles at some point in time and another set of roles at a later time.
I could go and store these user-roles as custom facets on the Contact entity, but as they may change for a user from visit to visit, I will loose historical data if I update the data in the facet every time the user log in (fx. I will not be able to tell which roles a given user had, at some given visit).
Instead, I could create a custom IElement for my facet data, and store the roles along with a timestamp saying when the given roles were registered, but this model may be hard to handle during the reporting phase, where I would need to connect the interaction data with the role-data based on timestamps every time I generate a report.
Is it possible to store these custom data in the xDB in something else than the Contact collection? Can I store custom data in the Interactions collection? There is a property called Tracker.Current.Session.Interaction.CustomValues which sounds like what I need, but if I store data here, will I be able to perform proper aggregation/reporting on the data? Any other approaches I haven't thought about?
CustomValues
Yes, the CustomValues dictionary is what I would use in your case. This dictionary will get serialized to MongoDB as a nested document of every interaction (unless the dictionary is empty).
Also note that, since CustomValues is a member of the base class Sitecore.Analytics.Model.Entity, this dictionary is available in many other data classes of xDB. For example, you can store custom values in PageData and PageEventData objects.
Since CustomValues takes an object of any class, your custom data class needs some extra things for it to be successfully saved to and subsequently loaded from MongoDB:
It has to be marked as [Serializable].
It needs to be registered in the MongoDB driver like this:
using Sitecore.Analytics.Data.DataAccess.MongoDb;
// [...]
MongoDbObjectMapper.Instance.RegisterModelExtension<YourCustomClassName>();
This needs to be done only once per application lifetime - for example, in an initialize pipeline processor.
Your own storage
Of course, you don't have to use Sitecore's API to store your custom data. So the alternative would be to manually save data to a custom MongoDB collection or an SQL table. You can then read that data in your aggregation processor, finding it by the ID of currently processed interaction.
The benefit of this approach is that you can decide where and how your data is stored. The downside is extra work of implementing and maintaining this data storage.