I need to have 2 API to
1) Retrieve a list of clothes (while checking which items are the user's favourites, and mark it with a heart shape)
2) Retrieve a list of user's favourite clothes
How should I store user favourites?
What I've figured out so far:
Embed all user's ID in each clothing item in "Clothes" document. And keep an array of user's favourite in "User" document. To find out which clothes is a user's favourite we will do a match between "Clothes" and "User" document by leveraging the ID field.
Clothes collection:
{
"id" : "clothesID01",
"images": [
{"imgUrl": "https://s3-ap-1.amazonaws.com/rental/img1.png"},
{"imgUrl": "https://s3-ap-1.amazonaws.com/rental/img2.png"},
{"imgUrl": "https://s3-ap-1.amazonaws.com/rental/img3.png"}
],
"brand" : "Halo",
"title" : "Cheryl Dress",
"retailPrice" : {
"currency": "USD",
"amount": 447
},
"description":"Halo pieces are xxxx",
"favorites" : [
{"userId" : "user01"},
{"userId" : "user02"}
],
"isPremium" : true,
"publishedDate" : "2019-04-04T06:12:46.839+00:00"
...
}
User collection:
{
"id": "user01",
"phoneNumber": "+123456789",
"favourites":[
{"clothesId" : "clothesID01"},
{"clothesId" : "clothesID04"}
]
...
}
Base on the Rules of thumb for mongoDB Design , in rule 3,
if there are more than a few thousand documents on the “many” side, don’t use an array of ObjectID references
The "clothes" document favourite might consist of about 100k users (fingers crossed) which might not be suitable to use an array of ObjectID references.
What's the remedy for this?
Cons: Data size in MongoDB is typically higher due to e.g. each document has field names stored it. less flexibity with querying (e.g. no JOINs) no support for transactions - certain atomic operations are supported, at a single document level.
MongoDB would not be well suited for applications that need: Multi-Object Transactions: MongoDB only supports ACID transactions for a single document. SQL: SQL is well-known and a lot of people know how to write very complex queries to do lots of things.
First of all, you have no need to store the favorite data in the clothes collection at all. In addition to the issues you identified, you will have a race condition whenever two users update favorite the same clothing item simultaneously.
Instead, only store the user's favorites in the User collection, then highlight the hearts during the rendering phase if the ClothesID matches the User's list of favorites.
Second, use a dictionary hashmap for more performative lookups, rather than a list which will require searching every item.
{
"id": "user01",
"phoneNumber": "+123456789",
"favourites": {
"clothesID01": true,
"clothesID04": true
}
}
When you want to know if a clothesID is a favorited, you can check if
if (user.favourites[clothesID] === true)
This does not require iterating over every item in an Array, instead you are checking just one specific location in memory.
So the direct queries you would use:
1) Retrieve a list of clothes (while checking which items are the user's favourites, and mark it with a heart shape)
const user = await db.User.findOne(ObjectId(userId));
const clothes = await db.Clothes.find(query).toArray();
for(let article of clothes) {
if(user.favourites[article.clotheId]) {
// display full heart
}
}
2) Retrieve a list of user's favourite clothes
const user = await db.User.findOne(ObjectId(userId), {favourites:true});
const favouriteIds = Object.keys(user.favourites);
const favourites = await db.Collection.find({_id: {$in: favouriteIds}}).toArray();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With