Little help with ecommerce data structure

Hi there,

I’m just starting out and experimenting with MongoDB, and I wanted to get an idea of whether I can improve what I have in mind. I’m working on a personal project for a pet shop e-commerce website, and I’ll have the following “tables”/documents: Animals, Products, and Users.

My users can be connected to multiple animals, and my products can also be associated with several animals. So, when I display products to the user, I want to prioritize showing products related to the animals they own. The approach I came up with is as follows:

User: {
id
Animals[Object…]
}

Product: {
id
Animals[Object…]
}

Animals:{
id
Products[Object…]
User[Object…]
}

However, I’m a bit unsure if this is the best way to go about it. I’m not sure if there might be a more efficient way to perform the query I want. :thinking:

Hello, @Tutuacs_N_A ! Welcome to the MongoDB community! :wave:

If you do not plan to interact with animals documents often (to read or write updates), you can embed aminals object in user objects. Especially if that animal objects do not represent something abstract, like a general description of some parrot, but rather a pet, that belong only to some one single user in the database.

So, you can model your data like this:

db.users.insertMany([
  {
    _id: 'U1',
    hasPets: ['cat', 'budgerigar']
  },
  {
    _id: 'U2',
    hasPets: ['dog']
  },
]);
db.products.insertMany([
  {
    _id: 'P1',
    forPets: ['cat']
  },
  {
    _id: 'P2',
    forPets: ['dog', 'cat']
  },
  {
    _id: 'P3',
    forPets: ['budgerigar']
  }
]);

Later, when a client application makes a request to your node.js application, during authentication/authorization process you fetch current user object along with the pets array. So, by the time corresponding endpoint is hit, you already know the pet list for which you need to fetch products:

db.products.aggregate([
  {
    $match: {
      forPets: {
        $in: ['dog', 'budgerigar']
      }
    }
  }
]);

Output:

[
  { _id: 'P2', forPets: [ 'dog', 'cat' ] },
  { _id: 'P3', forPets: [ 'budgerigar' ] }
]

If you animal objects has additional fields, you can store them as an array in a separate field, like this:

{
    _id: 'U1',
    hasPets: ['cat', 'budgerigar'],
    petObjects: [
      {
        name: 'Cat 1',
        color: 'ginger'
      },
      {
        name: 'Cat 2',
        color: 'black'
      },
      {
        name: 'Budgerigar',
        color: 'green'
      }
    ],
  }

Don’t worry about data normalization - for many use cases in MongoDB, the denormalized data model is optimal. Your’s seems to be exact same case :wink:.

1 Like