I really can't find how to do it, how do I get in my RecyclerView all the values of a certain department.
First things first, is it even possible?
This is how my Firestore database loos like this, "blue_bottle" and "tops_national" is part of a document:
I want to populate my RecyclerView with all products, both out of "blue_bottle" and "tops_national" with the same department.
So I need a DocumentReference which I believe is right:
private val promoOnedb = FirebaseFirestore.getInstance()
private val promoOneRef: DocumentReference = promoOnedb.collection("tops")
.document("promotions")
But how do I query that DocumentReference now to show all products, in both collections to show all products of the same department? Please.
The only way in Firestore to read across multiple collections is with a collection group query, which reads from all collections with a specific name.
o with a single collection group query you can read from all blue_bottle collections or all tops_national collections. There is no feature in Firestore however to read from all blue_bottle collections and all tops_national collections with a single operation. You will need at least two (collection group) queries for that, and thus merge the results from those in your application code.
If you want to read all products with a single operation, they will need to be stored in collections of the same name, like products. Only then can you use a single collection group query to read them all in one go.
Related
In firestore I have some sub-collections inside each collection just like below:
Collection1 -> id -> Sub-collection -> scId -> Data
So here I want to get all data from sub-collections by the help of the where clause. I tried one query like the below which is failing.
db.collection("Collection1").whereEqualTo("eDate", selectedDate)
.get().addOnSuccessListener(queryDocumentSnapshots -> {
List<Exp> mData = queryDocumentSnapshots.toObjects(Exp.class);
Here eDate is coming under the Data which is inside each sub-collection.
So is there any way to do that or any suggestions on how to do that or about the mistakes which I did here?
Firestore queries are shallow and do not extend above or below the named collection being queried. The query you show here will only return documents immediately within "Collection1". It will not consider any documents in nested subcollections.
If you want documents in a subcollection, you will have to build a CollectionReference to that subcollection, and query it individually. You can't query all subcollection nested under a document at the same time. You can't query across differently-named subcollections at the same time.
If this behavior does not meet the needs of your app, you should consider restructuring your data to do so, or building your app to perform as many queries as needed to get all the documents from among all the collections where they live.
I've been trying to find a query for almost 2 days now
I want to search id (current user id) from the document 4 fields (customer1,customer2,customer3,customer4)
Here is the firestore document picture
tried this query
final Query userQuery = collectionReference
.whereEqualTo("customer1",firebaseAuth.getInstance().getCurrentUser().getUid())
.whereEqualTo("customer2",firebaseAuth.getInstance().getCurrentUser().getUid())
.whereEqualTo("customer3",firebaseAuth.getInstance().getCurrentUser().getUid())
.whereEqualTo("customer4",firebaseAuth.getInstance().getCurrentUser().getUid());
but this only shows up if the current ID is present in all 4. Is there any easier way to do this.
You can do that by using a field that is an array containing the uids you want to test, and then applying array-contains on it. In your case:
In your case:
customer: [customer1, customer2, customer3, customer4]
collectionReference
.where("customer ", "array-contains", firebaseAuth.getInstance().getCurrentUser().getUid())
Firestore does not support logical OR queries among mulitple fields. So, what you're trying to do is not possible with a single query using the database structure you have now. You would have to perform multiple queries and merge the results in the client.
If you want to be able to use a single query, you will have to change your database. One option is to put all the customers into a single array field and use an array-contains query to find a customer in that field.
I am trying to show to user items, he participated in (for example liked posts). Now I store in user document (in users collection) IDs of documents from another collection (posts) and when I want to show them in recycler view firstly I get IDs from user document. Then I get all posts by IDs. Is there any workaround, where I would be able to store user ID in subcollection of post document and then get query of all liked/commented/whatever posts by user? So user document will not have reference to post's IDs and in posts collection I am able to do something like:
Query ref = from db.collection("posts") get all posts where post.likedBy == user;
I do no like idea of putting all users who liked the post into post document - user downloads all ids.
posts (collection)
-postID (post document)
-authorID, ... (fields)
users (collections)
-userID (user document)
-string[] idsOfPosts (fields)
You should use Subcollections as your data model.
Documents in subcollections can contain subcollections as well,
allowing you to further nest data. You can nest data up to 100 levels
deep.
Also you can use a collection group query to retrieve documents from a collection group instead of from a single collection. The link provides you with sample code snippets in different languages.
EDIT:
Based on the use case you have provided in the comments:
I would say the way you are describing your data model to get all posts liked by a user, it would need a query inside a query. Not sure if it's even feasible or efficient.
Here is my suggestion:
Build your data model similar to the following
This way running the following query (I'm using NodeJs) would give you all posts liked by user1.
let postsRef = db.collection('posts');
const user1 = postsRef.where('Liked', 'array-contains',
'user1');
let query1 = user1.get()
.then(snapshot => {
if (snapshot.empty) {
console.log('No matching documents.');
return;
}
snapshot.forEach(doc => {
console.log(doc.id, '=>', doc.data());
});
})
.catch(err => {
console.log('Error getting documents', err);
});
Output:
EDIT: (11/12/2019)
Based on what you have described in the comments, here is an idea that might solve your issue:
Instead of having a list of the Users who liked the post, you can have a reference to a Document that contains the list of users. You can reference to as many Documents as you wish.
Example:
The Documents can be even in a different Collection.
I have a recyclerview using Firestore Recyclerview Adapter, Now I want to show the list by using OR query.
For example I want to show the list which are either in "Pending" state OR "Assigned" state using query. I know firestore doesn't have OR query inbuilt but I want to achieve this anyhow. Any alrernative solution.
I have stored 4 state in firestore db : Pending, Assigned, Accepted and Completed.
Only want to show pending or assigned
Below is my code:
Query query = requestVehiclesCollectionReference
.whereEqualTo("clientId", id)
// show list which are in Pending state or Assigned state
.whereEqualTo("status", "Pending")
.orderBy("createdAt", Query.Direction.DESCENDING);
FirestoreRecyclerOptions<Item> options = new
FirestoreRecyclerOptions.Builder<Item>()
.setQuery(query, Item.class)
.build();
Firestore doesn't support queries with OR conditions. See:
Implementing OR in firestore query - Firebase firestore
How to perform compound queries with logical OR in Cloud Firestore?
Firebase Firestore - OR query
The common workaround is to use multiple queries (one for each condition) and merge the results in your application code.
FirebaseUI's adapters show data from a single query or collection. They have no option to show the results from multiple queries/collections.
From this combination it follows that you can't show data from an OR condition with a single FirebaseUI adapter. You will have to create you own adapter for this, although you can certainly use the (open-source) FirebaseUI adapters for inspiration.
I have a users collection with uId, name, photo
I have a visits collection with uId, userId, location
I have a recyclerview in which I want to show the location with the user name and photo
Can I use the reference field type? If so, how will Firestore know to link visits.userId == users.uId ?
Maybe I first need to query all the visits and then query the relevant user but 2 things:
It means querying a lot of times.
I didn't understand how to collect the joined collection into the adapter, which is based on one query?
Please advice
Thanks
current code
visitsList = db.collection("visitsList");
Query query = visitsList.whereEqualTo("userId",prefs.getString("id","")).orderBy("visitDate", Query.Direction.ASCENDING);
FirestoreRecyclerOptions<AVisit> options = new FirestoreRecyclerOptions.Builder<AVisit>().setQuery(query, AVisit.class).build();
adapter = new VisitsListAdapter(options, VisitsListActivity.this);
RecyclerView rv = findViewById(R.id.rvVisitsList);
rv.setHasFixedSize(true);
rv.setLayoutManager(new LinearLayoutManager(this));
rv.setAdapter(adapter);
The code is a simple query from the collection, not sure how to get the name and photo from the userId field in that collection.
Can I use the reference field type?
Yes, you can use a reference field.
If so, how will Firestore know to link visits.userId == users.uId ?
Firestore results always comes from a single collection (at the moment). It does not automatically join the document from the users collection when you're reading from the visits collection. You will have to do this yourself.
That indeed means you'll be executing multiple reads, but it's often not nearly as slow as you may think. See Google Firestore - how to get document by multiple ids in one round trip?
Update: To show data from the user profile in a list of visits, there are two main options:
load the additional user document in populateView or with a custom parseSnapshot implementation.
duplicate the relevant user data in the visits collection (which is quite normal in NoSQL databases). Also see Alex' answer here: indexed query with FirestoreRecyclerAdapter.