Android Firestore id of empty document - android

How i can get id of empty document (document without field but contains collections)
for Example
public void getUsersLists(OnSuccessListener<List<String>> callback) {
storeCollection().get(getSource()).addOnCompleteListener(task -> {
if (task.isSuccessful()) {
QuerySnapshot result = task.getResult();
List<String> stringList = parseResult(result);
callback.onSuccess(stringList);
} else {
callback.onError(task.getException());
}
}).addOnFailureListener(callback::onError);
}
private List<String> parseResult(QuerySnapshot result) {
List<String> list = new ArrayList<>();
if (result != null) {
for (DocumentSnapshot snapshot : result.getDocuments()) { <<----documetns is zero
String name = snapshot.getId();
list.add(name);
}
}
return list;
}
private CollectionReference storeCollection() {
return firestore()
.collection(COLLECTION_DATA)
.document(AuthManager.getUserId())
.collection(COLLECTION_STORES);
}
COLLECTION_STORES contain empty document that contain other collections.
But i need to get the name/id of document, collection.getDocuments() return empty list, only after i add field via Firebase console the collection.getDocuments() returns the documents.
Is there a way to get the document name/id? or i must attach a field/object to document in this case?
I am understand that attaching object to this document can solve the issue, but it is also complicates the design.

You can't query for a document that doesn't exist. Firestore indexes used for querying work based on documents and fields that actually exist - an index can't work with things that don't exist.
If there are subcollections organized under a document ID that doesn't exist, you need to know the path of those subcollections in order to work with them, including the document ID. There is no way to programmatically discover them if you don't know the document ID where they're organized.

Related

Firestore to query Array sub collection

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?

Firebase Cloud Firestore Query whereEqualTo for reference

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 :)

Firestore whereEqualsTo from arraylist

I'm trying to list documents that matches field String value from ArrayList.
Simply:
I have ArrayList with tags stored at runtime
and documents with field tag
and I want to query documents that matches tag with one of tags stored in ArrayList. Is this possible with official query or does I have to download all documents and filter it client-side? Thanks for any answers.
Also, this is my method generating query:
public static Query getQueryForFollowed(DocumentSnapshot snapshots) {
if (snapshots == null || !snapshots.exists()) {
return FirebaseFirestore.getInstance().collection("posts").whereEqualTo("null", "null"); // return query that will get nothing
}
ArrayList<String> f = processFollowedTags(snapshots);
Query query = FirebaseFirestore.getInstance()
.collection("posts")
.whereEqualTo("tag", f.get(0));
for (int i = 1; i < f.size(); i++) {
query = query.whereEqualTo("tag", f.get(i));
}
return query;
}
I have debugged code and query has contained requested conditions, but query didn't found any document matching it.
Try This
Query query = FirebaseFirestore.getInstance()
.collection("posts")
.whereEqualTo("tag", f.get(0)).orderBy("tag", Query.Direction.ASCENDING);;
After some more search on Google I have found that querying field to multiple values is not available.
According to:
https://stackoverflow.com/a/46633294/8428193
https://github.com/firebase/firebase-js-sdk/issues/321
Below code snippet may help you.
fun arrayContainsQueries() {
// [START array_contains_filter]
val citiesRef = db.collection("cities")
citiesRef.whereArrayContains("regions", "west_coast")
// [END array_contains_filter]
}
ref : git
As of Nov 2019 this is now possible to do with the in query.
With the in query, you can query a specific field for multiple values
(up to 10) in a single query. You do this by passing a list containing
all the values you want to search for, and Cloud Firestore will match
any document whose field equals one of those values.
it would look like this:
Query query = FirebaseFirestore.getInstance()
.collection("posts")
.whereIn("tag", f);

Android Firestore query get the id of the document that contains the value in the search

Firestore database image
Hello, I just tried to use Firestore. I had some problem when getting document id.
The question is, I want to get a document id (red box) which has value (blue box) in it.
I use the following query:
collection("mychannel").whereEqualTo("74wRU4xHrcV9oWAXEkKeRNp41c53")
But did not give results.
Thanks!
As in the official documentation:
Although Cloud Firestore can store arrays, it does not support querying array members or updating single array elements.
So there is no way in which you can use the following query:
collection("mychannel").whereEqualTo("74wRU4xHrcV9oWAXEkKeRNp41c53")
If you only want to get the entire userId array you need to iterate over a Map like this:
collection("mychannel").document("1fReXb8pgQvJzFdzpkSy").get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
Map<String, Object> map = document.getData();
for (Map.Entry<String, Object> entry : map.entrySet()) {
if (entry.getKey().equals("userId")) {
Log.d("TAG", entry.getValue().toString());
}
}
}
}
}
});
But note, even if userId object is stored in the database as an array, entry.getValue() returns an ArrayList, not an array.
So the output will be:
[74wRU4xHrcV9oWAXEkKeRNp41c53]
A better approach will be if you consider this alternative database structure, where each user id is the key in a map and all values are true:
userId: {
"74wRU4xHrcV9oWAXEkKeRNp41c53": true,
"AdwF...": true,
"YsHs...": true
}
This question is answered here: Firestore: Query by item in array of document
In summary, don't use arrays to store data in Firestore as the query you are trying to do is not available yet (remember it is still in beta). You should use a Map instead.

How can i read ArrayLists within a document from Firestore cloud database?

I'm Trying to build a restaurant app using firestore to store the orders and the users.
I tried 2 methods, first one was to write the ArrayList of orders as a Array in firestore database, but coudn't read them afterwards...
I used DocumentSnapshot.toObject(myclassoflist.class) but this only worked with no array list in the document, only with values = ".."
Then I created a collection of documents (each document is an item) which contains the array as simple values
To understand this take a look at my database
Then, to read them i first get all the document ids
db.collection("orders").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (DocumentSnapshot document : task.getResult()) {
documentsIDs.add(document.getId());
}
Integer allIdsD = task.getResult().size();
if (allIdsD.equals(documentsIDs.size())) {
readDocs();
}
}
}
});
Then for each document id, i created 3 more db.collection(collection).get() in order to get the inside of each document within the subcollection, using again the function DocumentSnapshot.toObject(myclass.class).
The problem here is that it takes ~0.8 secs to get a complete order from the database, which is a lot considering there could be like 100+ orders per day
My project on GITHUB
Examples from: LimatexMM/app/src/main/java/g3org3/limatexmm/orders.java
EDIT:
I also tried to write the orders as follow:
orderListBig docData = new orderListBig(list, currentUser, adList, docId);
(list is ArrayList, currentUser, adList are objects)
db.collection("orderss").document(docId).set(docData)
and then read it with:
db.collection("orderss").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (DocumentSnapshot document : task.getResult()) {
orderListBig ahah = document.toObject(orderListBig.class);
allOrders.add(ahah); (ArrayList of ordersListBig)
an part of my order document
As per official documentation regarding the use of arrays in Cloud Firestore you need to know that:
Although Cloud Firestore can store arrays, it does not support querying array members or updating single array elements.
If you only want to get the entire orderList array and get the value of, let's say itemMore, you need to get the reference of that particular document and then iterate over a Map like this:
Map<String, Object> map = documentSnapshot.getData();
for (Map.Entry<String, Object> entry : map.entrySet()) {
if (entry.getKey().equals("itemMore")) {
Log.d("TAG", entry.getValue().toString());
}
}
But note, even if orderList object is stored in the database as an array, entry.getValue() returns an ArrayList, not an array.
I better approach for your use-case, would be if you consider this alternative database structure, where each item is the key in a map and all values are true:
orderList: {
"itemMore": true,
"itemMoreValue": true,
"itemMoreOtherValue": true
}
Bafta! ;)

Categories

Resources