7

For those of you who worked with Firebase (Firestore), then you can have a collection with documents in which each document has an id, then a collection can hold a sub collection (equivalent of an embedded document as an array of documents as a property).

Then, this sub collection can hold many documents while each has an id.

In Firestore the sub collection is lazy loaded.

It will fetch the documents on that collection, but if there is one or more sub collections, it won't retrieve it unless specifically going to that route. e.g: collection/document/subcollectionname/anotherdocument

So 2 questions:

  1. Are embedded documents lazy loaded? I don't want to get a document with all of its embedded documents (possibly a million) unless I explicitly access to it.
  2. How can I make sure each embedded document in MongoDB gets an "_id" in the form of ObjectID("blablabla")?

EDIT: I currently have a firestore implementation which has a subcollection/s practice behind it.

Example: organization => documentId => projects => projectId => activities => :activityType => activityId

  1. organization collection that holds documents (each document = organization).
  2. Each organization document holds a schema (id, name, language, etc..) and a few subcollections in which one of them is projects subcollection
  3. projects sub collection holds documents of projects.
  4. a project document holds the project schema (id, name, location, etc..) and one subcollection named activities.
  5. activities sub collection holds its own schema (id, type, category, etc...) and 6 more sub collections, each represents an activity type.
  6. each activity sub collection holds its own schema. No more sub collections.

Now, the good thing about it is that if I choose to get all organizations, then I will get only the documents of the organization collection and NOT the embedded subcollections (projects, etc..) while in MongoDB, I would get EVERYTHING per document.

How do I achieve the same nested documents with their own nested documents structure with the lazy load effect in MongoDB?

Joseph D
  • 73
  • 5
  • I've not used nested documents in MongoDB much but instead I'd convert the sub-collection into a collection. Let's say in Firestore you have `posts -> {postID} -> comments -> {commentID}` then in Mongo that comments being a collection on it's own and each doc in there containing the project ID. This will also prevent you from hitting 16 MB limit per documents. What is your use case? – Dharmaraj Jul 29 '21 at 11:23
  • I'll edit soon my use case. According to your approach, I'll always have root collections? What if I already have 60 existing collections in firestore with some of them doubly nested? How should I approach this? – Joseph D Jul 29 '21 at 11:30
  • If you could share what you have in Firestore currently then it'll be easier to comment on that. – Dharmaraj Jul 29 '21 at 11:31
  • @Dharmaraj Is that explanation is sufficient to describe my problem? I do understand that I could have model things differently. However, I really do wanna know the practice of subcollections in Mongo – Joseph D Jul 29 '21 at 11:53

1 Answers1

5

How many activities can a single project have? If there's no limit then you're better off creating a root level collection for activities. In MongoDB, the maximum BSON document size is 16 MB. That being you may not be able to store all projects and their activities in a single document (organization document).

I would create 3 collections namely - organizations, projects and activities.

  1. Each organization should have a document in organizations collection similar to that you have in Firestore.
  2. Each project should have a document in projects collection containing a field "organizationID" so you can query projects of a specific organization using their ID. This is equivalent of a document in your projects sub-collection. Every project must also have it's own unique ID.
  3. Each activity should have a document in activities collection containing a field "projectID" so activities of a specific project can be retrieved.

enter image description here

I've added those additional organizationID, projectID fields even though you have _id just in case you'd like to have Firestore Document IDs there for easier side-by-side queries.

You don't have to worry about 16 MB document size limit this way and it'll be easier to query both projects and activities as long as you have the correct IDs.

Querying activities of a certain project:

await db.collection("activities").find({projectID: "myProjectID"}).toArray()

Thereafter it's upto you how you want to write queries with projections, aggregation, etc.

Dharmaraj
  • 47,845
  • 8
  • 52
  • 84
  • @SunnyRahi it'll be best if you provide more details about your use case in a different question just like OP of this question did. – Dharmaraj Dec 15 '21 at 17:50
  • My bad I just edited it – Sunny Rahi Dec 15 '21 at 17:52
  • 1
    Hey which one is more efficient? Like we can get all the activities as my sub collection suppose user.doc("userId" ).collection("activities"). Get(), or the mongodb find query db.collection("activities").find({projectID}) to go each document that match with my userId? Is it efficient like the fire store one? – Sunny Rahi Dec 15 '21 at 17:56