1

I'm creating a firestore document that's not at the root level of an existing collection but somewhat deeper:

  const response = await addDoc(
    collection(
      firestore,
      'stats',    //collection
      'dayStats', //document
      'years',    //collection
      '2023',     //document
     'january',  //collection
    ),
      statData
  );

At the time of creation, the entire collection structure does not yet exist, but only a part of it (stats/dayStats/years).

What ends up happening is that stat document is successfully created in the correct place, but not the intermediary documents. They are in italics and there's a warning for them saying "This document does not exist, it will not appear in queries or snapshots".

I suppose this means that I need to be explicit about force creating these intermediary documents? Is there some kind of a config I can pass to the function, that would just create the intermediary documents in the path, if they to not yet exist? Or do I need to do this by hand each time I'm creating a document, that has a ancestor document that might not exist?

enter image description here

Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121
Damjan Vučina
  • 352
  • 2
  • 12

1 Answers1

1

The intermediary documents are in italics and there's a warning for them saying "This document does not exist, it will not appear in queries or snapshots". I suppose this means that I need to be explicit about force creating these intermediary documents?

Indeed the intermediary parent documents don't exist and you need to create them if you want to store some data in these documents. If, on the other hand, you don’t need to store any data in the intermediary docs you don’t need to create them as they are not needed at all for your sub-sub-collections to exist.

Is there some kind of a config I can pass to the function, that would just create the intermediary documents in the path, if they to not yet exist?

No

Do I need to do this by hand each time I'm creating a document, that has a ancestor document that might not exist?

Yes you need, in your code, to create the parent documents if you want to store some data in these documents. The best is to use a Batched Write which ensures that both the parent and children docs are created via an atomic operation.

For example:

import { writeBatch, doc } from "firebase/firestore";

const batch = writeBatch(firestore);

const ref1 = doc(firestore, "stats", "dayStats");
batch.set(ref1, {...});

const ref2 = doc(ref1, "years", "2023");
batch.set(ref2, {...});

const ref3 = doc(ref2, "january"); // DocID will be auto-generated
batch.set(ref3, statData);

await batch.commit();
Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121
  • @Renauld thanks for the detailed comment. Follow up question if I may, is there a use case where anyone might actually want this behaviour, where intermediary documents are not created under the hood. I understand you want users to be explicit about which documents they want created, but having everyone create intermediary docs by hand also doesn't seem ideal? Or am I missing something? – Damjan Vučina Feb 19 '23 at 20:03
  • Hi @DamjanVučina. I understand your point but, since one need for each document creation to define one or more fields values as well as a path, having a dedicated method would not make a huge difference in terms of workload compare to the code in my answer. – Renaud Tarnec Feb 20 '23 at 08:43
  • @RenauldTarnec Say I have a collection of events structured as events/{year}/months/{month}/document. Depending on the startTime attribute of the event that is created, I place the newly created document in the corresponding subcollection. Say start time is sometime in March '23. Are you really telling me that before each and every insert, I need to query whether a doc with id 2023 exists, if not, then create it, then check whether doc with id 3 exists, if not, then create it. That's so many unnecessary requests, and is a huge red flag for using deep collections, right? Should be in docs. – Damjan Vučina Mar 01 '23 at 19:28
  • You don’t need to create the intermediary documents. You would create them ONLY if you want to store data in these documents. You wrote in your question: "Is there some kind of a config I can pass to the function, that would just create the intermediary documents in the path, if they to not yet exist?" so I understood that you WANT to create these docs. If they aren’t necessary don’t create them it’s fine like that. Also if my answer solves your problem please upvote and accept it. Thx – Renaud Tarnec Mar 01 '23 at 19:30
  • @RenauldTarnac Forgive me but I are you sure about "You would create them ONLY if you want to store data in these documents.". I think you also need to create them if you want to read their parent collection, otherwise they don't show up. E.g. per example above, getting all docs in events collection returns [], but should return e.g. [2022, 2023]. This is because year docs are intermediaries, even though they do not store data. How do I make years show up in the array efficiently? This is the issue that I would like to solve and then accept the question. – Damjan Vučina Mar 01 '23 at 19:44
  • As I told you: Either you don’t need to store any data in the intermediary docs and you don’t create them as they are not needed for your sub-sub-collections to exist. Or you do need to store data in those documents and you need to create them. There isn’t any other alternative. – Renaud Tarnec Mar 01 '23 at 19:46
  • You may be interested by reading the "One key point to note" section of this answer: https://stackoverflow.com/a/61658557/3371862 – Renaud Tarnec Mar 01 '23 at 19:48
  • Thank you for the link. I'm really sorry but that doesn't answer my example from the last question, regarding getting all existing years. Do you want me to accept this answer, and post a new more specific question? – Damjan Vučina Mar 01 '23 at 19:53
  • Actually you never mentioned that you want to get the intermediary years in your initial question. So in my opinion my answer correctly answers your question. If you want to be able to get all existing years you should probably write a new question with all the possible details because there are several ways to do what you are looking for. – Renaud Tarnec Mar 01 '23 at 19:57
  • 1
    Thank you and sorry for not being specific enough – Damjan Vučina Mar 01 '23 at 19:59
  • https://stackoverflow.com/questions/75608617/firestore-efficiently-inserting-documents-in-subcollections – Damjan Vučina Mar 01 '23 at 20:34