I'm trying to retrieve value in 'expireDate' from products which belongs for current user (User has a reference to a product). I'm using Flutter and Firebase Cloud - Database.
FirebaseUser user = await FirebaseAuth.instance.currentUser();
String product = 'exampleId';
Firestore.instance
.collection('users/${user.uid}/products')
.snapshots()
.listen((snapshot) {
snapshot.documents.forEach((document) {
print(document.data['idProduct'].path);
print(document.data['idProduct']);
});
});
Program returns: 'Instance of 'DocumentReference'
I expect '2020-05-02'
Loading a document with a field that is a DocumentReference does not automatically load the linked document. You'll need to load the reference document explicitly, and then look up the expireDate field that you're looking for.
So something like
Firestore.instance
.collection('users/${user.uid}/products')
.snapshots()
.listen((snapshot) {
snapshot.documents.forEach((document) {
Document product = await document.data['idProduct'].get();
print(product.data['expireDate']);
});
});
Related
I am trying to get all documents where the length of the "users" array is less than 2 and where the userId is not present already. I am doing the following query, but it is not executing correctly. What is the problem and how can I fix it? I just want all documents where there is only one entry in the array "users" and where the array does NOT contain the current userId.
await FirebaseFirestore.instance
.collection('rooms')
.where("users"[0], isNotEqualTo: userId)
.where('users'[1], isEqualTo: null)
.get()
.then((snapshot) async {
// If no empty room is found, create room
if (snapshot.docs.isEmpty) {
print("No empty room found, creating new room");
roomId = await createRoom(userId);
return roomId;
}
You can't query individual array elements in Firestore. You can only check whether an array contains a specific item.
It sounds like your array items have a specific meaning, in which case you should create (nested) fields that indicate/name the roles. For example:
participants: {
creator: "uid1",
receiver: "uid2"
}
With that you can then query the nested fields with dot notation:
.where("participants.creator", "!=", "uid1")
.where("participants.receiver", "==", null)
Keep in mind there that the participants.receiver field still has to exist in the latter case and have a value of null. Firestore can't filter in fields that don't exist.
I'm creating a post that uploads data to Firestore's sub-collection and brings it up to MyBookmark page. It's good to create a sub-collection and upload data simply. And now I'd like to add a 'data duplication prevention' function here.
If the post is already saved in the bookmark, should not upload it.
For this purpose, I would like to check if the post is already in the collection when I press the bookmark button.
IconButton(
onPressed: () async {
//get userModel
UserModelState _userModelstate =
Provider.of<UserModelState>(context, listen: false);
//=========================================
//duplication data test
DocumentReference bookmarkRef = Firestore.instance
.collection(COLLECTION_USERS)
.document(_userModelstate.userModel.userKey)
.collection(COLLECTION_BOOKMARk)
// .where(KEY_BOOKMARK_PRODUCTKEY, isEqualTo: productKey)
.document();
DocumentSnapshot bookmarkSnapshot = await bookmarkRef.get();
//test (return "No exist")
if(bookmarkSnapshot.exists) {
print("Yes exist");
} else {
print("No exist");
}
I tried writing a code to check if there was data in the collection, but it is always printed as "No exist".
How can I confirm the existence of a specific document in collection?
Thank you.
If the productKey is supposed to be unique in the Bookmark collection of the user, consider using the productKey as the document ID. Since document IDs are by definition unique within their collection, using them guarantees unique product keys without you having to write any code for it.
That said, you current code can't work because you call document(). Whenever you call document() without any parameters, it generates a reference to a new unique document. And since you immediately call get() on that reference, the document will (also: by definition) not exist yet.
To check if a document with a specific product ID exist, you will need to run a query:
CollectionReference bookmarksRef = Firestore.instance
.collection(COLLECTION_USERS)
.document(_userModelstate.userModel.userKey)
.collection(COLLECTION_BOOKMARk);
Query bookmarkQuery = bookmarksRef.where(KEY_BOOKMARK_PRODUCTKEY, isEqualTo: productKey);
QuerySnapshot bookmarkSnapshot = await bookmarkQuery.get();
if (bookmarkSnapshot.size > 0) {
print("product key already in use");
}
I have my firestore collection structure as shown in the image.
Following is the main collection name which contains currently logged userId as a document ("AuScbj..")
which contains a subcollection called uIds which contains the user ids of users he follows.
When logged in user ("AuScbj..") visits a particular user profile, how can I check whether that profile user's Id available in his following list just by querying like below
firebaseFirestore.collection("Following)
.document(FirebaseAuth.getInstance().getCurrentUser().getUid())
.collection("uIds").where(
You're looking for .where(fieldPath: "uids", opStr: "array-contains", value: followingUID). It should work with your simple "array" data.
To check if id1 is present inside the uIds array in a really simpler manner, first, you should create a class:
class Document {
List<String> uIds;
}
Then get the "AUScbTj5MpNY.." document and read the content of the uIds array using the following method:
private void checkId(String id) {
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference followingRef = rootRef.collection("Following");
DocumentReference uidRef = followingRef.document(uid);
uidRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
List<String> uIds = document.toObject(Document.class).uIds;
if (uIds.contains(id)) {
//Update the UI
}
} else {
Log.d(TAG, "No such document");
}
} else {
Log.d(TAG, "get failed with ", task.getException());
}
}
});
}
Inside the onComplete, we get the array as a List and check if the id with which we are calling the method, exists inside the array. To make it work, kick it off with:
checkId(id1);
Please also note that:
firebaseFirestore.collection("Following)
.document(FirebaseAuth.getInstance().getCurrentUser().getUid())
.collection("uIds").where(/* ... /*);
Will never work, as uIds is an array inside a document and not a collection.
You can also find more info, in the following article:
How to map an array of objects from Cloud Firestore to a List of objects?
I am trying to get and display my user's information when they are logged in. (i.e: name, email, phone)
I have tried multiple snippets i have found on youtube and on stack overflow but they have failed. Most tutorials use realtime Database, which is not what i am looking for.
I have also tried making a "users" object.
private void getData(){
FirebaseFirestore db = FirebaseFirestore.getInstance();
db.collection("users")
//.document(FirebaseAuth.getInstance().getCurrentUser().getUid())
.whereEqualTo("email:", FirebaseAuth.getInstance().getCurrentUser().getUid())
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (DocumentSnapshot document : task.getResult()) {
//Toast.makeText(getApplicationContext(),document.getId() +"==>" + document.getData(),Toast.LENGTH_LONG).show();
//Toast.makeText(getApplicationContext(),""+ document.get("Email") ,Toast.LENGTH_LONG).show();
nameEdt.setText((CharSequence) document.get("First Name"));
emailEdt.setText((CharSequence) document.get("Email"));
phoneEdt.setText((CharSequence) document.get("Phone"));
}
} else {
Toast.makeText(getApplicationContext(),"No such document",Toast.LENGTH_LONG).show();
}
}
});
}
Database Structure:
I understand that documents in firestore are not associated with users, but i dont know how to set my code up so that it only retrieves data from the user that is signed in* It works fine for newly created accounts, but if i were to log out and sign in with a different user it will not update the "account/user information".
In short, how would I access and display my database information from signed in users?
Additional Notes: I am using Email and Password for authentication
To access your user data stored in Firestore, it shouldn't be as complicated as you thought, there's no queries needed, you just need to fetch the documents corresponding to the user's uid, and fetch the specific fields or do whatever you need with them, like this:
db.collection("users").document(FirebaseAuth.getInstance().getCurrentUser().getUid())
.get().addOnCompleteListener(task -> {
if(task.isSuccessful() && task.getResult() != null){
String firstName = task.getResult().getString("First Name");
String email = task.getResult().getString("Email");
String phone = task.getResult().getString("Phone");
//other stuff
}else{
//deal with error
}
});
Original Answer:
User information is not stored in the Firestore database, they are associated with the Firebase Authentication which you set up for the log in. To retrieve the related user information, you need to use the related FirebaseAuth APIs. Use this to retrieve the current log in user:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
Then you can get the name and email with something like this:
String name = user.getDisplayName();
String email = user.getEmail();
For more information, refer to the documentation.
If FirebaseAuth doesn't resolve, that probably means you didn't follow the set up guides correctly and forgot to include the dependency in your gradle file:
implementation 'com.google.firebase:firebase-auth:17.0.0'
After a couple days head butting at trying to find a solution, i have found one that is able to retrieve user information from the database. However it is important to note that because my application is not holding a lot of data so this structure works for me.
So i was essentially on the right track, but with some lack of understanding of firebase i missed a few concepts.
private void getData(){
FirebaseFirestore db = FirebaseFirestore.getInstance();
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
final String current = user.getUid();//getting unique user id
db.collection("users")
.whereEqualTo("uId",current)//looks for the corresponding value with the field
// in the database
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (DocumentSnapshot document : task.getResult()) {
nameEdt.setText((CharSequence) document.get("firstName"));
emailEdt.setText((CharSequence) document.get("email"));
phoneEdt.setText((CharSequence) document.get("phone"));
// These values must exactly match the fields you have in your db
}
}
As mentioned before, documents do not associate with users, but you CAN link them together by creating a field in your db called "whatever your want" (i made mine uId). This is because firebase generates a unique id for each user when authenticated. By creating a field that holds that unique id you are able to retrieve the associated information in that collection.
How to create the field:
I created a "user" object that would grab the uid from my edit text. In my code, i passed the uid wherever i was creating/authenticating a new user/account.
FirebaseUser testUser = FirebaseAuth.getInstance().getCurrentUser(); //getting the current logged in users id
String userUid = testUser.getUid();
String uidInput = userUid;
User user = new User(firstNameInput,lastNameInput,uidInput);
db.collection("users").document(userUid)
.set(user)
.addOnSuccessListener(new OnSuccessListener<Void>() {
note: I believe you can also add it to your hash map if you have it done that way.
I am trying to create a query which only selects documents whose reference is equal to a given reference, using Java for Android development. A document which it would match contains the reference for the path "/users/someUser". I am creating the reference like so:
DocumentReference ref = mDatabase.document("users/someUser");
I have also tried:
DocumentReference ref = mDatabase.document("/users/someUser");
Then the query:
Query query = mDatabase.collection("myCollection").whereEqualTo("refField", ref).limit(10);
However, when I run the query and check the task.isSuccessful() in the onComplete method, it's not passing, i.e. it didn't work, whereas when I remove the .whereEqualTo(), it passes and the task's result isn't empty. How can I properly use .whereEqualTo() to check for all documents containing a specific reference?
An example of a document that should match my query would be:
/myCollection/GDpojS5koac2C7YlIqxS which contains the field:
refField: /users/someUser (value of type reference)
And an example of a document that should not match my query would be:
/myCollection/J5ZcVAMYU1nI5XZmh6Bv which contains the field:
refField: /users/wrongUser (value of type reference)
I think you need to add a get() method to run the query and add an onCompletionListener.
Something like this should work:
mDatabase.collection("myCollection")
.whereEqualTo("refField", ref)
.limit(10)
.get()
.addOnCompleteListener({task ->
if(task.isSuccessful){
val result = task.result
})
The above example is in kotlin, but i guess in java it is something similar
You need not to worry about the documents, if you create a query based on your fields then all the documents will be returned in the "QuerySnapshot" object,
for eg,
CollectionReference collectionReference = db.collection(FIRESTORE_USERS);
DocumentReference documentReference = collectionReference.document(userID);
CollectionReference notificationCollection = documentReference.collection(FIRESTORE_NOTIFICATIONS);
notificationCollection.whereEqualTo(USER_TYPE, userType)
.whereGreaterThanOrEqualTo(SEND_AT, calendar.getTime())
.get().addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot documentSnapshots) {
List<DocumentSnapshot> snapshotsList = documentSnapshots.getDocuments();
ArrayList<NotificationCollections> notificationCollectionsArrayList = new ArrayList<>();
for (DocumentSnapshot snapshot : snapshotsList) {
// each document having that particular field based on query
}
}});
in the above example I am fetching all those documents which match a particular user id and also having time greater than or equal to supplied time (time will not be used in your case)
I hope this helps...
Happy coding :)