2

Let us assume the following as the user flow in a multi tenant application with each tenant having its own set of catalogs or share a common catalog.

User logs into the application and see

UI with list of catalogs - User clicks on one catalog and navigates to

UI with list of categories - User clicks on one category and navigates to

UI with list of Groups - User clicks on one group and navigates to

UI with list of Articles - User clicks on one article and navigates to

UI all the details for an Article - an article can be a doc, video or pdf and other metadata

I am new to MondoDB and based on my understanding the document structure could be

    [
        {
          "TenantName": "Tenant A",
          "catalogs": [
            {
              "Categories": [
                {
                  "Groups": [
                    {
                      "Articles": [
                        {
                          "Article Title": "Title 1"
                        }
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        },
        {
          "TenantName": "Tenant B",
          "catalogs": [
            {
              "Categories": [
                {
                  "Groups": [
                    {
                      "Articles": [
                        {
                          "Article Title": "Title 1"
                        }
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        }
    ]

Is the above design the right approach to start with?

But is this performance efficient as I read the root document is performance efficient but the nested may not be. Since the flow of the application is step by step I am worried whether this approach will be helpful considering the performance and the storage.

PS: The category can be part of multiple tenants, same groups can be part of multiple categories, same article can be part of multiple groups

Gopi
  • 5,656
  • 22
  • 80
  • 146
  • is is any specific requirement to use mongoDB only for above one? as per your structure it seems you have to use relational DB which will help you to develop maximize and scalable application. – hiren207 Jun 12 '23 at 06:31
  • As soon as you start to share something, the shared data should be part of a separate collection and the tenants should be referring them by ids. Ideally you would use a relational database for this, but you can use MongoDB for it as well, but not without its drawbacks. See $lookup https://www.mongodb.com/docs/manual/core/views/join-collections-with-view/ or by issuing 2 queries, one for tenants and one for categories. – Daniel F Jun 12 '23 at 06:36
  • @hiren207 I completely agree but somehow all the schema falls back to RDBMS way rather than NoSQL. So if this is a case in NoSQL how could we design the documents? – Gopi Jun 13 '23 at 05:28
  • @Gopi Yes, it can be but the performance will be low compare to SQL DB, NoSQL DBs are designed specifically for non-relationation data but if you want you can do, let me try to share mongoose example in answer which may can help you. – hiren207 Jun 13 '23 at 05:47
  • @hiren207 Sure, that will really enlightened my knowledge – Gopi Jun 13 '23 at 05:49
  • @Gopi, i tried to design similar as per your requirement, if you want to try it. – hiren207 Jun 13 '23 at 06:47

1 Answers1

1

This is how you can use it with mongoose (ORM)

// Tenant Model
const TenantSchema = new mongoose.Schema({
  TenantName: {
    type: String,
    required: true,
  },
  catalogs: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Catalog',
  }],
});

const Tenant = mongoose.model('Tenant', TenantSchema);


// Catalog Model
const CatalogSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
  },
  tenant: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Tenant',
  },
  categories: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Category',
  }],
});

const Catalog = mongoose.model('Catalog', CatalogSchema);


// Category Model
const CategorySchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
  },
  catalog: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Catalog',
  },
  groups: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Group',
  }],
});

const Category = mongoose.model('Category', CategorySchema);


// Group Model
const GroupSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
  },
  category: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Category',
  },
  articles: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Article',
  }],
});

const Group = mongoose.model('Group', GroupSchema);


// Article Model
const ArticleSchema = new mongoose.Schema({
  title: {
    type: String,
    required: true,
  },
  group: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Group',
  },
  type: {
    type: String,
    enum: ['document', 'video', 'pdf'],
    required: true,
  },
  metadata: {
    // Add any additional metadata fields here
  },
});

const Article = mongoose.model('Article', ArticleSchema);

hiren207
  • 184
  • 6