I have used database denormalization in Firestore. User can easily sort his friends by his name/letters without an issue. Moreover, User can see “friends of friends” unless friend disabled the visibility setting.
User(collection)
->User ID(Doc) -> Name: Name0
-> visibility: true
-> Friends (sub-collection)
->Friend1 ID (Doc) -> Name: friend1Name
-> visibility: true
->Friend2 ID (Doc) -> Name: friend2Name
-> visibility: true
->Friend3 ID (Doc) -> Name: friend3Name
-> visibility: false
->...
->User ID(Doc) -> ...
This structure has borned two issues, when User wanted to sort his friends of friends by the name/letters, he needs to call Friends (sub-collection) of his all friends to make successful sorting. So, the number of call directly based on the number of his friends.
Secondly, when User has changed his visibility setting, it is required to update the visibility of the denormalized data where he is registered inside Friend’s sub-collections. Therefore, if you trigger it from "Cloud Functions", the number of document call directly depending on the number of User’s friends. The cost is open ended for both issues above.
I will be glad if there is an alternative costless structure to cope with those issues in Firestore.