My database is quite simple. A collection and inside, there are documents with user information, including their username.
(I am doing this in flutter and firestore).
What I want is to prevent two users from having the same username.
I am doing this to insert the data.
FirebaseFirestore.instance.collection('users').add({
'username': 'username',
'desc': 'some bio',
'fieldone': 'aaa',
'fieldtwo': 'bbb',
// other user info
});
And to consult the data of a user (by their username).
FirebaseFirestore.instance.collection('users').where('username', isEqualTo: 'username').get();
At the moment I insert the data, what can I do to verify that said username is already in the database?
So if the username already exists, return an error and don't let insert it. And if it doesn't exist yet, it can be inserted.
What query can help me for this?
I am new to firebase. :(. Thanks.
What query can help me for this?
This can't be accomplished by a single query. You will have to take the steps you outlined already in your question. You will have to first query for documents with that username, then only insert a new one if there were none found.
However, you should be aware that there is a race condition here. If two people are trying at the same time to add the same username, it's possible that they both end up adding a document.
The only way to ensure uniqueness in Firestore is using the document ID. You might want to consider using the ID of the document to store the username (or some version of it, like a hash) so that a race condition can never occur, and that you only have one document with that username.
See also:
Firestore unique index or unique constraint?
Cloud Firestore: Enforcing Unique User Names
Unique field in Firestore database + Flutter
firebase rule for unique property in firestore
As you can see, your issue has already been thoroughly discussed on Stack Overflow.
Related
I have the following data as shown in the image.
I want to make sure that the username field is unique. How can I enforce that? Bear in mind that my document id is already unique and I don't want to use my username as the document ID
There is no way to enforce unique values of fields in Firestore. The only uniqueness you can guarantee is the document IDs within a collection, so the solution is to create a new collection where the user names are used as document IDs.
This has been discussed a few times before, so I recommend checking out:
Firestore security rule to check if character username already exists
Check a document field for a specific value in Cloud Firestore
I want to make unique usernames in firebase/firestore, which shows some of the relevant security rules.
Cloud Firestore: Enforcing Unique User Names
Firestore unique index or unique constraint?, a more complete write-up with code and rules samples.
Cloud Firestore: Enforcing Unique User Names
I want to assign a unique but incremental document/record(a data entry, not Firebase document) number when user generates his/her document in the app.
The document number should be unique integer/long and will be visible on the generated PDF document of the user as Your document number : 1100xxxxxx. This last generate document's number will be stored separately so when a new user generated his/her document, this number can be easily picked, incremented and assigned to user.
This way I won't have to query the database again for the last generated number using sorting as
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
Query query = rootRef.collection("Users")
.orderBy("DocumentNo", Query.Direction.DESCENDING)
.limit(1);
Right now, I generate a user by assigning the user.uid to the Firebase document. The reason I want to ensure the uniqueness of generated certificate number is that it will be visible to user and multiple users will be hitting the server at the same time(same millisecond even).
Although, I've seen almost every similar answer but the answer I've found similar to what I was thinking is this. Also, this unanswered question is what I should do but it has problems too.
So, is there a way by which I can generate a unique document/record number to the user? Answer need not be in Flutter, I want the logic mainly.
If you want to increment a number every time something happens do:
document.ref.update({unique_value: FieldValue.increment(1)});
That number will be unique. It will work with multiple users hitting the server at the same time.
i have a simple question regarding if it's a good practice to use the uid of the FirebaseAuth-Service for relations in other collections as the document index. So on login I get the uid of the FirebaseUser. With that I create an user like so:
Now is that a good practice to use this uid as the index of another document somewhere in another collection like this:
Or is it more common to let the index be generated and add an uid field inside the document so that I can query it with 'uid' equal 'my_uid' for example?
I come from the SQL-side and I don't have that much experience about NoSQL and how to sturcture it well. It would be great if someone could give me an advice here.
This is not a problem at all to reuse the same document ID in different collections, whether this id is a user uid (from Auth) or any other value (including an auto generated Firestore id).
Or is it more common to let the index be generated and add an uid
field inside the document so that I can query it with 'uid' equal
'my_uid' for example?
This is also a common approach, which can be interesting for example if you don't want to display the value of a Firestore document id (for example in an an url like https://www.whatever.com/players/-useruid- or https://www.whatever.com/players/-playername-).
Note however that this can generate some "tricky" side effects: for example if you want to avoid having two user profiles with the same user_name, in order to check that into a Transaction, you need to use the user_name as the id of the documents, since, with the Client SDKs it is not possible to execute a query within a Transaction (you need to define a DocumentReference to pass to the Transaction's get() method).
I'd like my web app router slugs to correspond to my Firestore documents data.
For example:
www.mysite.com/restaurants/burger-king
/restaurants <- Firestore Collection
/restaurants/mcdonalds <- Firestore Document
/restaurants/burger-king <- Firestore Document
This is easy enough, as I can assign the name as a slug-friendly UID in Firestore. The difficulty arises with CRUD functionality. I need to be able to rename my item titles, but Firestore does not permit you to rename indexes, which is the issue I'm facing.
One SO solution I saw was to delete the old record and creates a new one at the updated index. That's problematic for me, because sub-collections would be hard to transfer from the client side.
Are there more elegant solutions?
You don't have to identify a document by its ID. If you're able to ensure uniqueness of a document field value, you could instead query a collection for an ID value in a known field, then use the results of that query to satisfy your REST API. Then, you can change the value of that document field as often as you want, in order to satisfy required changes to the public API.
I'm playing around with the new Firestore database from Firebase and was wondering if there was a more efficient way to enforce unique usernames (or unique child nodes).
I use email/password auth but allow users to create a unique handle, like Twitter.
With the Realtime database I was able to achieve this with transactions and a multiple node structure.
-users
-uid1234:
-username: ryan
-usernames:
-ryan: uid1234
I was thinking it may be possible to do this without the extra usernames node using documents as the username in Firestore.
You could do it probably do it in 2 ways. Check with a separate call before create user, if the user exist in an collection with usernames.
Also you could create a rule like:
match /users/{document=**} {
allow create: if !exists(/databases/$(database)/documents/usernames/$(request.resource.data.username));
}
In that case you get a error back if the username already exist on creating and that you can catch in the code.