4

I am trying to run the following query:

this.db.firestore
        .collectionGroup('members')
        .orderBy('dateModified', 'desc')
        .where(firebase.firestore.FieldPath.documentId(), '==', uid)

But I get the error:

Invalid query. When querying a collection group by FieldPath.documentId(), the value provided must result in a valid document path, but 'X6yL5Ko55jSMWhhoQUO91xVYdEH3' is not because it has an odd number of segments (1).

Is the only way around this to add the document id to the document? This is not ideal as I have a lot of existing data... The document id is the uid of the firebase user.

MadMac
  • 4,048
  • 6
  • 32
  • 69

2 Answers2

7

As the error message says, for an index on a collection group the documentId() field values are actually stored as document paths to ensure unique lookups of those values in the index.

If you want to also query on document ID over a collection group, you will indeed have to store the ID as a field value in each document.

Also keep in mind that it is then possible to get multiple documents for the query, even though that is astronomically unlikely if you use the built-in add() operation.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
4

Adding the uid to the document itself is the only possible way at the moment and then query on that field:

this.db.firestore
        .collectionGroup('members')
        .orderBy('dateModified', 'desc')
        .where("uid", '==', uid)

There was a Github issue for the same and explains why that's not possible.

That's pretty much why I sometimes prefer to store a root level collection members. Each document in the collection will have contain the groupID (or whatever your parent collection is meant for). If you use userID as the key for documents in there then it goes easy.

this.db.firestore.collection("members").doc(uid)

So instead of having a path like: /groups/{groupID}/members/{memberID}, the structure will be like: /groups/{groupID} and all the members will be store in the root level collection 'members'. A document in that collection may look like:

// uid as doc key
{
  groupId: "groupID", 
  ...otherFields
}

The catch is if a member can join multiple groups you cannot use the userId as the key.

Dharmaraj
  • 47,845
  • 8
  • 52
  • 84
  • 1
    Ah that is annoying as I didn't realise this limitation before I designed my datamodel. Luckily it is for users and I store the email in the document so I can use this rather than the uid/documentId. – MadMac Jul 26 '21 at 20:44
  • @Dharmaraj, I like the idea of members to be root collection.\ To mitigate the conflict member having multiple groups, the "groupId" property can also be treated as an array of groupIds.\ This way even querying will be possible and no limitations. – saurabh Aug 11 '22 at 13:18