1

I'm working on a front-end application where I need to display a list of projects for a user. Each project contains a lot of data.

For my list view, I'm aiming to:

  1. Fetch only essential metadata for each project, enough to identify the project to the user.
  2. Avoid loading the full data for all projects initially to ensure faster loading and to save on bandwidth.

Then, when a user clicks on a specific project from the list:

  1. I want to fetch the complete detailed data for that single project.

I'm using Firebase Firestore as my database.

My idea is to add a subcollection with one document with the detailed data:

projects (collection)
|
|-- projectId1 (document)
|   |-- title
|   |-- description
|   |-- createdDate
|   |
|   |-- details (sub-collection)
|       |
|       |-- detailId1 (document)
|           |-- fullDescription
|           |-- images
|           |-- ...
|
|-- projectId2 (document)
...

Has anyone implemented a similar pattern? What's the best approach to achieve this? Any suggestions or best practices would be much appreciated!

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
Lars Flieger
  • 2,421
  • 1
  • 12
  • 34

2 Answers2

3

As Alex has explained in his question, with the Client SDKs it is not possible to get only a subset of the fields for a Document. When you fetch a Document you get it with all its fields (it is the same when fetching a collection).

But getting only a subset of the fields for a Document is possible with the Firestore REST API: With the REST API you can use a Projection when fetching a collection. In the payload you pass to the API call you list the documents' fields to be returned.

Parsing the result of the API call (JSON) is not as easy as getting the data from the Client SDK but for few fields it's worth it, since you don't need to denormalize your data.

So, if the number of fields representing the "essential metadata" is not very high (more or less around 5 fields) this solution is very interesting for fetching the "list view". Then, when you want to fetch a specific Project document, you can use the client SDK.


Concretely you need to use the runQuery method and pass as payload a StructuredQuery with the following format:

{
  "select": {
          fields: [
            {
              fieldPath: "title",
            },
            {
              fieldPath: "description",
            },
            // ...
          ],
        },
  "from": [
          {
            collectionId: "projects",
          },
        ],
  "where": {  // Optional
    object (Filter)
  },
  "orderBy": [   // Optional

    {
      object (Order)
    }
  ],
  "startAt": {    // Optional

    object (Cursor)
  },
  "endAt": {    // Optional
    object (Cursor)
  },
  "offset": integer,    // Optional
  "limit": integer   // Optional
}
Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121
2
  1. Fetch only essential metadata for each project, enough to identify the project to the user.
  1. Avoid loading the full data for all projects initially to ensure faster loading and to save on bandwidth.

These are common practices. It's best to download only the data that you're interested in. Unfortunately, there is no way you can only read some fields of a document with the client SDKs for mobile or web. It's the entire document or nothing. So in such a case, you should denormalize the data. This means that you can have in a collection lighter versions of the document and in another one the full versions. So you have to display a list of light objects, as Cloud Firestore is optimized for storing large collections of small documents, and on the click, perform another request and get the full object.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • But nothing speaks against the solution of a subcollection containing a single document with further details right? – Branchverse Aug 21 '23 at 10:34
  • 1
    @Branchverse That's correct. In the NoSQL world, [there is no perfect database schema](https://stackoverflow.com/questions/53053768/what-is-the-correct-way-to-structure-this-kind-of-data-in-firestore). So the solution is to always choose a schema that can be queried at lower costs. – Alex Mamo Aug 21 '23 at 10:37
  • That i do understand, was wondering if there was like a performance or storage difference on firebase site if u either denormalize or use a single document subcollection – Branchverse Aug 21 '23 at 10:39
  • In terms of speed, no. That's because Firestore speed depends on the number of documents you return and not on the number of documents you search in. – Alex Mamo Aug 21 '23 at 10:41
  • Hey there. Did my answer help? Can I help you with other information? – Alex Mamo Aug 25 '23 at 06:24