Is it possible to query collectionGroup on a specific collection? [duplicate] - firebase

This question already has answers here:
collectionGroup within a certain path
(2 answers)
Closed 3 years ago.
I have a user collection, and within that collection there's a collection name groups, which then has groupItems. Is it possible to run a query for all groupItems for a specific user?
I could run a global version like:
db.collectionGroup('groupItems')
but that is overkill for me, I'm looking for something like:
db.collection('users').doc(uid).collection('groups').collectionGroup('groupIems').where('categoryOnly', '==', true)
Is this possible?
The architecture of the collections looks like this:
Users
---> User
------> Collections
---------> GroupA
------------> GroupAItems
---------------> GroupAItem1
---------------> GroupAItem2
---------> GroupB
------------> GroupBItems
---------------> GroupBItem1
---------------> GroupBItem2
Ideally I could call for all Group Items instead of first calling for groups and getting [GroupA, GroupB...], and then calling for GroupA's items, then GroupB's, etc.

Update: it turns out that querying a specific path may be possible after all, thanks to how FieldPath.documentId() is indexed for collection group indexes. Check #samthecodingman's answer here: https://stackoverflow.com/a/68049847
Happy answer above 👆
Old answer below 👇
There is currently no way to limit a collection group to just collections under a specific path. All collection group queries get documents from all collections with the specified name.
So the only way to currently query a subset of your groups is to use a naming scheme that allows you to uniquely address them.
Also see:
Does collection group queries get data from all collections with the same name?
collectionGroup within a certain path

Related

Select a matching element from a dataset with multiple conditions and inputs - programming [duplicate]

This question already has answers here:
Query based on multiple where clauses in Firebase
(8 answers)
Closed last year.
I'm using FirebaseRecyclerAdapter and pass FirebaseRecyclerOptions with some query into constructor. Each item has number of fields including timestamp a and another integer field b. So I want items with older a but less b to be on top of list. It's easy to implement with sqlite, but not so easy with nosql. It seems I need to add some extra field which keeps both fields:
String.valueOf(a) + String.valueOf(b) but how to achieve asc / desc properties?
Loading the whole list and sorting in Java is not an option.
Unfortunately, Firebase Realtime database does not support queries on multiple properties, supports only queries on a single child property. So, you're correct in guessing that you'll need to create an extra field to keep both fields. So to achieve this, you need to create a new field which in your database should look like this:
Firebase-root
|
--- itemId
|
--- a: valueOfA
|
--- b: valueOfB
|
--- a_b: valueOfA_valueOfB
So as you see, the a_b property combines the values that you want to filter on.
Unlike Firebase Realtime database, Cloud Firestore allows compound queries. You should take a look at this. So a query as the one below is allowed in Cloud Firestore without creating a combined property.
itemIdRef.whereEqualTo("a", "valueOfA").whereEqualTo("b", "valueOfB");
When you order strings this is the normal ordering method. A quick fix would be to add two zeros before each second element like this: "1516428687_001", "1516428687_002", "1516428687_012". Now your order will be fine. For more explanations, please see my answer from this post.

Firestore: Wherein custom object array?

im trying to make a sort of chat app with the following architecture:
Its currently working as follows: in a root doc, there is an array of chat objects. Each chat object spawns a message doc, which contains an array of message objects. Same logic for comments.
Im thinking about a function to update all posts relative to the associated user, IE if a user changes their name all associated comments will be updated. Is this possible with the WhereIn() function? Or should i edit the architecture to something more like each document being its own message/comment? Thanks!
An in clause checks if a specific field is equal to one of a set of values, which doesn't apply here.
You might be thinking of array-contains, but that wouldn't work in your current structure either. The array-contains only matches exact an item in the array if it completely/exactly matches the value in the query.
The common way to allow such a query is to add a participants array field to each document where you store the UIDs of all participants in that doc. Then you can do an array-contains query against that.

Firebase getting a list of documents [duplicate]

This question already has answers here:
Google Firestore - How to get several documents by multiple ids in one round-trip?
(17 answers)
Closed 8 months ago.
In Firestore, if I have as list of, say, 20 document IDs, what is the best way to fetch all those documents?
I'm thinking of, for example, using something like Angolia for search and getting a list of ids back from it.
Would I need to manually get or onSnaptshot each reference, or is there a more performant/simple way to fetch a list of documents just using their ID?
Thanks!
A lot of the options depends on how your firestore is structured, and what framework you're using to encorporate firebase.
Generally speaking, querying a list can be done using the in query operator.
In the case of id querying, the array is id's, and you query by firebase.firestore.FieldPath.documentId()
import { query, where } from "firebase/firestore";
const q = query(firebase.firestore.FieldPath.documentId(), where('id', 'in', ['SOME_ID_1', 'SOME_ID_2']));

When I use DataSnapshot with if else then it shows null value instead of original value, why? [duplicate]

This question already has answers here:
Query based on multiple where clauses in Firebase
(8 answers)
Closed last year.
I'm using FirebaseRecyclerAdapter and pass FirebaseRecyclerOptions with some query into constructor. Each item has number of fields including timestamp a and another integer field b. So I want items with older a but less b to be on top of list. It's easy to implement with sqlite, but not so easy with nosql. It seems I need to add some extra field which keeps both fields:
String.valueOf(a) + String.valueOf(b) but how to achieve asc / desc properties?
Loading the whole list and sorting in Java is not an option.
Unfortunately, Firebase Realtime database does not support queries on multiple properties, supports only queries on a single child property. So, you're correct in guessing that you'll need to create an extra field to keep both fields. So to achieve this, you need to create a new field which in your database should look like this:
Firebase-root
|
--- itemId
|
--- a: valueOfA
|
--- b: valueOfB
|
--- a_b: valueOfA_valueOfB
So as you see, the a_b property combines the values that you want to filter on.
Unlike Firebase Realtime database, Cloud Firestore allows compound queries. You should take a look at this. So a query as the one below is allowed in Cloud Firestore without creating a combined property.
itemIdRef.whereEqualTo("a", "valueOfA").whereEqualTo("b", "valueOfB");
When you order strings this is the normal ordering method. A quick fix would be to add two zeros before each second element like this: "1516428687_001", "1516428687_002", "1516428687_012". Now your order will be fine. For more explanations, please see my answer from this post.

Firebase Collection Group Query on Id / Key [duplicate]

This question already has an answer here:
How to perform collection group query using document ID in Cloud Firestore
(1 answer)
Closed 2 years ago.
I have been following along the following document:
https://firebase.google.com/docs/firestore/query-data/queries#collection-group-query
My data structure roughly looks like this:
/teams/{teamid}
{
displayName: "Company X Team",
owner: "userid",
}
/teams/{teamid}/invites/{emailAddressAsKey}
{
someProp: "my data"
}
In my web app I want to search through all the different teams records to find an invite who's id/key is equal to the email address that I pass in. After reading through the documentation, I think a Collection Group Query is what I'm looking for. However, my situation doesn't exactly match the example. I want to match on the key, not a prop within the document. I suppose I could add the email address again as a prop, but that doesn't feel right.
You have to put the document ID as a key in the document itself. There is currently no other solution.
It's tempting to use FieldPath.documentId() in a where clause (eg following Alex Mamo's answer https://stackoverflow.com/a/56967352/2518722), but that doesn't work in the general case. The reason is that FieldPath.documentId() actually refers to the full, unique ID of the document including its path.
If you do try this you'll get the following error:
Error: When querying a collection group and ordering by
FieldPath.documentId(), the corresponding value must result in a valid
document path, but '<your doc id>' is not because it contains an odd
number of segments.
Basically the where clause only works with searches on keys/values not document IDs.
You can solve this with the help of FieldPath.documentId() like in the following line of code:
db.collectionGroup('teams').where(firebase.firestore.FieldPath.documentId(), '==', 'teams/teamId').get()
This query will return all documents with a specific team id.

Resources