Schema design in MongoDB - mongodb

I need help to model a database in MongoDB.
The model below shows performance problems.
- Collection users
- email
- hash
- store
- name
- adress
- logo
- products
- name
- value
- description
- image
- featured
- categories
- id_category
- Collection category
- id
- name
In the system the user can have a shop and the shop have many products and the products have many categories.
The problem is when I want to put a product featured on the home page , the system will search for all users , which is not good.
I thought about putting the products in another collection , but that would think of " relational " mode, which MongoDB is not .

You can do relational in MongoDB it just isn't build with that in mind so you will have to pay attentions to the things that relational databases would usually pay attention to for you and you will also have to work arround things that are missing like joins. But that doesn't mean you can't do relational and if you look at your schema you are already doing the categories relational.
Also since you are storing images with the product and a shop can have a lot of products you will probably run into the 16MB document size limit sooner or later.
A product collection is probably the right way for you given the information from the question.

Since your user have many products, I think its better to put "product" in another collection.
Note that MongoDB has a limit of 16 MB for a single document.
You can do something like the following:
- Collection users
- email
- hash
- store
- name
- adress
- logo
- products :[product1ID, product2ID,...]
- Collection Product
- ProductID
- name
- value
- description
- image
- featured
- categories
- id_category
- Collection category
- id
- name
Embedded document model is not a good choice for many-to-many relation. Using normalized data model can clarify the schema, save disk space. Although you would have to run multiple queries for a "JOIN".
For more detail, you can read the data model section of the official manual:http://docs.mongodb.org/manual/core/data-modeling-introduction/

Related

How to avoid customer's order history being changed in MongoDB?

I have two collections
Customers
Products
I have a field called "orders" in each of my customer document and what this "orders" field does is that it stores a reference to the product Id which was ordered by a customer, now my question is since I'm referencing product Id and if I update the "title" of that product then it will also update in the customer's order history since I can't embed each order information since a customer may order thousands of products and it can hit 16mb mark in no time so what's the fix for this. Thanks.
Create an Orders Collection
Store ID of the user who made the order
Store ID of the product bought
I understand you are looking up the value of the product from the customer entity. You will always get the latest price if you are not storing the order/price historical transactions. Because your data model is designed this way to retrieve the latest price information.
My suggestion.
Orders place with product and price always need to be stored in history entity or like order lines and not allow any process to change it so that when you look up products that customers brought you can always get the historical price and price change of the product should not affect the previous order. Two options.
Store the order history in the current collection customers (or top say 50 order lines if you don't need all of history(write additional logic to handle this)
if "option1" is not feasible due to large no. of orders think of creating an order lines transaction table and refer order line for the product brought via DBref or lookup command.
Note: it would have helped if you have given no. of transactions in each collection currently and its expected rate of growth of documents in the collection QoQ.
You have orders and products. Orders are referencing products. Your problem is that the products get updated and now your orders reference the new product. The easiest way to combat this issue is to store full data in each order. Store all the key product-related information.
The advantage is that this kind of solution is extremely easy to visualize and implement. The disadvantage is that you have a lot of repetitive data since most of your products probably don't get updated.
If you store a product update history based on timestamps, then you could solve your problem. Products are identified now by 3 fields. The product ID, active start date and active end date. Or you could configure products in this way: product ID = product ID + "Version X" and store this version against each order.
If you use dates, then you will query for the product and find the product version that was active during the time period that the order occurred. If you use versions against the product, then you will simply query the database for the particular version of the product itself. I haven't used mongoDb so I'm not sure how you would achieve this in mongoDb exactly. Naively however, you can modify the product ID to include the version as well using # as a delimiter possibly.
The advantage of this solution is that you don't store too much of extra data. Considering that products won't be updated too often, I feel like this is the ideal solution to your problem

RESTful API: How to organize nested resources

I have question about how to organize API route structure. Have read many books about building RESTful APIs and couldn't find answer for that.
Every book tells about simple CRUD actions, and nested resources in one level.
Like /users and /users/1/posts. No problem with that.
EXAMPLE:
But let's look at more difficult real life example:
GET /cars // List of cars
GET /cars/{car_id} // Get single car
POST /cars // Add new car
PUT /cars/{car_id} // Update existing car
DELETE /cars/{car_id} // Delete car by specified ID
Structure for database table of cars would be
Table "cars"
- id
- uuid
- make
- model
- year
- created_at
- updated_at
- deleted_at
No problems so far, but then I need to add nested resource.
All repairs that were done with specified car.
GET /cars/{car_id}/repairs // List of repairs that were done with car
GET /cars/{car_id}/repairs/{repair_id} // Get single repair
POST /cars/{car_id}/repairs // Add new repair for specified car
PUT /cars/{car_id}/repairs/{repair_id} // Update existing repair for specified car
DELETE /cars/{car_id}/repairs/{repair_id} // Delete repair by specified ID
Structure for database table would be
Table "car_repairs"
- id
- uuid
- car_id ( foreign key to cars )
- title
- description
- repair_started_at
- repair_ended_at
- created_at
- updated_at
- deleted_at
So far no problem. Like in all books. a /users route and nested route /users/1/posts. But then here starts problem, when I need to add another level of nesting.
I need CRUD routes for all defects that were found when car was on repair
GET /cars/{car_id}/repairs/{repair_id}/defects // List of all defects that were found for specified repair for speicified car
GET /cars/{car_id}/repairs/{repair_id}/defects/{defect_id} // Get single defect
POST /cars/{car_id}/repairs/{repair_id}/defects // Add new defect
PUT /cars/{car_id}/repairs/{repair_id}/defects/{defect_id} // Update existing defect
DELETE /cars/{car_id}/repairs/{repair_id}/defects/{defect_id} // Delete existing defect
Table structure would be:
Table "car_repair_defects"
- id
- uud
- car_id
- repair_id
- name
- description
- created_at
- updated_at
- deleted_at
QUESTSIONS:
What to do here, is level of .../defects normal practice or not ?
Consider situation if I need to add another, 4th level of nesting, at example, all parts that were used for found defect
What best practice when nesting resources in RESTful API's
One can say that this can be done without nesting. Example /cars /repairs /defects /parts But then, what about RESTful examples with nested resources. Then what is maximal level of nesting resource 0, 1, 2, 3 ?
Also if it will be done without nesting, at example, you need to create dictionary route /defects that just lists all possible car defects. So there would be name collision.
Also, if there is no nesting, how would you filter items, that you would filter with nesting ?
defects?car_id=1&repair_id=2&defect_id=3
Like this ? This looks ugly.
Please can someone point to a book or article, or give answer about maximal level of nesting and questions listed before.
Thank you.
Here's the key point: REST doesn't care what spelling you use for your identifiers.
Which is to say, REST considers each of these URI to be equally good.
/cars/{car_id}/repairs/{repair_id}/defects
/08617423-cc74-4967-9a67-49e4171f01b7
As far as the client is concerned, the identifier is opaque; encoding information into the URI is done at the discretion of the server for its own exclusive use.
Beyond that, identifier spelling conventions are effectively code style conventions; use spellings that are consistent with the local style.
From the client's perspective, the identifier does not describe the semantics of the resource; that's the job of the hypermedia representation.

mongodb custom objectId depending on object type

my question:
I am building a project with mongoDB/mongoose, I have different Schemas Users - Locations - Devices etc.
I am using the Object Id's generated by mongo to have unique links that are going to be sharable.
I still want mongo to generate the Id's and index them, but i want to add 2 characters to them for example: users ---> U-573c5f2dc8973c3cee73f0ae, Locations L-573c5f2dc8973c3cee73f0ae, and so on...
I will appreciate if somebody can help me out with this.

Export PostgreSQL data to MongoDB

Hello I fell parachute on a project that will use MongoDB and do the import of a base using PostgreSQL, this base possess several banks and has a total of 251 tables my questions are:
1 - From what I've studied so far in MongoDB relationships I have but only one document that brings all the information I need, ie in a product table where I have the vendor id and category id to export to mongo I would have to create a document with the product + vendor information + category information, correct?
2 - Is there any program that exports these data to the mongo and generates the document with all the information I need?

Lucene - Index and search entites with unique attributes

I am implemeting Lucene for an ecommerce system and need to index the products along with their attributes. However, I'm not sure how to approach this as every product will have a totally unique attribute list.
Most examples online show a lucene access layer with a product structure such as Name / Title / Description, sometimes even with a custom field which just gets added for every product.
An example of two products that would need to be indexed are shown below. As you can see in this case (although not always) there are similar attributes, but also unique ones.
ID - 1
Product - Electric Shower
Name - Triton t80Z
Description - Details about shower here...
Attributes
Color - Black
Power Rating - 7.5Kw
Temperature Control - Manual
Water Entry - Top Left
ID - 2
Product - Digital Shower
Name - Grohe Grotherm
Description - Details about shower here...
Attributes
Color - Chrome
Temperature Control - Thermostatic
Water Entry - Top Left
Flow Limit - 8 Litre/min
LCD Display - True
Control Panel - Wireless
Control Panel Range - 10m
Given this situation, how would I index the above products and create a query in lucence to find any products across the site that contain a Temperature Control attribute which is Thermostatic?
Unlike with databases, Lucene has no schema (at least in the classical DB sense) so you are free to add any attributes (they're called fields) at any given time. Just create a new Field, with the relevant name/value, add it to the Document and that's it.
Q> how would I <..> create a query in lucence to find any products across the site that contain a Temperature Control attribute which is Thermostatic?
A> something along the lines of the following should just work, providing you will use the same analyzer which is used for indexing the document:
Query q = new AnalyzingQueryParser(<params>).parse("temperature_control:Thermostatic");
Going deeper into details, it depends if values for Temperature Control come from a pre-defined list, and how you want them to be searchable (exact match VS separate words, etc.). These will define settings for your analyzer.