7

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.

Scott Dietrich
  • 686
  • 1
  • 8
  • 20

2 Answers2

11

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.

HughHughTeotl
  • 5,439
  • 3
  • 34
  • 49
  • Doesn't this defeat the purpose of the query? If I know the full path to the document, then why would I need to query across all subcollections for it? This feels like a bug on the Firestore side of things... – joelpoloney Nov 12 '19 at 22:52
  • Well yes, it's not perfect! Perhaps I misunderstood though, but I don't see why this defeats the purpose of the query? You don't have to put the full document path as a value in the document - just the specific thing you want to search on. – HughHughTeotl Nov 13 '19 at 23:58
  • 1
    It was more of a comment on Firestore not supporting the use-case. I talked with the support team and with members from Firebase and we came up with the best way to do this is to duplicate the ID into the actual data fields for the objects themselves. This way you don't have to rely on `FieldPath.documentId()` and can query on `id` (after you index it). – joelpoloney Nov 14 '19 at 04:20
  • This should be the accepted answer. – Johnny Oshika Mar 07 '21 at 18:41
1

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.

Johnny Oshika
  • 54,741
  • 40
  • 181
  • 275
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Wouldn't it be: `db.collectionGroup('invites').where(firebase.firestore.FieldPath.documentId(), '==', someEmailVar).get()` – Scott Dietrich Jul 10 '19 at 22:48
  • Yes, if you want to use a collection group query on the `invites` collection. Does it work this way? – Alex Mamo Jul 11 '19 at 08:15
  • 1
    Yes. I am trying to get at `invites`. As to whether I got it to work, not yet. I ran the query and then got an error complaining about "collection references need an odd number of segments". I understand that this error is all about the alternating collection/document structure. However, I'm not sure why it is happening in this instance. Maybe it has something to do with using email as a key. The docs say you shouldn't have a "." in the document key. However, I've seen several answers on SO recommend using email as a key. – Scott Dietrich Jul 11 '19 at 15:50
  • You can use the email address as a key, there is no problem with that. That error usually appears when you pass to a `collection()` or `document()` function a wrong number of segments. Be sure that all segments are not null or empty. For testing purposes, try to hardcode them and see if it works and please get back to me. – Alex Mamo Jul 11 '19 at 15:54
  • Here is the docs link I was reading about document ids. Maybe I'm not reading it correctly: https://firebase.google.com/docs/firestore/quotas#collections_documents_and_fields – Scott Dietrich Jul 11 '19 at 16:24
  • Have you tried to hardcode the values inside the reference and see if it works? Can you conform that please? – Alex Mamo Jul 11 '19 at 16:35
  • 7
    This method won't work because `FieldPath.documentId()` refers to the entire, fully qualified path. Have posted an answer below. – HughHughTeotl Oct 21 '19 at 17:27
  • 1
    As @HughHughTeotl mentioned, this won't work. The way to get this to work is to provide a fully qualified path of the ID (e.g. `firebase.firestore.FieldPath.documentId(), '==', 'teams/teamId'`), which defeats the purpose of collection group queries. It's best to include the id in a property of the document so that the query can be done properly. – Johnny Oshika Mar 07 '21 at 18:41
  • 1
    @JohnnyOshika Yes, you're right. I just updated my answer. Thank you, Johnny. – Alex Mamo Mar 19 '21 at 15:58