├── Daigrams
├── BigO.png
├── Event_loop.png
├── NodeJS_Runtime.png
├── Thread_pool.png
├── client-server-model.png
├── mvc.png
└── pipes.png
├── HTML & CSS
├── CSS.md
└── HTML.md
├── Javascript
└── Javascript.md
├── MongoDB
├── Aggregation.md
├── AggregationQstns.md
└── MongoDb.md
├── NodeJs & Express Js
├── Express.md
└── NodeJs.md
├── PostgreSQL
└── PostgreSQL.md
└── Typescript
└── TypeScript.md
/Daigrams/BigO.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aswanthnarayan/ProgrammingNotes/15f0b2f512dff406e490b14a26797bd823bb1e34/Daigrams/BigO.png
--------------------------------------------------------------------------------
/Daigrams/Event_loop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aswanthnarayan/ProgrammingNotes/15f0b2f512dff406e490b14a26797bd823bb1e34/Daigrams/Event_loop.png
--------------------------------------------------------------------------------
/Daigrams/NodeJS_Runtime.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aswanthnarayan/ProgrammingNotes/15f0b2f512dff406e490b14a26797bd823bb1e34/Daigrams/NodeJS_Runtime.png
--------------------------------------------------------------------------------
/Daigrams/Thread_pool.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aswanthnarayan/ProgrammingNotes/15f0b2f512dff406e490b14a26797bd823bb1e34/Daigrams/Thread_pool.png
--------------------------------------------------------------------------------
/Daigrams/client-server-model.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aswanthnarayan/ProgrammingNotes/15f0b2f512dff406e490b14a26797bd823bb1e34/Daigrams/client-server-model.png
--------------------------------------------------------------------------------
/Daigrams/mvc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aswanthnarayan/ProgrammingNotes/15f0b2f512dff406e490b14a26797bd823bb1e34/Daigrams/mvc.png
--------------------------------------------------------------------------------
/Daigrams/pipes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aswanthnarayan/ProgrammingNotes/15f0b2f512dff406e490b14a26797bd823bb1e34/Daigrams/pipes.png
--------------------------------------------------------------------------------
/HTML & CSS/CSS.md:
--------------------------------------------------------------------------------
1 | # CSS
2 |
3 | CSS (Cascading Style Sheets) is used to style HTML elements. The basic syntax of a CSS rule consists of a selector and a declaration block.
4 |
5 | **example**:
6 |
7 | ```css
8 | selector {
9 | property: value;
10 | property: value;
11 | }
12 | ```
13 |
14 | # CSS Selectors
15 |
16 | CSS selectors are used to target HTML elements that you want to style. Here are some common types of selectors
17 |
18 | ### 1. Universal Selector
19 |
20 | Selects all elements on the page.
21 |
22 | ```css
23 | * {
24 | margin: 0;
25 | padding: 0;
26 | }
27 | ```
28 |
29 | ### 2.Element Selector
30 |
31 | Selects all elements of a specified type.
32 |
33 | ```css
34 | h1 {
35 | color: green;
36 | }
37 | ```
38 |
39 | ### 3. Class Selector
40 |
41 | Selects all elements with a specified class attribute.
42 |
43 | ```css
44 | .intro {
45 | font-size: 20px;
46 | }
47 | ```
48 |
49 | ### 4. ID Selector
50 |
51 | Selects the element with the specified ID
52 |
53 | ```css
54 | header {
55 | background-color: lightblue;
56 | }
57 | ```
58 |
59 | ### 5. Attribute Selector
60 |
61 | Selects elements based on an attribute or attribute value.
62 |
63 | ```css
64 | a[target="_blank"] {
65 | color: red;
66 | }
67 | ```
68 |
69 | ### 6. Descendant Selector
70 |
71 | Selects elements that are descendants of another element.
72 |
73 | ```css
74 | div p {
75 | color: purple;
76 | }
77 | ```
78 |
79 | ### 7. Child Selector
80 |
81 | Selects elements that are direct children of another element.
82 |
83 | ```css
84 | ul > li {
85 | list-style-type: none;
86 | }
87 | ```
88 |
89 | ### 8. Sibling Selectors
90 |
91 | **_Adjacent Sibling Selector_**: Selects an element that is immediately preceded by a specified element.
92 |
93 | ```css
94 | h1 + p {
95 | margin-top: 0;
96 | }
97 | ```
98 |
99 | **_General Sibling Selector_**: Selects all elements that are preceded by a specified element.
100 |
101 | ```css
102 | h1 ~ p {
103 | color: gray;
104 | }
105 | ```
106 |
107 | ### 9. Pseudo-class Selector
108 |
109 | Selects elements based on their state or position.
110 |
111 | ```css
112 | a:hover {
113 | color: orange;
114 | }
115 | ```
116 |
117 | ### 10. Pseudo-element Selector
118 |
119 | Selects a part of an element.
120 |
121 | ```css
122 | p::first-line {
123 | font-weight: bold;
124 | }
125 | ```
126 |
127 | ### 11.Combining Selectors
128 |
129 | You can combine multiple selectors to target more specific elements.
130 |
131 | ```css
132 | div.intro,
133 | #main-content p {
134 | margin: 10px;
135 | }
136 | ```
137 |
138 |
139 | # CSS BOX MODEL
140 |
141 | The CSS Box Model is a fundamental concept that describes how elements on a web page are structured and how space is allocated around them. It consists of four main components:
142 |
143 | - `Content`
144 | - `Padding`
145 | - `Border`
146 | - `Margin`
147 |
148 | ### 1. Content
149 | This is the actual content of the box, such as text or an image. It's the innermost part of the box.
150 |
151 | ### 2. Padding
152 | Padding is the space between the content and the border. It creates a transparent area inside the box around the content. You can set different padding values for each side of the box.
153 |
154 | Example:
155 | ```css
156 | div {
157 | padding: 10px; /* Applies 10px padding to all sides */
158 | }
159 | ```
160 | ### 3. Border
161 | The border surrounds the padding (if any) and the content. It can have various styles, widths, and colors.
162 |
163 | Example:
164 |
165 | ```css
166 | div {
167 | border: 1px solid black; /* 1px solid black border around the box */
168 | }
169 | ```
170 | ### 4. Margin
171 | Margin is the space outside the border. It creates a transparent area outside the box, separating it from other elements.
172 |
173 | Example:
174 |
175 | ```css
176 | div {
177 | margin: 15px; /* Applies 15px margin to all sides */
178 | }
179 | ```
180 |
181 | ### Visual Representation
182 |
183 | ```lua
184 | +---------------------------+
185 | | Margin |
186 | | +---------------------+ |
187 | | | Border | |
188 | | | +---------------+ | |
189 | | | | Padding | | |
190 | | | | +-----------+ | | |
191 | | | | | Content | | | |
192 | | | | +-----------+ | | |
193 | | | +---------------+ | |
194 | | +---------------------+ |
195 | +---------------------------+
196 |
197 | ```
198 |
199 | # Box Sizing
200 |
201 | By default, the width and height properties apply to the content box. You can change this behavior using the box-sizing property.
202 |
203 | **Content-box (default)**: width and height apply to the content only.
204 | ```css
205 | div {
206 | box-sizing: content-box;
207 | }
208 | ```
209 | **Border-box**: width and height include content, padding, and border.
210 | ```css
211 | div {
212 | box-sizing: border-box;
213 | }
214 | ```
215 |
216 | # CSS Text Styling Guide
217 |
218 | ## Font Properties
219 |
220 | **font-family**: Specifies the typeface for the text.
221 | ```css
222 | p {
223 | font-family: Arial, sans-serif;
224 | }
225 | ```
226 |
227 | **font-size**: Sets the size of the font.
228 | ```css
229 | p {
230 | font-size: 16px;
231 | }
232 | ```
233 |
234 | **font-weight**: Defines the thickness of the font.
235 | ```css
236 | p {
237 | font-weight: bold; /* or 400, 700, etc. */
238 | }
239 | ```
240 |
241 | **font-style**: Sets the style of the font (normal, italic, or oblique).
242 | ```css
243 | p {
244 | font-style: italic;
245 | }
246 | ```
247 |
248 | **font-variant**: Controls the use of small caps and other font variations.
249 | ```css
250 | p {
251 | font-variant: small-caps;
252 | }
253 | ```
254 |
255 | **font**: A shorthand property for setting multiple font properties at once.
256 | ```css
257 | p {
258 | font: italic bold 16px Arial, sans-serif;
259 | }
260 | ```
261 |
262 | ## Text Color
263 |
264 | **color**: Sets the color of the text.
265 | ```css
266 | p {
267 | color: #333; /* Dark gray color */
268 | }
269 | ```
270 |
271 | ## Text Alignment
272 |
273 | **text-align**: Aligns the text within its container (left, right, center, justify).
274 | ```css
275 | p {
276 | text-align: center;
277 | }
278 | ```
279 |
280 | ## Text Decoration
281 |
282 | **text-decoration**: Adds decorations like underline, overline, or line-through.
283 | ```css
284 | a {
285 | text-decoration: underline;
286 | }
287 | ```
288 |
289 | ## Text Transform
290 |
291 | **text-transform**: Controls the capitalization of text (uppercase, lowercase, capitalize).
292 | ```css
293 | p {
294 | text-transform: uppercase;
295 | }
296 | ```
297 |
298 | ## Text Indentation
299 |
300 | **text-indent**: Sets the indentation of the first line of text.
301 | ```css
302 | p {
303 | text-indent: 20px;
304 | }
305 | ```
306 |
307 | ## Line Height
308 |
309 | **line-height**: Sets the amount of space between lines of text.
310 | ```css
311 | p {
312 | line-height: 1.5;
313 | }
314 | ```
315 |
316 | ## Letter Spacing
317 |
318 | **letter-spacing**: Adjusts the spacing between characters.
319 | ```css
320 | p {
321 | letter-spacing: 2px;
322 | }
323 | ```
324 |
325 | ## Word Spacing
326 |
327 | **word-spacing**: Adjusts the spacing between words.
328 | ```css
329 | p {
330 | word-spacing: 4px;
331 | }
332 | ```
333 |
334 | ## Text Shadow
335 |
336 | **text-shadow**: Adds shadow effects to text.
337 | ```css
338 | h1 {
339 | text-shadow: 2px 2px 4px #666;
340 | }
341 | ```
342 |
343 | ## White Space
344 |
345 | **white-space**: Controls how whitespace inside an element is handled (normal, nowrap, pre, pre-wrap, pre-line).
346 | ```css
347 | p {
348 | white-space: pre-wrap;
349 | }
350 | ```
351 |
352 | ## Text Overflow
353 |
354 | **text-overflow**: Controls how overflowed text is displayed (clip, ellipsis).
355 | ```css
356 | p {
357 | text-overflow: ellipsis;
358 | overflow: hidden;
359 | white-space: nowrap;
360 | }
361 | ```
362 |
363 | # FLEX BOX
364 | Flex-box is a layout model that allows you to design complex layouts with ease, aligning items horizontally or vertically.
365 |
366 | ```css
367 | .container {
368 | display: flex;
369 | justify-content: center; /* Align items horizontally */
370 | align-items: center; /* Align items vertically */
371 | }
372 |
373 | .item {
374 | flex: 1; /* Grow and shrink items as needed */
375 | }
376 | ```
377 | # GRID
378 | CSS Grid Layout provides a two-dimensional grid-based layout system, allowing for more complex designs.
379 |
380 | ```css
381 | .container {
382 | display: grid;
383 | grid-template-columns: 1fr 1fr; /* Create two equal columns */
384 | grid-gap: 10px; /* Space between grid items */
385 | }
386 |
387 | .item {
388 | grid-column: span 1; /* Specify how many columns an item should span */
389 | }
390 | ```
391 |
392 | # CSS POSITIONING
393 | CSS positioning allows you to control the exact position of elements on a page.
394 |
395 | ## Types of Positioning
396 | **`Static`**: Default positioning, flow of the document.
397 | **`Relative`**: Positioned relative to its normal position.
398 | **`Absolute`**: Positioned relative to its nearest positioned ancestor.
399 | **`Fixed`**: Positioned relative to the viewport.
400 | **`Sticky`**: Switches between relative and fixed, depending on scroll position.
401 |
402 | ```css
403 | .relative {
404 | position: relative;
405 | top: 10px;
406 | left: 20px;
407 | }
408 |
409 | .absolute {
410 | position: absolute;
411 | top: 50px;
412 | right: 20px;
413 | }
414 |
415 | .fixed {
416 | position: fixed;
417 | bottom: 0;
418 | right: 0;
419 | }
420 | ```
421 |
422 | # CSS Variables
423 | CSS Variables (Custom Properties) allow you to define reusable values in your stylesheets.
424 |
425 | ```css
426 | :root {
427 | --main-color: #3498db;
428 | }
429 |
430 | .element {
431 | color: var(--main-color);
432 | }
433 | ```
434 |
435 | # CSS TRANSITIONS
436 | CSS transitions and animations are used to create dynamic visual effects and enhance the user experience by animating changes to CSS properties. Here’s a breakdown of each:
437 |
438 | ## Properties
439 | - `property`: The CSS property you want to animate (e.g., background-color, width).
440 | - `duration`: How long the transition takes (e.g., 0.5s, 200ms).
441 | - `timing-function`: The speed curve of the transition (e.g., linear, ease, ease-in, ease-out, ease-in-out).
442 | - `delay`: Delay before the transition starts (e.g., 0s, 1s).
443 |
444 | ## TRANSFORM
445 | The transform property in CSS is used to apply various transformations to elements, such as scaling, rotating, translating, and skewing. This property allows you to change the appearance of an element without affecting its layout.
446 |
447 | ```css
448 | selector {
449 | transform: transform-function;
450 | }
451 | ```
452 | ### Transform Functions
453 | **translate(x, y)**
454 | Moves the element from its original position.
455 | x: Horizontal movement (e.g., 10px, 50%).
456 | y: Vertical movement (e.g., 20px, 30%).
457 | ```css
458 | .translate-example {
459 | transform: translate(50px, 20px);
460 | }
461 | ```
462 | **rotate(angle)**
463 |
464 | Rotates the element around its origin.
465 | angle: The degree of rotation (e.g., 45deg, 1rad).
466 | ```css
467 | .rotate-example {
468 | transform: rotate(45deg);
469 | }
470 | ```
471 | **scale(x, y)**
472 |
473 | Scales the element in the horizontal and vertical directions.
474 | x: Horizontal scale factor (e.g., 1.5 for 150%).
475 | y: Vertical scale factor (e.g., 2 for 200%).
476 | ```css
477 | .scale-example {
478 | transform: scale(1.5, 0.5);
479 | }
480 | ```
481 | **skew(x, y)**
482 |
483 | Skews the element along the x and y axes.
484 | x: Skew angle along the x-axis (e.g., 20deg).
485 | y: Skew angle along the y-axis (e.g., 10deg).
486 |
487 | ```css
488 | .skew-example {
489 | transform: skew(20deg, 10deg);
490 | }
491 | ```
492 | **matrix(a, b, c, d, e, f)**
493 | Applies a 2D transformation using a matrix.
494 | a, b, c, d, e, f: Values for the matrix transformation.
495 |
496 | ```css
497 | .matrix-example {
498 | transform: matrix(1, 0.5, -0.5, 1, 0, 0);
499 | }
500 | ```
501 |
502 |
503 |
504 |
505 |
506 | # ANIMATION
507 |
508 | CSS animations provide more control and complexity compared to transitions, allowing you to create keyframe-based animations.
509 |
510 | ```css
511 | @keyframes animation-name {
512 | from {
513 | property: value;
514 | }
515 | to {
516 | property: value;
517 | }
518 | }
519 | ```
520 | ## Properties
521 | - `animation-name`: The name of the @keyframes animation.
522 | - `animation-duration`: The duration of the animation (e.g., 2s, 500ms).
523 | - `animation-timing-function`: The speed curve of the animation (e.g., linear, ease, ease-in, ease-out, ease-in-out).
524 | - `animation-delay`: Delay before the animation starts (e.g., 0s, 1s).
525 | - `animation-iteration-count`: How many times the animation should repeat (e.g., 1, infinite).
526 | - `animation-direction`: The direction of the animation (e.g., normal, reverse, alternate, alternate-reverse).
527 | - `animation-fill-mode`: The styles to apply before and after the animation (e.g., none, forwards, backwards, both).
528 |
529 | example:
530 |
531 | ```css
532 | @keyframes fadeIn {
533 | from {
534 | opacity: 0;
535 | }
536 | to {
537 | opacity: 1;
538 | }
539 | }
540 |
541 | .box {
542 | width: 100px;
543 | height: 100px;
544 | background-color: #3498db;
545 | animation: fadeIn 2s ease-in-out;
546 | }
547 | ```
548 | # Z-INDEX
549 | The z-index property in CSS controls the stacking order of positioned elements (those with a position value other than static). It determines which elements appear on top of others when they overlap.
550 |
551 | ```css
552 | selector {
553 | z-index: value;
554 | }
555 | ```
556 | ## Values
557 |
558 | **Integer Values**:
559 | - `Positive integers` (e.g., 1, 2, 10) bring the element closer to the front.
560 | - `Negative integers` (e.g., -1, -10) push the element further behind other elements.
561 | **Auto**:
562 | The default value, which means the element will stack according to the document order and other positioning properties.
563 |
564 | ## Important Considerations
565 |
566 | **Positioning**: For z-index to work, the element must have a position property set to relative, absolute, fixed, or sticky.
567 | **Stacking Context**: z-index only affects stacking within the same stacking context. A new stacking context is created by elements with certain properties, such as position with a z-index value other than auto, opacity less than 1, transform, and others.
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
--------------------------------------------------------------------------------
/HTML & CSS/HTML.md:
--------------------------------------------------------------------------------
1 | # HTML (HyperText Markup Language)
2 | HTML is a markup language that tells web browsers how to structure the web pages
3 |
4 | ## HTML Structure
5 |
6 | ```html
7 |
8 |
9 |
10 |
11 |
12 | My Web Page
13 |
14 |
15 |
16 |
17 |
Welcome to My Web Page
18 |
19 |
26 |
27 |
28 |
Home
29 |
This is the home section.
30 |
31 |
32 |
About
33 |
This is the about section.
34 |
35 |
36 |
Contact
37 |
This is the contact section.
38 |
39 |
40 |
43 |
44 |
45 |
46 | ```
47 |
48 | # HTML Elements
49 | HTML elements are the building blocks of HTML documents. They consist of a start tag, content, and an end tag.
50 |
51 | ## Basic HTML Elements
52 |
53 | ### Document Structure
54 | - ``: Defines the document type and version of HTML.
55 | - ``: The root element of an HTML document.
56 | - ``: Contains meta-information about the document.
57 | - ``: Contains the content of the document.
58 |
59 | ### Metadata
60 | - ``: Defines the title of the document.
61 | - ``: Provides metadata such as character set, description, keywords, author.
62 | - ``: Links to external resources like stylesheets.
63 | - `
568 |
569 |
570 |
571 |
572 |
573 |
Header 1
574 |
Header 2
575 |
Header 3
576 |
577 |
578 |
579 |
580 |
Spans two rows
581 |
Data 1
582 |
Data 2
583 |
584 |
585 |
Data 3
586 |
Data 4
587 |
588 |
589 |
Data 5
590 |
Spans two columns
591 |
592 |
593 |
594 |
595 |
Footer 1
596 |
Footer 2
597 |
Footer 3
598 |
599 |
600 |
601 |
602 |
603 | ```
604 | # DEFER attribute
605 | The `defer` attribute is used to load a script asynchronously but ensures that the script is executed only after the HTML document has been completely parsed.
606 |
607 | ```html
608 |
609 |
610 |
611 |
612 |
613 | Document
614 |
615 |
616 |
617 |
618 |
Hello, World!
619 |
620 |
621 | ```
622 | Both `script1.js` and `script2.js` will be fetched in parallel, but `script1.js` will execute before `script2.js` once the HTML parsing is complete.
--------------------------------------------------------------------------------
/MongoDB/Aggregation.md:
--------------------------------------------------------------------------------
1 | # AGGREGATION
2 |
3 | Aggregation is a way of querying and transforming data to perform complex operations such as filtering, grouping, sorting, reshaping, and calculating data from multiple documents to provide meaningful insights.
4 |
5 | ## Types of Aggregation in MongoDB
6 |
7 | 1. Single Purpose Aggregation Methods
8 | 2. Map-Reduce
9 | 3. Aggregation Pipeline
10 |
11 | ## SINGLE PURPOSE
12 |
13 | These methods are simpler and more specific than the aggregation pipeline. They are designed for specific types of aggregation operations:
14 |
15 | * **count():** Returns the count of documents matching a query.
16 |
17 | ```js
18 | db.collection.count({ status: "active" });
19 | ```
20 |
21 | * **distinct():** Returns an array of distinct values for a specified field among matching documents.
22 |
23 | ```js
24 | db.collection.distinct("status");
25 | ```
26 |
27 | * **estimatedDocumentCount():** Returns an estimate of the count of documents in a collection.
28 |
29 | ```js
30 | db.collection.estimatedDocumentCount();
31 | ```
32 |
33 | * **findAndModify:** Finds and modifies a single document.
34 |
35 | ```js
36 | db.collection.findAndModify({
37 | query: { status: "active" },
38 | update: { $set: { status: "inactive" } }
39 | });
40 | ```
41 |
42 |
43 | ## MAP-REDUCE
44 |
45 | Map-Reduce is a data processing technique used to handle large datasets by breaking down the computation into two main steps: map and reduce.
46 |
47 | * **Map:** Takes each document from a collection and processes it to generate key-value pairs. Think of it as a "mapping" function that extracts or calculates some data from each document.
48 |
49 | * **Reduce:** Takes the grouped key-value pairs generated by the map step and combines them in some way to produce the final result.
50 |
51 | ```js
52 | { "_id": 1, "product": "laptop", "quantity": 2, "price": 1000 }
53 | { "_id": 2, "product": "phone", "quantity": 5, "price": 300 }
54 | { "_id": 3, "product": "laptop", "quantity": 1, "price": 1000 }
55 | ```
56 | To find the total ales amount for each product using mapReduce
57 |
58 | ```js
59 | var mapFunction = function() {
60 | emit(this.product, this.quantity * this.price);
61 | };
62 |
63 | var reduceFunction = function(key, values) {
64 | return Array.sum(values);
65 | };
66 |
67 | db.sales.mapReduce(
68 | mapFunction, // Map function
69 | reduceFunction, // Reduce function
70 | { out: "total_sales_per_product" } // Output collection
71 | );
72 | ```
73 |
74 | output will be:
75 |
76 | ```js
77 | { "_id": "laptop", "value": 3000 }
78 | { "_id": "phone", "value": 1500 }
79 | ```
80 |
81 | ## MongoDB Aggregation Pipeline
82 | MongoDB's Aggregation Framework is a powerful tool that allows you to perform operations on the data stored in your collections. It is used to process data records and return computed results. The aggregation pipeline is a series of stages where each stage transforms the document. The output of one stage becomes the input to the next.
83 |
84 | * **Aggregation:** A way of processing a large number of documents in a collection by passing them through different stages.
85 | * **Pipeline:** A series of stages where each stage performs a specific operation on the input document and passes the result to the next stage.
86 | * **Stages:** The individual operations that can be chained together to form a pipeline.
87 |
88 | ## Common Aggregation Stages
89 |
90 | 1. **$match:**
91 |
92 | Filters documents based on a condition.
93 |
94 | 2. **$group:**
95 |
96 | Groups documents by a specified field and can perform operations on the grouped data.
97 |
98 | 3. **$sort:**
99 |
100 | Sorts the documents.
101 |
102 | 4. **$project:**
103 |
104 | Shapes the documents by including, excluding, or adding new fields.
105 |
106 | 5. **$limit:**
107 |
108 | Limits the number of documents passed to the next stage.
109 |
110 | 6. **$unwind:**
111 |
112 | Deconstructs an array field from the input documents to output a document for each element.
113 |
114 | **In MongoDB Atlas, you can run aggregation pipelines directly in the Aggregation tab of a collection.**
115 |
116 | **In the MongoDB Shell `(mongosh)`, you can run the aggregation pipeline using the db.collection.aggregate() method. Here's an example:**
117 |
118 | ```
119 | db.users.aggregate([
120 | { $match: { isActive: true } },
121 | { $count: "ActiveUser" }
122 | ])
123 |
124 | ```
125 |
126 | ## Common Aggregation Operators
127 |
128 | 1. **$sum:**
129 |
130 | Calculates the sum of numeric values. Used within stages like `$group` or `$project`.
131 |
132 | 2. **$avg:**
133 |
134 | Computes the average of numeric values. Used within stages like `$group`.
135 |
136 | 3. **$add:**
137 |
138 | Adds numbers, dates, or expressions together. Used within stages like `$project` or `$addFields`.
139 |
140 |
141 |
142 | | **Aggregation Type** | **Description** | **Use Case** |
143 | |----------------------------------------|:-----------------------------------------------------------------------------------------------------------:|:------------------------------------------------------------------------:|
144 | | **Aggregation Pipeline** | Processes data through multiple stages, transforming documents at each step. | Most common and flexible; preferred for complex aggregations. |
145 | | **Single Purpose Aggregation Methods** | Simpler methods for specific aggregation tasks like count, distinct, etc. | Basic counting or fetching distinct values. |
146 | | **Map-Reduce** | Uses JavaScript functions (map and reduce) to process and aggregate data; suitable for custom aggregations. | When the Aggregation Pipeline is insufficient or custom logic is needed. |
147 |
148 | ## MongoDB Aggregation Pipeline Examples
149 |
150 | The following MongoDB aggregation pipeline examples are based on data retrieved from Hitesh Chaudary's GitHub Gist. You can visit the [Gist link](https://gist.github.com/hiteshchoudhary/) to access the data and push it to your MongoDB database.
151 |
152 | For a better understanding, watch Hitesh Chaudary's MongoDB Aggregation Playlist.
153 |
154 |
155 | ### 1. How Many Users are Active?
156 |
157 | ```
158 | [
159 | {
160 | $match: {
161 | isActive: true
162 | }
163 | },
164 | {
165 | $count: "ActiveUser"
166 | }
167 | ]
168 | ```
169 | **Output:**
170 |
171 | ```
172 | {
173 | "ActiveUser": 516
174 | }
175 | ```
176 | This query counts the number of users who are active by matching documents where `isActive` is `true` and then counting the results.
177 |
178 |
179 | ### 2. What is the Average Age of All Users?
180 |
181 | * Average age of total collection:
182 |
183 | ```
184 | [
185 | {
186 | $group: {
187 | _id: null,
188 | AverageAge: {
189 | $avg: "$age"
190 | }
191 | }
192 | }
193 | ]
194 | ```
195 |
196 | **Output:**
197 |
198 | ```
199 | {
200 | "_id": null,
201 | "AverageAge": 29.835
202 | }
203 | ```
204 | his query calculates the average age of all users by grouping all documents together and then taking the average of the `age` field.
205 |
206 |
207 | * Average age based on gender:
208 |
209 | ```
210 | [
211 | {
212 | $group: {
213 | _id: "$gender",
214 | AverageAge: {
215 | $avg: "$age"
216 | }
217 | }
218 | }
219 | ]
220 | ```
221 | **Output:**
222 |
223 | ```
224 | {
225 | "_id": "male",
226 | "AverageAge": 29.851926977687626
227 | }
228 | {
229 | "_id": "female",
230 | "AverageAge": 29.81854043392505
231 | }
232 | ```
233 | This query calculates the average age for each gender by grouping users by their `gender` and then taking the average age within each group.
234 |
235 | ### 3. List the Most Common Favorite Fruit Among the Users
236 | ```
237 | [
238 | {
239 | $group: {
240 | _id: "$favoriteFruit",
241 | count: {
242 | $sum: 1
243 | }
244 | }
245 | },
246 | {
247 | $sort: {
248 | count: -1
249 | }
250 | },
251 | {
252 | $limit: 1
253 | }
254 | ]
255 | ```
256 |
257 | **Output:**
258 |
259 | ```
260 | {
261 | "count": 339,
262 | "_id": "banana"
263 | }
264 | ```
265 | This query finds the most common favorite fruit by grouping users by their favoriteFruit, counting the occurrences of each fruit, and then sorting to find the highest count.
266 |
267 | ### 4. Find the Number of Males and Females in the Collection
268 |
269 | ```
270 | [
271 | {
272 | $group: {
273 | _id: "$gender",
274 | GenderCount: {
275 | $sum: 1
276 | }
277 | }
278 | }
279 | ]
280 | ```
281 | **Output:**
282 |
283 | ```
284 | {
285 | "_id": "male",
286 | "GenderCount": 493
287 | }
288 | {
289 | "GenderCount": 507,
290 | "_id": "female"
291 | }
292 | ```
293 | This query groups users by their gender and counts the number of users in each group.
294 |
295 | ### 5. Find the User Count Per Country
296 |
297 | ```
298 | [
299 | {
300 | $group: {
301 | _id: "$company.location.country",
302 | perUser: {
303 | $sum: 1
304 | }
305 | }
306 | },
307 | {
308 | $sort: {
309 | perUser: -1
310 | }
311 | }
312 | ]
313 | ```
314 | **Output:**
315 |
316 | ```
317 | {
318 | "_id": "Germany",
319 | "perUser": 261
320 | }
321 | {
322 | "_id": "USA",
323 | "perUser": 255
324 | }
325 | {
326 | "_id": "France",
327 | "perUser": 245
328 | }
329 | {
330 | "_id": "Italy",
331 | "perUser": 239
332 | }
333 | ```
334 | This query groups users by the country they are located in and counts how many users belong to each country, then sorts the results by the count.
335 |
336 |
337 |
338 | ### 6. List All the Unique Eye Colors Present in the Collection
339 |
340 | ```
341 |
342 | [
343 | {
344 | $group: {
345 | _id: "$eyeColor"
346 | }
347 | }
348 | ]
349 | ```
350 | **Output:**
351 |
352 | ```
353 |
354 | {
355 | "_id": "blue"
356 | }
357 | {
358 | "_id": "brown"
359 | }
360 | {
361 | "_id": "green"
362 | }
363 | ```
364 |
365 | This query lists all unique eye colors by grouping users by their `eyeColor`.
366 |
367 |
368 | #### 7. Find the Average Number of Tags Per User
369 |
370 | **Approach 1:** Using `$unwind`
371 |
372 | *Whenever you deal with an array in MongoDB aggregation pipeline, use the $unwind operator to deconstruct the array. This operator creates duplicates of the documents, with each duplicate containing one element from the array, but all with the same _id as the original document.*
373 |
374 | ```
375 | [
376 | {
377 | $unwind: "$tags"
378 | },
379 | {
380 | $group: {
381 | _id: "$_id",
382 | noOfTags: {
383 | $sum: 1
384 | }
385 | }
386 | },
387 | {
388 | $group: {
389 | _id: null,
390 | AverageTagsPerUser: {
391 | $avg: "$noOfTags"
392 | }
393 | }
394 | }
395 | ]
396 | ```
397 |
398 | **Output:**
399 |
400 | ```
401 | {
402 | "_id": null,
403 | "AverageTagsPerUser": 3.556
404 | }
405 | ```
406 |
407 | **Steps:**
408 |
409 | 1. Unwind the `tags` array: This creates a separate document for each tag within the array.
410 | 2. Group by `_id` to count the number of tags per user.
411 | 3. Group using `_id:` `null` to calculate the average number of tags per user.
412 |
413 | **Approach 2: Using `$addFields`**
414 |
415 | This approach adds a new field to the document using $addFields and then calculates the size of the tags array.
416 |
417 | ```
418 | [
419 | {
420 | $addFields: {
421 | noOfTags: {
422 | $size: {
423 | $ifNull: ["$tags", []]
424 | }
425 | }
426 | }
427 | },
428 | {
429 | $group: {
430 | _id: null,
431 | AverageTagsPerUser: {
432 | $avg: "$noOfTags"
433 | }
434 | }
435 | }
436 | ]
437 | ```
438 | **Output:**
439 |
440 | ```
441 | {
442 | "_id": null,
443 | "AverageTagsPerUser": 3.556
444 | }
445 | ```
446 |
447 | This method also returns the same output. Here, we add a new field to the document using `$addFields` and then access the `size` property to calculate the average number of `tags` per user.
448 |
449 |
450 | ### 8. How many users have 'enim' as one of their tags
451 |
452 | ```
453 | [
454 | {
455 | $match: {
456 | tags:"enim"
457 | }
458 | },
459 | {
460 | $count: 'Total No of enim Tags'
461 | }
462 | ]
463 | ```
464 | **Output:**
465 |
466 | ```
467 | {
468 | "Total No of enim Tags": 62
469 | }
470 | ```
471 | This query filters users who have "enim" in their tags array and then counts the results.
472 |
473 | ### 9. What are the names and age of the users who are inactive and a tag "valit" in their document
474 |
475 | ```
476 | [
477 | {
478 | $match: {
479 | isActive:false , tags:"velit"
480 | }
481 | },
482 | {
483 | $project: {
484 | name:1,
485 | age:1
486 | }
487 | }
488 |
489 | ]
490 | ```
491 | In here we filter the document based on tags and isActive status , then further filtered out the document details using project stage
492 |
493 |
494 | ### 10. Find the last three registered users name and favorite fruit
495 |
496 | ```
497 |
498 | [
499 | {
500 | $sort: {
501 | registered: -1
502 | }
503 | }
504 | ,
505 | {
506 | $limit: 3
507 | },
508 | {
509 | $project: {
510 | name:1,
511 | registered:1,
512 | favoriteFruit:1
513 | }
514 | }
515 |
516 | ]
517 |
518 | ```
519 | **Output:**
520 |
521 | ```
522 |
523 | {
524 | "_id": {
525 | "$oid": "66c72f43dd088db781effec5"
526 | },
527 | "name": "Stephenson Griffith",
528 | "registered": "2018-04-14T03:16:20+0000",
529 | "favoriteFruit": "apple"
530 | }
531 | {
532 | "_id": {
533 | "$oid": "66c72f43dd088db781effdb6"
534 | },
535 | "name": "Sonja Galloway",
536 | "registered": "2018-04-11T12:52:12+0000",
537 | "favoriteFruit": "strawberry"
538 | }
539 | {
540 | "_id": {
541 | "$oid": "66c72f43dd088db781efffd7"
542 | },
543 | "name": "Mcpherson Christensen",
544 | "registered": "2018-04-11T07:18:42+0000",
545 | "favoriteFruit": "strawberry"
546 | }
547 | ```
548 | This query sorts users by their registration date in descending order, limits the results to the last three users, and then projects their name and favoriteFruit.
549 |
550 |
551 | ### 11. Categorize the user by their favorite fruit
552 | ```
553 | [
554 | {
555 | $group: {
556 | _id: "$favoriteFruit",
557 | users:{
558 | $push:"$name"
559 | }
560 | }
561 | }
562 | ]
563 | ```
564 | **Output:**
565 | ```
566 | {_id:"strawberry",
567 | users:Array (323) // array with users name with Fav fruit as strawberry
568 | }
569 | ,
570 | {_id:"banana",
571 | users:Array (339) // array with users name with Fav fruit as banana
572 | }
573 | ,
574 | {_id:"apple",
575 | users:Array (338) // array with users name with Fav fruit as apple
576 | }
577 | ```
578 | This query groups users by their favoriteFruit and creates an array of user names for each fruit category.
579 |
580 | ### 12. Find the users count with "ad" as second property in the tags array
581 |
582 | ```
583 | [
584 | {
585 | $match: {
586 | "tags.1":"ad"
587 | }
588 | },
589 | {
590 | $count: 'Users with ad as Second Tag'
591 | }
592 | ]
593 | ```
594 | **Output:**
595 |
596 | ```
597 | {
598 | "Users with ad as Second Tag": 12
599 | }
600 | ```
601 |
602 | This query filters users whose second tag in the tags array is "ad" and counts the number of such users
603 |
604 | ### 13. find users who have both 'enim and 'id' in tags
605 |
606 |
607 | ```
608 | [
609 | {
610 | $match:{
611 | tags:{
612 | $all:["id","enim"]
613 | }
614 | }
615 | }
616 | ]
617 | ```
618 |
619 | **Output:**
620 |
621 | ```
622 | User Documents with tag name 'enim' and 'id
623 |
624 | ```
625 | This query filters users who have both "enim" and "id" in their tags array.
626 |
627 | ### 14. List all companies located in Usa with their corresponding user count
628 |
629 | ```
630 |
631 | [
632 | {
633 | $match:{
634 | "company.location.country":"USA"
635 | }
636 | }
637 | ,{
638 | $group:{
639 | _id:"$company.title",
640 | userCount:{
641 | $sum:1
642 | }
643 | }
644 | }
645 | ]
646 | ```
647 | **Output:**
648 |
649 | ```
650 | {
651 | "_id": "BESTO",
652 | "userCount": 1
653 | },
654 | {
655 | "_id": "DANJA",
656 | "userCount": 1
657 | },
658 | {
659 | "_id": "KONGLE",
660 | "userCount": 1
661 | }
662 | .......etc
663 |
664 | ```
665 | This query filters users based on their company's location being in the USA, groups the results by the company title, and counts the number of users for each company.
666 |
667 |
--------------------------------------------------------------------------------
/MongoDB/AggregationQstns.md:
--------------------------------------------------------------------------------
1 | **refer the previous document for inserted document**
2 |
3 | ### Count the number of active users:
4 |
5 | 1. How many users have isActive set to true?
6 |
7 | ans:
8 |
9 | ```js
10 | db.persons.aggregate([
11 | { $match: { isActive: true } },
12 | { $count: "Total Active Users" },
13 | ]);
14 | ```
15 |
16 | ### Group users by gender and count them:
17 |
18 | 2. What is the total number of male and female users?
19 |
20 | ans:
21 |
22 | ```js
23 | db.persons.aggregate([
24 | {
25 | $group: {
26 | _id: "$gender", // Groups documents by the "gender" field
27 | noOfUsers: { $sum: 1 }, // Counts the number of documents in each group
28 | },
29 | },
30 | ]);
31 | ```
32 |
33 | ### Find the average age of users by gender:
34 |
35 | 3. What is the average age of male and female users?
36 |
37 | ans:
38 |
39 | ```js
40 | db.persons.aggregate([
41 | {
42 | $group: {
43 | _id: "$gender", // Groups documents by the "gender" field
44 | averageAge: { $avg: "$age" }, // Calculates the average age for each group
45 | },
46 | },
47 | ]);
48 | ```
49 |
50 | ### Find the most common favorite fruit among users:
51 |
52 | 4. What is the most frequently mentioned favoriteFruit?
53 |
54 | ans:
55 |
56 | ```js
57 | db.persons.aggregate([
58 | {
59 | $group: {
60 | _id: "$favoriteFruit", // Groups documents by the "favoriteFruit" field
61 | count: { $sum: 1 }, // Counts the number of documents for each group
62 | },
63 | },
64 | { $sort: { count: -1 } }, // Sorts the results in descending order by count
65 | { $limit: 1 }, // Limits the output to the top 1 result
66 | ]);
67 | ```
68 |
69 | ### Find the count of users for each eyeColor:
70 |
71 | 5. How many users have each type of eyeColor?
72 |
73 | ans:
74 |
75 | ```js
76 | db.persons.aggregate([
77 | {
78 | $group: {
79 | _id: "$eyeColor", // Groups documents by the "eyeColor" field
80 | count: { $sum: 1 }, // Counts the number of documents in each group
81 | },
82 | },
83 | ]);
84 | ```
85 |
86 | ### Group by country and count users:
87 |
88 | 6. How many users are there in each country based on the company.location.country?
89 |
90 | ans:
91 |
92 | ```js
93 | db.persons.aggregate([
94 | {
95 | $group: {
96 | _id: "$company.location.country", // Groups documents by the "country" field inside "company.location"
97 | count: { $sum: 1 }, // Counts the number of documents in each group
98 | },
99 | },
100 | ]);
101 | ```
102 |
103 | ### Get the earliest and latest registered users:
104 |
105 | 7. Who are the earliest and latest registered users based on the registered field?
106 |
107 | ans:
108 |
109 | #### Finding the Latest Registered User
110 |
111 | ```js
112 | db.persons.aggregate([
113 | { $sort: { registered: -1 } }, // Sorts documents by the "registered" field in descending order (most recent first)
114 | { $limit: 1 }, // Limits the output to the top 1 document, which is the latest registered user
115 | ]);
116 | ```
117 |
118 | #### Finding the Earliest Registered User
119 |
120 | ```js
121 | db.persons.aggregate([
122 | { $sort: { registered: -1 } }, // Sorts documents by the "registered" field in descending order (most recent first)
123 | { $limit: 1 }, // Limits the output to the top 1 document, which is the latest registered user
124 | ]);
125 | ```
126 |
127 | **also can done using**
128 |
129 | ```js
130 | db.persons.aggregate([
131 | {
132 | $facet: {
133 | latestRegistered: [
134 | { $sort: { registered: -1 } }, // Sort by registered date in descending order
135 | { $limit: 1 }, // Limit to the most recent document
136 | ],
137 | earliestRegistered: [
138 | { $sort: { registered: 1 } }, // Sort by registered date in ascending order
139 | { $limit: 1 }, // Limit to the earliest document
140 | ],
141 | },
142 | },
143 | ]);
144 | ```
145 |
146 | ### Calculate the average age of users per country:
147 |
148 | 8. What is the average age of users grouped by their company.location.country?
149 |
150 | ans:
151 |
152 | ```js
153 | db.persons.aggregate([
154 | {
155 | $group: {
156 | _id: "$company.location.country", // Groups documents by the "country" field inside "company.location"
157 | averageAge: { $avg: "$age" }, // Calculates the average age for each group
158 | },
159 | },
160 | ]);
161 | ```
162 |
163 | ### Find users registered after a specific date:
164 |
165 | 9. How many users were registered after '2020-01-01'?
166 |
167 | ### Get a list of all unique tags:
168 |
169 | 10. What are all the unique tags used across all users?
170 |
171 | **Using distinct**
172 |
173 | ```js
174 | db.persons.distinct("tags");
175 | ```
176 |
177 | **_Using aggregation_**
178 |
179 | ```js
180 | db.persons.aggregate([
181 | { $unwind: "$tags" }, // Deconstructs the "tags" array, creating a separate document for each tag
182 | { $group: { _id: "$tags" } }, // Groups the documents by each unique "tag"
183 | ]);
184 | ```
185 |
186 | ### Count users having a specific tag:
187 |
188 | 11. How many users have the tag "culpa"?
189 |
190 | ```js
191 | db.persons.aggregate([
192 | { $match: { tags: "culpa" } }, // Filters documents where the "tags" array contains the value "culpa"
193 | ]);
194 | ```
195 |
196 | ### Sort users by their age:
197 |
198 | 12. Get a sorted list of users in descending order of age.
199 |
200 | ### Find users having specific tags:
201 |
202 | 13. Find all users having both 'eiusmod' and 'culpa' tags.
203 |
204 | ans:
205 |
206 | ```js
207 | db.persons.aggregate([{ $match: { tags: { $all: ["id", "ad"] } } }]);
208 | ```
209 |
210 | **or**
211 |
212 | ```js
213 | db.persons.find({ tags: { $all: ["culpa", "eiusmod"] } });
214 | ```
215 |
216 | ### Group users by age range and count them:
217 |
218 | 14. How many users fall into age groups like 20-29 etc.?
219 |
220 | ```js
221 | db.persons.aggregate([
222 | { $match: { $and: [{ age: { $gte: 20 }, age: { $lte: 29 } }] } },
223 | { $count: "People with age between 20 and 29" },
224 | ]);
225 | ```
226 |
227 | **without aggregation**
228 |
229 | ```js
230 | db.persons.find({ $and: [{ age: { $gte: 20 }, age: { $lte: 29 } }] }).count();
231 | ```
232 |
233 | ### Calculate the average number of tags per user:
234 |
235 | 15. What is the average number of tags a user has?
236 |
237 | ### Find top 5 countries with the most users:
238 |
239 | 16. Which 5 countries have the most users?
240 |
241 | ans:
242 |
243 | ```js
244 | db.persons.aggregate([
245 | { $group: { _id: "$company.location.country", userCount: { $sum: 1 } } },
246 | ]);
247 | ```
248 |
249 | ### Calculate the distribution of users registration year:
250 |
251 | 17. How many users registered each year?
252 |
253 | ```js
254 | db.persons.aggregate([
255 | {
256 | $group: {
257 | _id: { $year: { $dateFromString: { dateString: "$registered" } } }, // Extracts the year from the registered field
258 | count: { $sum: 1 }, // Counts the number of users registered each year
259 | },
260 | },
261 | ]);
262 | ```
263 |
264 | ### Find users with a specific domain in their email:
265 |
266 | 18. How many users have emails ending with '@artworlds.com'?
267 |
268 | ```js
269 | db.persons.aggregate([
270 | {
271 | $match: {
272 | "company.email": { $regex: /@artworlds\.com$/, $options: "i" }, // Match emails ending with '@artworlds.com'
273 | },
274 | },
275 | {
276 | $count: "emailCount", // Count the number of matching documents
277 | },
278 | ]);
279 | ```
280 |
281 | ### Calculate the ratio of active to inactive users:
282 |
283 | 19. What is the ratio of active (isActive: true) to inactive users?
284 |
285 | ```js
286 | db.persons.aggregate([
287 | {
288 | $facet: {
289 | activeUsers: [{ $match: { isActive: true } }, { $count: "count" }],
290 | inactiveUsers: [{ $match: { isActive: false } }, { $count: "count" }],
291 | },
292 | },
293 | {
294 | $project: {
295 | activeToInactiveRatio: {
296 | $cond: [
297 | { $eq: [{ $arrayElemAt: ["$inactiveUsers.count", 0] }, 0] },
298 | "Infinity",
299 | {
300 | $divide: [
301 | { $arrayElemAt: ["$activeUsers.count", 0] },
302 | { $arrayElemAt: ["$inactiveUsers.count", 0] },
303 | ],
304 | },
305 | ],
306 | },
307 | },
308 | },
309 | ]);
310 | ```
311 |
312 | ### Find the top 3 companies with the most users:
313 |
314 | 19. Which companies have the highest number of users associated with them?
315 |
316 | ```js
317 | db.persons.aggregate([
318 | {
319 | $group: {
320 | _id: "$company.title", // Group by company title
321 | userCount: { $sum: 1 }, // Count the number of users per company
322 | },
323 | },
324 | {
325 | $sort: { userCount: -1 }, // Sort the results in descending order of user count
326 | },
327 | {
328 | $limit: 3, // Limit the results to the top 3 companies with the highest user count
329 | },
330 | ]);
331 | ```
332 |
333 | ### Get the age distribution of users by gender:
334 |
335 | 20. What is the age distribution (e.g., count by age range) for male and female users?
336 |
337 | ```js
338 | db.persons.aggregate([
339 | {
340 | $bucket: {
341 | groupBy: "$age", // Field to group by
342 | boundaries: [0, 18, 35, 50, 100], // Define age ranges
343 | default: "Unknown", // Handle any ages outside the specified ranges
344 | output: {
345 | totalCount: { $sum: 1 }, // Count total users in each bucket
346 | maleCount: { $sum: { $cond: [{ $eq: ["$gender", "male"] }, 1, 0] } }, // Count male users in each age range
347 | femaleCount: {
348 | $sum: { $cond: [{ $eq: ["$gender", "female"] }, 1, 0] },
349 | }, // Count female users in each age range
350 | },
351 | },
352 | },
353 | ]);
354 | ```
355 |
356 | ### Find users with missing or null fields:
357 |
358 | 21. How many users have missing or null values for critical fields such as name, age, or company.email?
359 |
360 | ```js
361 | db.persons.aggregate([
362 | {
363 | $match: {
364 | $or: [
365 | { name: { $in: [null, ""] } }, // Check for null or empty name
366 | { age: { $in: [null, ""] } }, // Check for null or empty age
367 | { "company.email": { $in: [null, ""] } }, // Check for null or empty company.email
368 | ],
369 | },
370 | },
371 | {
372 | $count: "missingFieldsCount", // Count the number of users with missing critical fields
373 | },
374 | ]);
375 | ```
376 |
377 | ### Find users with a specific country and favorite fruit:
378 |
379 | 22. How many users from 'Italy' have 'banana' as their favoriteFruit?
380 |
381 | ```js
382 | db.persons.aggregate([
383 | {
384 | $match: {
385 | "company.location.country": "Italy", // Filter users from Italy
386 | favoriteFruit: "banana", // Filter users whose favorite fruit is banana
387 | },
388 | },
389 | {
390 | $count: "bananaLoversCount", // Count the number of users matching the criteria
391 | },
392 | ]);
393 | ```
394 |
395 | ### Find the maximum, minimum, and average age:
396 |
397 | 23. What is the maximum, minimum, and average age of all users?
398 |
399 | ```js
400 | db.persons.aggregate([
401 | {
402 | $group: {
403 | _id: null, // We don't need to group by any specific field, so we set _id to null
404 | maxAge: { $max: "$age" }, // Calculate the maximum age
405 | minAge: { $min: "$age" }, // Calculate the minimum age
406 | avgAge: { $avg: "$age" }, // Calculate the average age
407 | },
408 | },
409 | {
410 | $project: {
411 | _id: 0, // Exclude the _id field from the result
412 | maxAge: 1,
413 | minAge: 1,
414 | avgAge: 1,
415 | },
416 | },
417 | ]);
418 | ```
419 |
420 | ### Top 5 tags by frequency:
421 |
422 | 24. What are the 5 most frequently used tags?
423 |
424 | ```js
425 | db.persons.aggregate([
426 | {
427 | $unwind: "$tags", // Deconstructs the tags array into individual documents
428 | },
429 | {
430 | $group: {
431 | _id: "$tags", // Groups by each tag
432 | count: { $sum: 1 }, // Counts the occurrences of each tag
433 | },
434 | },
435 | {
436 | $sort: { count: -1 }, // Sorts the tags by their count in descending order
437 | },
438 | {
439 | $limit: 5, // Limits the result to the top 5 most frequent tags
440 | },
441 | ]);
442 | ```
443 |
444 | ### Users with the longest time since registration:
445 |
446 | 25. Who are the top 10 users with the longest time since they registered?
447 |
448 | ```js
449 | db.persons.aggregate([
450 | {
451 | $sort: { registered: 1 }, // Sorts by registration date in ascending order
452 | },
453 | {
454 | $limit: 10, // Limits to the top 10 users
455 | },
456 | ]);
457 | ```
458 |
459 | ### Find users grouped by both favoriteFruit and eyeColor:
460 |
461 | 26. How many users prefer each combination of favoriteFruit and eyeColor?
462 |
463 | ```js
464 | db.persons.aggregate([
465 | {
466 | $group: {
467 | _id: { favoriteFruit: "$favoriteFruit", eyeColor: "$eyeColor" }, // Group by both favoriteFruit and eyeColor
468 | count: { $sum: 1 }, // Count the number of users for each combination
469 | },
470 | },
471 | {
472 | $sort: { count: -1 }, // Optional: Sort the results by count in descending order
473 | },
474 | ]);
475 | ```
476 |
--------------------------------------------------------------------------------
/MongoDB/MongoDb.md:
--------------------------------------------------------------------------------
1 | # SQL vs NoSQL: A Comparison
2 |
3 | SQL (Structured Query Language) and NoSQL (Not Only SQL) databases are two major types of database management systems, each with its own set of strengths, weaknesses, and ideal use cases
4 |
5 | ## 1. SQL DATABASES
6 |
7 | - SQL databases are relational, meaning they store data in structured tables with rows and columns
8 | - SQL databases enforce a fixed schema, meaning the structure of data (tables, columns, data types) must be defined before data can be inserted. This schema is usually strict and requires changes to be planned and executed carefully.
9 | - Data in SQL databases is often normalized to reduce redundancy, and relationships between tables are established using foreign keys.
10 |
11 | ### Ideal For:
12 |
13 | - Complex queries and transactions
14 | - Applications requiring strong consistency
15 | - Structured data with defined relationships
16 | - Enterprise applications (e.g., ERP, CRM)
17 |
18 | **Examples**
19 |
20 | - MySQL
21 | - PostgreSQL
22 | - Oracle Database
23 | - Microsoft SQL Server
24 |
25 | ## 1. NoSQL DATABASES
26 |
27 | - NoSQL databases can be document-based, key-value stores, column-family stores, or graph databases, allowing for a more flexible data model.
28 | - NoSQL databases are typically schema-less or have a dynamic schema, meaning they can store unstructured or semi-structured data. This flexibility allows for easier modifications and varied data structures
29 | - NoSQL databases often store data in a demoralized form, with related data embedded within the same document or object, reducing the need for complex joins.
30 |
31 | ### Ideal For:
32 |
33 | - Large-scale distributed systems
34 | - Applications requiring high availability and scalability
35 | - Unstructured or semi-structured data (e.g., JSON, XML)
36 | - Real-time analytics, content management, IoT, big data applications
37 |
38 | **NoSQL Databases:**
39 |
40 | - MongoDB (Document-based)
41 | - Redis (Key-value store)
42 | - Cassandra (Column-family store)
43 | - Neo4j (Graph database)
44 |
45 | # MongoDB
46 |
47 | MongoDB is a NoSQL, document-oriented database that stores data in flexible, JSON-like documents..
48 |
49 | In MongoDB, **collections** and **documents** are fundamental concepts used to store and manage data.
50 |
51 | ## Collection
52 |
53 | A collection in MongoDB is a grouping of MongoDB documents. It's similar to a table in a relational database.
54 |
55 | - **Schema-less:** Collections do not enforce a schema, meaning that documents within the same collection can have different fields or data types.
56 |
57 | - **Implicit Creation:** Collections are created implicitly when you insert a document into them. You don't need to explicitly create a collection before using it.
58 |
59 | - **Organization:** Collections are stored within a database, and a single database can have multiple collections.
60 |
61 | **Example:** In a bookstore database, you might have collections such as books, authors, and genres.
62 |
63 | ## Document
64 |
65 | A document in MongoDB is a record in a collection. Documents are stored in a format called BSON (Binary JSON) but are typically represented as JSON-like structures.
66 |
67 | - **Flexibility:** Documents can have nested fields, arrays, and even other documents as values.
68 |
69 | - **Unique Identifier:** Each document has a unique identifier called `\_id`, which is automatically generated by MongoDB if not provided.
70 |
71 | - **Schema-less:** Documents are flexible and schema-less, allowing you to store different types of data in the same collection.
72 |
73 | **Example:** A document in the books collection might look like this:
74 |
75 | ```js
76 | {
77 | "_id": { "$oid": "66c4476627f54d54af6b1c24" },
78 | "title": "Book1",
79 | "author": "Author 1",
80 | "genre": ["genre1", "genre2", "genre3"],
81 | "rating": 9,
82 | "reviews": [
83 | { "user": "User1", "comment": "Great book!", "rating": 5 },
84 | { "user": "User2", "comment": "Enjoyed reading", "rating": 4 }
85 | ]
86 | }
87 |
88 | ```
89 |
90 | ## MongoD
91 |
92 | **mongod** is the primary process that runs the MongoDB server. It stands for "Mongo Daemon". When you run mongod, it starts the MongoDB server, allowing it to listen for connections, handle database operations, and manage data storage.
93 |
94 | - **Starting the Server:** To start the MongoDB server, you typically run the mongod command in your terminal
95 |
96 | ```js
97 | mongod;
98 | ```
99 |
100 | By default, it starts the server on port `27017` and uses the default data directory (`/data/db` on Linux/macOS or `C:\data\db` on Windows).
101 |
102 | ## BSON
103 |
104 | BSON is a binary encoding of JSON-like documents. Unlike JSON, which is text-based, BSON is designed to be efficient in both storage and retrieval, making it more suitable for high-performance applications.
105 |
106 | BSON supports additional data types that are not available in JSON. Some of these include:
107 |
108 | - **ObjectId:** A 12-byte unique identifier used as a primary key in MongoDB documents.
109 | - **Date:** Represents date and time, which is stored as a 64-bit integer.
110 | - **Binary Data:** Allows storage of raw binary data.
111 | - **Int32 and Int64:** Distinguishes between 32-bit and 64-bit integers.
112 | - **Decimal128:** High-precision decimal floating-point format for storing financial data.
113 |
114 | ### Why BSON is Used in MongoDB:
115 |
116 | - **Performance:** BSON's binary format allows MongoDB to efficiently encode and decode documents, making operations faster than they would be with plain text JSON.
117 |
118 | - **Rich Data Types:** BSON supports a wider range of data types than JSON, allowing MongoDB to store more complex data structures.
119 |
120 | - **Storage Optimization:** BSON is more compact than JSON, which helps in reducing storage space, especially for large-scale databases.
121 |
122 | ## ObjectId
123 |
124 | In MongoDB, an ObjectId is a unique identifier that is automatically generated for each document in a collection if no `_id` field is provided when the document is created. An ObjectId is a `12-byte` (96-bit) value consisting of different parts that together ensure uniqueness.
125 |
126 | An ObjectId consists of the following parts:
127 |
128 | 1. **Timestamp (4 bytes):**
129 |
130 | The first 4 bytes (32 bits) represent the Unix timestamp in seconds when the ObjectId was generated. This allows you to determine the creation time of a document by extracting the timestamp from the ObjectId.
131 |
132 | 2. **Machine Identifier (3 bytes):**
133 |
134 | The next 3 bytes (24 bits) represent a unique identifier of the machine (host) where the ObjectId was generated. This is usually derived from the hostname or IP address.
135 |
136 | 3. **Process Identifier (2 bytes):**
137 |
138 | The following 2 bytes (16 bits) are used to identify the specific process on the machine where the ObjectId was generated. This ensures uniqueness among different processes running on the same machine.
139 |
140 | 4. **Counter (3 bytes):**
141 |
142 | The final 3 bytes (24 bits) are a randomly incremented counter initialized to a random value. This counter ensures that ObjectIds generated in the same second on the same machine are unique.
143 |
144 | ```js
145 | ObjectId("64b5f30e27f54d54af6b1c24")
146 | ```
147 | Breaking this down into its parts:
148 |
149 | * **64b5f30e:** The first 4 bytes (64b5f30e) represent the timestamp when this ObjectId was generated.
150 | * **27f54d:** The next 3 bytes (27f54d) are the machine identifier.
151 | * **54af:** The following 2 bytes (54af) are the process identifier.
152 | * **6b1c24:** The last 3 bytes (6b1c24) are the incrementing counter.
153 |
154 | ## Namespace
155 |
156 | The concatenation of the collection name and database name is called a namespace
157 |
158 | It providing a unique identifier for each collection. It plays a crucial role in organizing, managing, and interacting with data within the MongoDB system
159 |
160 | ```js
161 | .
162 | ```
163 |
164 | ## Data Model Design
165 |
166 | MongoDB provides two types of data models:
167 |
168 | **Embedded data model** and **Normalized data model**. Based on the requirement, you can use either of the models while preparing your document.
169 |
170 | ### Embedded Data Model (de-normalized)
171 |
172 | In this model, you can have (embed) all the related data in a single document, it is also known as de-normalized data model.
173 |
174 | **For example:** assume we are getting the details of employees in three different documents namely, 'Personal_details', 'Contact' and, 'Address', you can embed all the three documents in a single one
175 |
176 | **Advantages:**
177 |
178 | - **Faster Read Operations:** Since all related data is stored together, accessing the document is quick and efficient.
179 |
180 | - **Atomicity:** Updates to a single document are atomic, which means that changes are either fully completed or not applied at all.
181 |
182 | - **Simpler Queries:** Fewer joins or lookups are required, simplifying your query logic.
183 |
184 | ### Normalized Data Model
185 |
186 | In a Normalized Data Model, related data is stored in separate documents, and the original document contains references (usually by ObjectId) to these related documents. This model is more akin to traditional relational database design, where data is normalized across multiple tables.
187 |
188 | **For example:** assume details of employees namely, 'Personal_details', 'Contact' and, 'Address', you can store this in 3 document with separate ID
189 |
190 | **Advantages:**
191 |
192 | - **Data Integrity:** Data is stored once and referenced as needed, reducing redundancy and the risk of inconsistencies.
193 |
194 | - **Flexibility:** You can easily update or extend the related data without affecting the original document.
195 |
196 | - **Efficient Storage:** If related data is large or frequently reused across multiple documents, a normalized model reduces duplication.
197 |
198 | ## MongoDB Shell Commands
199 |
200 | _For this documentation, we’ll use a `bookstore` database as our example. Each book is represented as a document containing information like title, author, genre, rating, and user reviews._
201 |
202 | ### Database Management
203 |
204 | - **`show dbs`** - Lists all databases.
205 | - **`use `** - Creates a new database or switches to an existing one.
206 | - **`db`** - Prints the name of the current database.
207 | - **`show collections`** - Lists all collections in the current database.
208 | - **`db.dropDatabase()`** - Delete the Data Base (After switching to that DB)
209 | - **`db.collection_name.drop()`** Delete a Collection from a DB
210 | - **`cls`** - Clears the screen.
211 | - **`help`** - Lists all available commands.
212 | - **`exit`** - Exits the MongoDB shell.
213 |
214 | ### Creating Collections
215 |
216 | - **Implicit Creation:** Collections are created automatically when a document is inserted into a non-existent collection.
217 |
218 | ```js
219 | db.books.insertOne({
220 | title: "Book1",
221 | author: "author 1",
222 | genre: ["genre1", "genre2", "genre3"],
223 | rating: 9,
224 | reviews: [
225 | { user: "User1", comment: "Great book!", rating: 5 },
226 | { user: "User2", comment: "Enjoyed reading", rating: 4 },
227 | ],
228 | });
229 | ```
230 |
231 | - **Explicit Creation\***
232 |
233 | ```js
234 | db.createCollection("books");
235 | ```
236 |
237 | ### Document Insertion
238 |
239 | - **Single Document:**
240 |
241 | ```js
242 | db.books.insertOne({
243 | title: "Book1",
244 | author: "author 1",
245 | genre: ["genre1", "genre2", "genre3"],
246 | rating: 9,
247 | reviews: [
248 | { user: "User1", comment: "Great book!", rating: 5 },
249 | { user: "User2", comment: "Enjoyed reading", rating: 4 },
250 | ],
251 | });
252 | ```
253 |
254 | - **Multiple Documents:**
255 |
256 | ```js
257 | db.books.insertMany([
258 | {
259 | title: "Book2",
260 | author: "author 2",
261 | genre: ["genre1", "genre4"],
262 | rating: 8,
263 | reviews: [{ user: "User3", comment: "Good read", rating: 4 }],
264 | },
265 | {
266 | title: "Book3",
267 | author: "author 3",
268 | genre: ["genre2", "genre5"],
269 | rating: 7,
270 | reviews: [],
271 | },
272 | ]);
273 | ```
274 |
275 | ### Querying Data
276 |
277 | 1. **Find All Documents:**
278 |
279 | ```js
280 | db.books.find();
281 |
282 | // return the complete book collection
283 | ```
284 |
285 | 2. **Find with Filter:**
286 |
287 | ```js
288 | db.books.find({ author: "Author 1" });
289 |
290 | // return all documents with author === Author 1
291 | ```
292 |
293 | 3. **Select Specific Fields**
294 |
295 | ```js
296 | db.books.find({ author: "Author 1" }, { title: 1, author: 1 });
297 |
298 | // return Author 1 but only get data of title,author,id
299 |
300 | /*
301 | [
302 | {
303 | "_id": { "$oid": "66c4476627f54d54af6b1c24" },
304 | "title": "Book1",
305 | "author": "Author 1"
306 | }
307 | ]
308 | */
309 | ```
310 |
311 | 4. **Find One Document:**
312 |
313 | ```js
314 | db.books.findOne({ author: "author 1" });
315 |
316 | // return only one document
317 | ```
318 |
319 | 5. **Find Only one Field from Document**
320 |
321 | ```js
322 | db.books.find({}, { _id: 0, author: 1 });
323 |
324 | // return all authors
325 | ```
326 |
327 | ### Using the distinct Method:
328 |
329 | The distinct method in MongoDB is used to find unique values for a specified field in a collection
330 |
331 | Syntax:
332 |
333 | ```js
334 | db.collection.distinct(field, query);
335 | ```
336 |
337 | - **field**: The name of the field for which you want to find distinct values.
338 | - **query**: An optional filter to limit the documents considered.
339 |
340 | example :
341 |
342 | 1.
343 |
344 | ```js
345 | db.books.distinct("genre");
346 |
347 | // returns all values included in genre key
348 | ```
349 |
350 | 2.
351 |
352 | ```js
353 | db.books.distinct("genre", { rating: 9 });
354 |
355 | // return all genre that has comes under rating 9
356 | ```
357 |
358 | ### Sorting and Limiting and Skipping
359 |
360 | 1. **Count Documents:**
361 |
362 | ```js
363 | db.books.find().count();
364 |
365 | // return a number which the count of total documents
366 | ```
367 |
368 | 2. **Limit the Number of Results:**
369 |
370 | ```js
371 | db.books.find().limit(2);
372 |
373 | // only returns 2 documents because the limit == 2
374 | ```
375 |
376 | 3. **Skip Documents**
377 |
378 | ```js
379 | db.books.find().skip(4);
380 |
381 | // Skip first 4 documents and return from 5 th document
382 | ```
383 |
384 | 4. **Sort Results:**
385 |
386 | ```js
387 | db.books.find().sort({ rating: -1 });
388 |
389 | // Sort by rating in descending order
390 | ```
391 |
392 | ```js
393 | db.books.find().sort({ title: 1 });
394 |
395 | // Sort by title in ascending order
396 | ```
397 |
398 | ### Complex Queries and Operators
399 |
400 | **Comparison Operators:**
401 |
402 | 1. **$gt** - Greater than
403 |
404 | ```js
405 | db.books.find({ rating: { $gt: 8 } });
406 |
407 | // return documents with rating is greater than 8
408 | ```
409 |
410 | 2. **$lt** - Less than
411 |
412 | ```js
413 | db.books.find({ rating: { $lt: 8 } });
414 |
415 | // Returns documents where the rating is less than 8
416 | ```
417 |
418 | 3. **$gte** - Greater than or equal to
419 |
420 | ```js
421 | db.books.find({ rating: { $gte: 8 } });
422 |
423 | // Returns documents where the rating is greater than or equal to 8
424 | ```
425 |
426 | 4. **$lte** - Less than or equal to
427 |
428 | ```js
429 | db.books.find({ rating: { $lte: 8 } });
430 |
431 | // Returns documents where the rating is less than or equal to 8
432 | ```
433 |
434 | **Regex Operator**
435 |
436 | In MongoDB, you can use regular expressions (regex) to perform pattern matching in queries. Regex can be very useful for searching text fields based on patterns rather than exact matches
437 |
438 | Syntax:
439 |
440 | ```js
441 | db.collection.find({ "field": { $regex: /pattern/, $options: "options" } })
442 | ```
443 |
444 | 1. To find the documents with Author name start with A
445 |
446 | ```js
447 | db.books.find({ "author": { $regex: /^A/ } })
448 | ```
449 |
450 | 2. To Find all documents where the title field contains any character followed by "Book".
451 |
452 | ```js
453 | db.books.find({ "title": { $regex: /.Book/ } })
454 | ```
455 |
456 | 3. To Find all documents Author names end with s
457 |
458 | ```js
459 | db.books.find({ "author": { $regex: /s$/ } })
460 | ```
461 |
462 | **Logical Operators:**
463 |
464 | 1. **$or**
465 |
466 | Matches documents that satisfy at least one of the conditions.
467 |
468 | ```js
469 | db.books.find({
470 | $or: [{ rating: 9 }, { author: "Author 2" }],
471 | });
472 |
473 | // Returns documents where either the rating is 9 or the author is "Author 2"
474 | ```
475 |
476 | 2. **$and**
477 |
478 | Matches documents that satisfy all the given conditions
479 |
480 | ```js
481 | db.books.find({
482 | $and: [{ rating: { $gte: 8 } }, { genre: "genre1" }],
483 | });
484 |
485 | // Returns documents where the rating is greater than or equal to 8 and the genre includes "genre1"
486 | ```
487 |
488 |
489 |
490 | ### Querying Nested Documents
491 |
492 | You can query nested documents by specifying the path to the field within the nested structure.
493 |
494 | ```js
495 | db.books.find({ "reviews.user": "User1" });
496 |
497 | // Returns documents where there is a review with the user "User1"
498 | ```
499 |
500 | ### Updating Documents
501 |
502 | 1. **Update a Single Document:**
503 |
504 | This operation updates the first document that matches the filter criteria.
505 |
506 | ```js
507 | db.books.updateOne({ title: "Book1" }, { $set: { rating: 10 } });
508 |
509 | // Updates the rating of the book titled "Book1" to 10
510 | ```
511 |
512 | 2. **Update Multiple Documents:**
513 |
514 | This operation updates all documents that match the filter criteria.
515 |
516 | ```js
517 | db.books.updateMany({ author: "Author 1" }, { $set: { rating: 8 } });
518 |
519 | // Updates the rating of all books authored by "Author 1" to 8
520 | ```
521 |
522 | 3. **Replace a Document:**
523 |
524 | This operation replaces an entire document with a new one.
525 |
526 | ```js
527 | db.books.replaceOne(
528 | { title: "Book1" },
529 | { title: "New Title", author: "New Author", rating: 7 }
530 | );
531 |
532 | // Replaces the entire document with a new one having the specified title, author, and rating
533 | ```
534 |
535 | ### upsert
536 |
537 | In MongoDB, an upsert operation is a combination of `update` and `insert`. The **upsert** option allows an update operation to insert a new document if no document matches the specified query criteria. If a matching document is found, it updates that document; if no matching document is found, it inserts a new document into the collection.
538 |
539 | ```js
540 | db.collection.updateOne(
541 | { }, // The filter criteria to find documents
542 | { }, // The update operation to apply
543 | { upsert: true } // The upsert option
544 | )
545 | ```
546 |
547 | ### Querying by Array Values
548 |
549 | You can query documents where an array field contains a specific value.
550 |
551 | ```js
552 | db.books.find({ genre: "genre1" });
553 |
554 | // Returns documents where the genre array includes "genre1"
555 | ```
556 |
557 | 1. **$in**
558 |
559 | Matches documents where the value of a field equals any value in the specified array
560 |
561 | ```js
562 | db.books.find({
563 | genre: { $in: ["genre1", "genre2"] },
564 | });
565 |
566 | // Returns documents where the genre field includes either "genre1" or "genre2"
567 | ```
568 |
569 | 2. **$nin**
570 |
571 | The `$nin` operator matches documents where the value of a field does not equal any value in the specified array.
572 |
573 | ```js
574 | db.books.find({
575 | genre: { $nin: ["genre1", "genre2"] },
576 | });
577 |
578 | // Returns documents where the genre field does not include "genre1" or "genre2"
579 | ```
580 |
581 | 3. **$all**
582 |
583 | The `$all` operator matches arrays that contain all the specified elements. Unlike `$in`, which matches any of the specified elements, `$all` requires all specified elements to be present in the array.
584 |
585 | ```js
586 | db.books.find({ genre: { $all: ["genre1", "genre2"] } });
587 |
588 | // Returns documents where the genre array includes both "genre1" and "genre2"
589 | ```
590 |
591 | 4. **$push**
592 |
593 | This operation adds a new element to an array within a document.
594 |
595 | ```js
596 | db.books.updateOne(
597 | { title: "Book1" },
598 | {
599 | $push: { reviews: { user: "User3", comment: "Another review", rating: 4 } },
600 | }
601 | );
602 |
603 | // Adds a new review to the reviews array for the book titled "Book1"
604 | ```
605 |
606 | 5. **$pull**
607 |
608 | This operation removes an element from an array within a document.
609 |
610 | ```js
611 | db.books.updateOne(
612 | { title: "Book1" },
613 | { $pull: { reviews: { user: "User1" } } }
614 | );
615 |
616 | // Removes the review by "User1" from the reviews array for the book titled "Book1"
617 | ```
618 |
619 | 6. **$addToSet**
620 |
621 | The `$addToSet` operator adds a value to an array only if it does not already exist
622 |
623 | ```js
624 | db.books.updateOne({ title: "Book1" }, { $addToSet: { genre: "genre4" } });
625 | // Adds "genre4" to the genre array of "Book1" if it's not already present
626 | ```
627 |
628 | 7. **$pop**
629 |
630 | The `$pop` operator removes either the first or last element from an array, depending on the value passed (1 for the last element, -1 for the first).
631 |
632 | ```js
633 | db.books.updateOne({ title: "Book1" }, { $pop: { reviews: 1 } });
634 | // Removes the last review from the reviews array of "Book1"
635 | ```
636 |
637 | 8. **$pullAll**
638 |
639 | The `$pullAll` operator removes all instances of the specified values from an array.
640 |
641 | ```js
642 | db.books.updateOne(
643 | { title: "Book1" },
644 | { $pullAll: { genre: ["genre1", "genre3"] } }
645 | );
646 | // Removes "genre1" and "genre3" from the genre array of "Book1"
647 | ```
648 |
649 | 9. **$elemMatch**
650 |
651 | The `$elemMatch` operator matches documents where at least one element in the array matches all the specified criteria. This is particularly useful for arrays of sub documents.
652 |
653 | ```js
654 | db.books.find({
655 | reviews: { $elemMatch: { rating: { $gte: 8 }, reviewText: /excellent/i } },
656 | });
657 |
658 | // Returns documents where at least one review in the reviews array has a rating of 8 or higher and contains the word "excellent"
659 | ```
660 |
661 | 10. **$slice**
662 |
663 | The `$slice` operator is used in projections to return a subset of the array
664 |
665 | ```js
666 | db.books.find({}, { reviews: { $slice: 3 } });
667 |
668 | // Returns only the first 3 reviews from the reviews array in each document
669 | ```
670 |
671 | 11. **$each**
672 |
673 | The `$each` modifier is used in conjunction with $push or `$addToSet` to add multiple elements to an array in a single operation.
674 |
675 | ```js
676 | db.books.updateOne(
677 | { title: "Book1" },
678 | { $push: { genre: { $each: ["genre4", "genre5"] } } }
679 | );
680 |
681 | // Adds "genre4" and "genre5" to the genre array in the document with title "Book1"
682 | ```
683 |
684 | 12. **$position**
685 |
686 | The `$position` modifier is used with $push to insert elements at a specified position within an array.
687 |
688 | ```js
689 | db.books.updateOne(
690 | { title: "Book1" },
691 | { $push: { genre: { $each: ["genre0"], $position: 0 } } }
692 | );
693 |
694 | // Inserts "genre0" at the beginning of the genre array in the document with title "Book1"
695 | ```
696 |
697 | 13. **$sort**
698 |
699 | The $sort modifier is used with $push to sort the array after modifying it.
700 |
701 | ```js
702 | db.books.updateOne(
703 | { title: "Book1" },
704 | { $push: { genre: { $each: ["genre4"], $sort: 1 } } }
705 | );
706 |
707 | // Adds "genre4" to the genre array and sorts the array in ascending order
708 | ```
709 |
710 |
711 |
712 | ### Field Update Operators
713 |
714 | Field update operators allow you to modify specific fields in documents. These operators are often used with update methods like `updateOne()` and `updateMany()`.
715 |
716 | 1. **$inc**
717 |
718 | The `$inc` operator increases the value of a field by a specified amount. If the field does not exist, it will be created.
719 |
720 | ```js
721 | db.books.updateOne({ title: "Book1" }, { $inc: { rating: 1 } });
722 | // Increases the rating of "Book1" by 1
723 | ```
724 |
725 | 2. **$mul**
726 |
727 | The `$mul` operator multiplies the value of a field by a specified amount.
728 |
729 | ```js
730 | db.books.updateOne({ title: "Book1" }, { $mul: { rating: 2 } });
731 | // Doubles the rating of "Book1"
732 | ```
733 |
734 | 3. **$rename**
735 |
736 | The `$rename` operator changes the name of a field in a document.
737 |
738 | ```js
739 | db.books.updateOne({ title: "Book1" }, { $rename: { author: "writer" } });
740 | // Renames the "author" field to "writer" in the "Book1" document
741 | ```
742 |
743 | 4. **$unset**
744 |
745 | The `$unset` operator deletes a specified field from a document.
746 |
747 | ```js
748 | db.books.updateOne({ title: "Book1" }, { $unset: { rating: "" } });
749 | // Removes the "rating" field from the "Book1" document
750 | ```
751 |
752 | 5. **$exists**
753 |
754 | The `$exists` operator in MongoDB is used to query documents based on whether a specific field exists or not in the document
755 |
756 | ```js
757 | db.books.find({ "author": { $exists: true } })
758 |
759 | //return all documents in the books collection where the author field exists
760 | ```
761 | 6. **$add**
762 |
763 |
764 | ### Geospatial Queries
765 |
766 | MongoDB supports geospatial queries, allowing you to perform location-based queries on geospatial data.
767 |
768 | 1. **$geoWithin**
769 |
770 | The $geoWithin operator finds documents located within a specified geographic area.
771 |
772 | ```js
773 | db.places.find({
774 | location: {
775 | $geoWithin: {
776 | $geometry: {
777 | type: "Polygon",
778 | coordinates: [
779 | [
780 | [longitude1, latitude1],
781 | [longitude2, latitude2],
782 | [longitude3, latitude3],
783 | [longitude1, latitude1],
784 | ],
785 | ],
786 | },
787 | },
788 | },
789 | });
790 | // Returns all places within the defined polygon area
791 | ```
792 |
793 | 2. **$near**
794 |
795 | The $near operator finds documents that are close to a specified point. It can be used with both 2D and 2DSphere indexes.
796 |
797 | ```js
798 | db.places.find({
799 | location: {
800 | $near: {
801 | $geometry: {
802 | type: "Point",
803 | coordinates: [longitude, latitude],
804 | },
805 | $maxDistance: 1000,
806 | },
807 | },
808 | });
809 | // Returns all places within 1000 meters of the specified location
810 | ```
811 |
812 | ### Deleting Documents
813 |
814 | 1. **Delete a Single Document:**
815 | This operation deletes the first document that matches the filter criteria.
816 |
817 | ```js
818 | db.books.deleteOne({ title: "Book1" });
819 |
820 | // Deletes the document where the title is "Book1"
821 | ```
822 |
823 | 2. **Delete Multiple Documents:**
824 | This operation deletes all documents that match the filter criteria.
825 |
826 | ```js
827 | db.books.deleteMany({ author: "Author 1" });
828 |
829 | // Deletes all documents where the author is "Author 1"
830 | ```
831 |
832 | ## Indexing
833 |
834 | Indexes improve the performance of read operations by allowing the database to quickly locate data.
835 |
836 | 1. **Create an Index:**
837 | This command creates an index on the specified field.
838 |
839 | ```js
840 | db.books.createIndex({ title: 1 });
841 |
842 | // Creates an index on the title field in ascending order
843 | ```
844 |
845 | Output:
846 |
847 | ```json
848 | "Index creation successful: title_1"
849 | ```
850 |
851 | 2. **View Indexes:**
852 | This command lists all the indexes on the collection.
853 |
854 | ```js
855 | db.books.getIndexes();
856 |
857 | // Displays all the indexes created on the books collection
858 | ```
859 |
860 | 3. **Drop an Index:**
861 | This command removes the specified index from the collection.
862 |
863 | ```js
864 | db.books.dropIndex({ title: 1 });
865 |
866 | // Drops the index on the title field
867 | ```
868 |
869 | Output :
870 |
871 | ```json
872 | "Index drop successful: title_1"
873 | ```
874 |
875 | ## TYPES OF INDEXES
876 |
877 | ### 1. Single-Field Index
878 |
879 | Indexes a single field in a document. It improves the efficiency of queries that match or sort by that specific field.
880 |
881 | Example:
882 | ```js
883 | db.collection.createIndex({ "fieldName": 1 })
884 | ```
885 |
886 | The 1 indicates an ascending order; -1 would indicate a descending order
887 |
888 | ### 2. Compound Index
889 |
890 | Indexes multiple fields within a document. It is beneficial for queries that filter on multiple fields.
891 |
892 | Example:
893 | ```js
894 | db.collection.createIndex({ "field1": 1, "field2": -1 })
895 | ```
896 |
897 | This creates an index on field1 in ascending order and field2 in descending order.
898 |
899 | ### 3. Multikey Index
900 |
901 | Indexes fields that contain arrays. Each element of the array is indexed separately, which allows for efficient querying of documents that have array fields.
902 |
903 | Example:
904 | ```js
905 | db.collection.createIndex({ "arrayField": 1 })
906 | ```
907 | ### 4. Text Index
908 |
909 | Indexes string content for text search. It supports queries using $text and provides capabilities like text search with operators such as `$search` and `$language`.
910 |
911 | Example:
912 | ```js
913 | db.collection.createIndex({ "textField": "text" })
914 | ```
915 |
916 | ### 5. Hashed Index
917 |
918 | Hashes the value of the indexed field. It is useful for queries that involve equality checks (=). It is not suitable for range queries.
919 |
920 | Example:
921 |
922 | ```js
923 | db.collection.createIndex({ "fieldName": "hashed" })
924 | ```
925 |
926 | ### 6. Wildcard Index
927 |
928 | Indexes all fields or a subset of fields within documents that match a specific pattern, particularly useful when working with documents containing unknown or varying fields.
929 |
930 | Example:
931 | ```js
932 | db.collection.createIndex({ "$**": 1 })
933 | ```
934 |
935 | ### 7. Partial Index
936 |
937 | Indexes only documents that meet a specific filter expression. It can be used to create smaller and more efficient indexes when not all documents are relevant for a given query.
938 |
939 | Example:
940 | ```js
941 | db.collection.createIndex({ "fieldName": 1 }, { partialFilterExpression: { "status": "active" } })
942 | ```
943 |
944 | ### 8. Sparse Index
945 |
946 | Only indexes documents where the indexed field exists and has a non-null value. It can be used to reduce the size of an index by excluding documents that do not have the indexed field.
947 |
948 | Example:
949 | ```js
950 | db.collection.createIndex({ "optionalField": 1 }, { sparse: true })
951 | ```
952 |
953 | ### 9. TTL (Time to Live) index
954 |
955 | A TTL (Time to Live) index in MongoDB is a special type of index that automatically removes documents from a collection after a certain period of time. This is particularly useful for managing collections that store temporary or time-sensitive data, such as session information, logs, or cached data.
956 |
957 | #### How TTL Index Works
958 |
959 | - **Expiration Time:** You define a TTL index on a date field in your documents. The index will automatically remove documents from the collection once the specified amount of time has passed since the value in that date field.
960 |
961 | - **Background Process:** MongoDB runs a background process that checks for expired documents regularly (usually every 60 seconds) and removes them.
962 |
963 | To create a TTL index, you use the `expireAfterSeconds` option when creating an index on a `date` field.
964 |
965 | **Example:**
966 |
967 | Suppose you have a collection called sessions that stores user session information. Each session has a createdAt field that stores the `date` and time when the session was created. If you want to automatically delete sessions after 1 hour (3600 seconds), you would create a TTL index like this:
968 |
969 | ```js
970 | db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 });
971 | ```
972 |
973 | - **Only Date Fields:** TTL indexes only work on fields that store `Date` or `ISODate` values.
974 | - **Automatic Expiration:** Once a document's `date` field value is older than the specified expireAfterSeconds value, MongoDB will automatically delete that document.
975 | - **Single Field Index:** TTL indexes can only be created on a single field, not on compound fields.
976 | - **Background Deletion:** The deletion of expired documents happens in the background and may not be immediate (typically checked every 60 seconds).
977 |
978 | #### Use Cases for TTL Index:
979 |
980 | - **Session Management:** Automatically expire user sessions after a set period of inactivity.
981 |
982 | - **Log Retention:** Remove old log entries after a certain period.
983 |
984 | - **Temporary Data:** Clean up temporary or cache data that is no longer needed.
985 |
986 | ### 10. Geospatial Index
987 |
988 | MongoDB provides robust support for geospatial data and queries, allowing you to store and query data that represents locations on the Earth. This is particularly useful for applications involving location-based services, mapping, and geographical data analysis
989 |
990 | #### Types of Geospatial Indexes
991 |
992 | MongoDB offers two types of geospatial indexes:
993 |
994 | 1. **2dsphere Index:**
995 |
996 | **Purpose:** Supports queries that calculate geometries on an Earth-like sphere, such as points, lines, and polygons. It's the most commonly used geospatial index and is suitable for data represented in `GeoJSON` format.
997 |
998 | **Data Types:** Supports GeoJSON objects (Point, LineString, Polygon, etc.) and legacy coordinate pairs (latitude, longitude).
999 |
1000 | **Use Cases:** Queries involving proximity (e.g., finding nearby locations), intersections, and containment within geometries.
1001 |
1002 | **Creating a 2dsphere Index**
1003 |
1004 | Suppose you have a collection named places that stores location data with GeoJSON format:
1005 |
1006 | ```js
1007 | {
1008 | "_id": 1,
1009 | "name": "Central Park",
1010 | "location": {
1011 | "type": "Point",
1012 | "coordinates": [-73.9712, 40.7831]
1013 | }
1014 | }
1015 | ```
1016 |
1017 | You can create a 2dsphere index on the location field:
1018 |
1019 | ```js
1020 | db.places.createIndex({ location: "2dsphere" });
1021 | ```
1022 |
1023 | #### 2dsphere Index Queries:
1024 |
1025 | Once a geospatial index is in place, you can perform various geospatial queries, such as:
1026 |
1027 | 1. **$near:**
1028 |
1029 | Finds documents near a specified point.
1030 |
1031 | ```js
1032 | db.places.find({
1033 | location: {
1034 | $near: {
1035 | $geometry: {
1036 | type: "Point",
1037 | coordinates: [-73.9712, 40.7831],
1038 | },
1039 | $maxDistance: 5000, // meters
1040 | },
1041 | },
1042 | });
1043 | ```
1044 |
1045 | 2. **$geoWithin:**
1046 |
1047 | Finds documents within a specified geometry (e.g., a polygon).
1048 |
1049 | ```js
1050 | db.places.find({
1051 | location: {
1052 | $geoWithin: {
1053 | $geometry: {
1054 | type: "Polygon",
1055 | coordinates: [
1056 | [
1057 | [-73.981, 40.768],
1058 | [-73.981, 40.776],
1059 | [-73.958, 40.776],
1060 | [-73.958, 40.768],
1061 | [-73.981, 40.768],
1062 | ],
1063 | ],
1064 | },
1065 | },
1066 | },
1067 | });
1068 | ```
1069 |
1070 | 3. **$geoIntersects:**
1071 |
1072 | Finds documents where the geometry intersects with a specified shape.
1073 |
1074 | ```js
1075 | db.places.find({
1076 | location: {
1077 | $geoIntersects: {
1078 | $geometry: {
1079 | type: "Polygon",
1080 | coordinates: [
1081 | [
1082 | [-73.982, 40.774],
1083 | [-73.982, 40.778],
1084 | [-73.958, 40.778],
1085 | [-73.958, 40.774],
1086 | [-73.982, 40.774],
1087 | ],
1088 | ],
1089 | },
1090 | },
1091 | },
1092 | });
1093 | ```
1094 |
1095 | 2. **2d Index:**
1096 |
1097 | **Purpose:** Supports queries on flat, Cartesian planes, which is less common but useful for certain types of two-dimensional geospatial data.
1098 |
1099 | **Data Types:** Works with coordinate pairs [x, y].
1100 |
1101 | **Use Cases:** Primarily used for flat, non-spherical data, such as gaming coordinates or 2D data representations.
1102 |
1103 | **Creating a 2d Index**
1104 |
1105 | Suppose you have a collection called locations, where each document contains a field named coords storing an [x, y] pair:
1106 |
1107 | ```js
1108 | {
1109 | "_id": 1,
1110 | "name": "Location A",
1111 | "coords": [50, 30]
1112 | }
1113 | ```
1114 |
1115 | You can create a 2D index on the coords field as follows:
1116 |
1117 | ```js
1118 | db.locations.createIndex({ coords: "2d" });
1119 | ```
1120 |
1121 | #### 2d Index Queries:
1122 |
1123 | After creating a 2D index, you can perform various geospatial queries on the coords field.
1124 |
1125 | 1. **$near:**
1126 |
1127 | Finds documents near a specific point in the 2D plane.
1128 |
1129 | ```js
1130 | db.locations.find({
1131 | coords: {
1132 | $near: [50, 30],
1133 | $maxDistance: 10,
1134 | },
1135 | });
1136 | ```
1137 |
1138 | This query finds all locations near the point [50, 30] within a maximum distance of 10 units.
1139 |
1140 | 2. **$within:**
1141 |
1142 | Finds documents within a specific shape, such as a box or circle.
1143 |
1144 | ```js
1145 | db.locations.find({
1146 | coords: {
1147 | $within: {
1148 | $box: [
1149 | [40, 20],
1150 | [60, 40],
1151 | ],
1152 | },
1153 | },
1154 | });
1155 | ```
1156 |
1157 | This query finds all locations within the box defined by the lower-left corner [40, 20] and the upper-right corner [60, 40].
1158 |
1159 | 3. **$center:**
1160 |
1161 | Finds documents within a circular area.
1162 |
1163 | ```js
1164 | db.locations.find({
1165 | coords: {
1166 | $within: {
1167 | $center: [[50, 30], 10],
1168 | },
1169 | },
1170 | });
1171 | ```
1172 |
1173 | This query finds all locations within a circle centered at [50, 30] with a radius of 10 units.
1174 |
1175 |
1176 | ### 11. Unique Index
1177 |
1178 | Ensures that the indexed field(s) do not contain duplicate values across documents. It's often used to enforce uniqueness for fields like email addresses or usernames.
1179 |
1180 | Example:
1181 | ```js
1182 | db.collection.createIndex({ "email": 1 }, { unique: true })
1183 | ```
1184 |
1185 | ## Grid FS
1186 |
1187 | GridFS is a feature in MongoDB used for storing and retrieving large files (like images, videos, and audio files). It works like a file system within MongoDB, breaking down large files into smaller pieces called "chunks" and storing them in a database.
1188 |
1189 | ### How Does GridFS Work?
1190 |
1191 | **File Division:** When you store a large file using GridFS, it divides the file into smaller chunks. Each chunk is no larger than 255kB.
1192 |
1193 | **Two Collections:**
1194 |
1195 | **fs.files:** This collection stores metadata about the file, like its name, size, and upload date.
1196 |
1197 | **fs.chunks:** This collection stores the actual chunks of data. Each chunk is linked to its file using a unique ID (files_id).
1198 |
1199 | **Example :**
1200 |
1201 | 1. **fs.files** Collection Document:
1202 |
1203 | Contains metadata about the file.
1204 |
1205 | ```js
1206 | {
1207 | "filename": "test.txt",
1208 | "chunkSize": 261120,
1209 | "uploadDate": "2014-04-13T11:32:33.557Z",
1210 | "md5": "7b762939321e146569b07f72c62cca4f",
1211 | "length": 646
1212 | }
1213 |
1214 |
1215 | ```
1216 |
1217 | 2. **fs.chunks** Collection Document:
1218 |
1219 | Stores a chunk of the file data.
1220 |
1221 | ```js
1222 | {
1223 | "files_id": "534a75d19f54bfec8a2fe44b",
1224 | "n": 0,
1225 | "data": "Mongo Binary Data"
1226 | }
1227 |
1228 | ```
1229 |
1230 | ### Why Use GridFS?
1231 |
1232 | - **Large File Storage:** GridFS allows you to store files larger than the standard MongoDB document size limit (16MB).
1233 |
1234 | - **Efficient Retrieval:** Since files are stored in chunks, you can retrieve and process them efficiently, especially useful for streaming large media files.
1235 |
1236 | ## Types of Collection In MongoDB
1237 |
1238 | ### Regular Collection
1239 |
1240 | The most common type of collection, where documents are stored without any specific constraints or special configurations.
1241 |
1242 | - Supports all basic operations like `insert`, `update`, `delete` query.
1243 | - No predefined schema, allowing flexibility in document structure.
1244 | - Indexes can be created to improve query performance.
1245 |
1246 | **Use Case:**
1247 |
1248 | General-purpose storage for a wide variety of applications, from simple CRUD operations to complex queries and indexing.
1249 |
1250 | ### Capped Collections
1251 |
1252 | Fixed-size collections that maintain insertion order and automatically remove the oldest documents when the size limit is reached.
1253 |
1254 | - **Size-Limited:** Configured with a maximum size in bytes and an optional document count limit.
1255 | - **Insertion Order:** Documents are stored in the order they are inserted, and once the limit is reached, older documents are overwritten (FIFO).
1256 | - **No Document Deletion:** Documents cannot be deleted; they are automatically removed when the limit is reached.
1257 | - **High-Performance:** Provides fast insertion and retrieval, ideal for scenarios where the latest data is of primary importance.
1258 |
1259 | **Use Case:**
1260 |
1261 | Logging, caching, real-time data streams, and other scenarios where only the most recent data is relevant.
1262 |
1263 | ```js
1264 |
1265 | db.createCollection(
1266 | "logs", // collection name
1267 | {
1268 | capped: true, //enable capped
1269 | size: 1048576, // 1 MB /-- size of collection
1270 | max: 10000 // Optional: Maximum of 10,000 documents
1271 | }
1272 | )
1273 |
1274 | ```
1275 |
1276 | ### Time Series Collections
1277 |
1278 | Collections optimized for storing and querying time-series data, which is data that includes a timestamp and typically arrives in time order.
1279 |
1280 | - **Time-Optimized Storage:** Organizes data efficiently for time-based access patterns.
1281 | - **Automatic Bucketing:** Groups data into buckets based on time intervals, improving storage efficiency and query performance.
1282 | - **TTL Support:** Documents can have a time-to-live (TTL) index, allowing automatic deletion of old data after a certain period.
1283 |
1284 | **Use Case:**
1285 |
1286 | Monitoring, IoT data, financial data, and other scenarios involving large volumes of time-stamped data.
1287 |
1288 | ### Views
1289 |
1290 | Virtual collections that are based on the results of an aggregation pipeline. Views do not store data but present data from other collections based on a specific query or transformation.
1291 |
1292 | - **Read-Only:** Views are read-only; you cannot `insert`, `update`, or `delete` documents in a view.
1293 | - **Dynamic:** The data presented in a view is always up-to-date with the underlying collections.
1294 | - **Aggregation-Based:** Views are defined using the MongoDB aggregation framework, allowing complex transformations.
1295 |
1296 | **Use Case:**
1297 |
1298 | Creating custom data representations, security layers (e.g., limiting fields or documents visible to certain users), and simplifying complex queries.
1299 |
1300 | To create a view in MongoDB, you use the `db.createView()` method. This method requires the name of the view, the source collection, and the aggregation pipeline that defines the view.
1301 |
1302 | **Example:**
1303 |
1304 | Suppose you have a collection named orders, and you want to create a view that shows only the orders with a total value greater than $100:
1305 |
1306 | ```js
1307 | db.createView(
1308 | "highValueOrders", // Name of the view
1309 | "orders", // Source collection
1310 | [
1311 | // Aggregation pipeline
1312 | { $match: { total: { $gt: 100 } } }, // Only include orders with total > 100
1313 | { $project: { _id: 0, customerName: 1, total: 1 } }, // Include only specific fields
1314 | ]
1315 | );
1316 | ```
1317 |
1318 | In this example, the view highValueOrders will always present a list of orders with a total value greater than $100, showing only the customerName and total fields. The data in this view is dynamically updated as the orders collection changes.
1319 |
1320 | ### Sharded Collections
1321 |
1322 | Collections that are distributed across multiple shards in a MongoDB cluster. Sharding allows MongoDB to scale horizontally by distributing data across multiple servers.
1323 |
1324 | - **Automatic Distribution:** MongoDB automatically distributes data across shards based on a shard key
1325 | - **High Availability:** Each shard is typically part of a replica set, ensuring data redundancy (storing the same data in multiple places) and high availability
1326 | - **Scalable:** Supports the horizontal scaling of data and queries.
1327 |
1328 | **Use Case:**
1329 |
1330 | Large-scale applications requiring horizontal scaling, such as those with massive datasets or high-throughput operations.
1331 |
1332 | ### TTL (Time to Live) Collections
1333 |
1334 | Collections with documents that automatically expire after a specified period, defined by a TTL index on a date field.
1335 |
1336 | - **Automatic Expiration:** Documents are automatically removed once they exceed the TTL value.
1337 | - **No Manual Deletion Required:** MongoDB handles the deletion process, which helps manage data retention policies.
1338 |
1339 | **Use Case:**
1340 |
1341 | Applications where data has a natural expiration, such as session management, temporary logs, or cached data.
1342 |
1343 | ### Clustered Collections
1344 |
1345 | Collections where documents are stored according to a clustered index, which is an index that dictates the physical order of data storage on disk.
1346 |
1347 | - **Clustered Index:** A single clustered index per collection that determines the physical order of data.
1348 | - **Efficient Queries:** Queries that align with the clustered index can be more efficient since data is stored in the index order.
1349 | - **Mandatory Index:** Every clustered collection must have a clustered index, and you cannot drop this index.
1350 |
1351 | **Use Case:** Scenarios where query performance is critical and aligned with the clustered index, such as queries on unique identifiers like `\_id`
1352 |
1353 | ## MongoDB Backup Methods
1354 |
1355 | Backing up and restoring data is crucial for maintaining data integrity and ensuring that you can recover from data loss, system failures, or other issues. MongoDB provides several methods for backing up and restoring data, each suitable for different use cases.
1356 |
1357 | 1. ### Mongodump and Mongorestore
1358 |
1359 | **mongodump:**
1360 |
1361 | This utility creates a backup by dumping the data from your MongoDB database into BSON (Binary JSON) format files. It’s often used for creating logical backups.
1362 |
1363 | **mongorestore:**
1364 |
1365 | This utility restores the data from the BSON files created by mongodump into a MongoDB database.
1366 | Example:
1367 |
1368 | To back up a database named myDatabase:
1369 |
1370 | ```js
1371 | mongodump --db myDatabase --out /path/to/backup/
1372 | ```
1373 |
1374 | ```js
1375 | mongorestore --db myDatabase /path/to/backup/myDatabase/
1376 | ```
1377 |
1378 | 2. ### Filesystem Snapshots
1379 |
1380 | This method involves taking a snapshot of the file system where MongoDB’s data files reside. It’s often used for physical backups and is typically faster for large datasets.
1381 |
1382 | **Best Use:**
1383 |
1384 | When using this method, you should stop writes to the database to ensure data consistency or use MongoDB’s journaling to capture changes.
1385 |
1386 | **Example:**
1387 |
1388 | On a Linux system, you might use LVM (Logical Volume Manager) to create a snapshot of the volume where MongoDB data is stored.
1389 |
1390 | 3. ### MongoDB Atlas Backups
1391 |
1392 | MongoDB Atlas, the managed cloud database service, provides automated backups as part of its service. It handles backup scheduling, retention, and restoration automatically.
1393 |
1394 | **Best Use:**
1395 |
1396 | This is ideal for users who are using MongoDB Atlas and want a hassle-free backup solution.
1397 |
1398 | **Example:**
1399 |
1400 | In MongoDB Atlas, you can configure backup policies via the Atlas UI, and restore your data to any point in time by selecting a snapshot or using point-in-time recovery.
1401 |
1402 | 4. ### Custom Scripts
1403 |
1404 | For specific needs, custom scripts can be created to handle backups, such as using mongodump with custom scheduling via cron jobs on Linux or Task Scheduler on Windows.
1405 |
1406 | **Best Use:**
1407 |
1408 | When you need a highly tailored backup solution, including features like offsite storage or integration with other systems.
1409 |
1410 | ## MongoDB Restore Methods
1411 |
1412 | ### Using mongorestore
1413 |
1414 | `mongorestore` is the primary tool for restoring data from a backup created by mongodump.
1415 |
1416 | **Example:**
1417 |
1418 | If you have a backup of myDatabase and want to restore it:
1419 |
1420 | ```js
1421 | mongorestore --db myDatabase /path/to/backup/myDatabase/
1422 | ```
1423 |
1424 | ### To restore a specific collection:
1425 |
1426 | ```js
1427 | mongorestore --collection myCollection --db myDatabase /path/to/backup/myDatabase/myCollection.bson
1428 | ```
1429 |
1430 | ### Restoring from Filesystem Snapshots
1431 |
1432 | If you took a filesystem snapshot as your backup, you would restore by copying the snapshot back to the original location and ensuring MongoDB’s data files are in place.
1433 |
1434 | **Best Use:**
1435 |
1436 | This is useful for large-scale systems where mongodump and mongorestore might be too slow.
1437 |
1438 | ### MongoDB Atlas Restore
1439 |
1440 | In MongoDB Atlas, you can restore data by selecting a backup snapshot or using point-in-time recovery.
1441 | Best Use: This method is ideal for MongoDB Atlas users who need a quick and reliable restore process.
1442 |
1443 | **Example:**
1444 |
1445 | In the MongoDB Atlas UI, you can choose a backup snapshot to restore your cluster to a previous state.
1446 |
1447 | #### Important Considerations
1448 |
1449 | **Backup Frequency:** Regular backups are important. The frequency depends on how critical the data is and how often it changes.
1450 |
1451 | **Consistency:** Ensure that the backup process captures a consistent state of the database, especially if your database is active during the backup.
1452 |
1453 | **Security:** Backups should be stored securely, with access controls and encryption, especially if they contain sensitive data.
1454 |
1455 | **Testing:** Periodically test your restore process to ensure that your backups are valid and can be restored when needed.
1456 |
1457 | # SCALING IN DATABASES
1458 |
1459 | Scaling in databases can be broadly categorized into vertical scaling and horizontal scaling
1460 | MongoDB support **Horizontal Scaling**
1461 |
1462 | First Understand the Key difference Between vertical scaling and horizontal scaling
1463 |
1464 | ## 1. Vertical Scaling (Scaling Up)
1465 |
1466 | Vertical scaling involves increasing the capacity of a single server or instance to handle more load. This can be achieved by upgrading the server's hardware, such as adding more CPU, RAM, or storage.
1467 |
1468 | **Advantages:**
1469 |
1470 | - **Simplicity:** Easier to implement since it involves upgrading existing hardware.
1471 | - **Consistency:** Data remains in a single location, reducing the complexity of data distribution and consistency.
1472 | - **Ease of Management:** No need to deal with the complexities of data sharding or distribution.
1473 |
1474 | **Disadvantages:**
1475 |
1476 | - **Limits:** There are physical and cost limits to how much you can upgrade a single machine. Eventually, you'll hit a ceiling.
1477 | - **Single Point of Failure:** The server can become a single point of failure, making it critical to have robust backup and failover strategies.
1478 | - **Cost:** High-performance hardware can be very expensive.
1479 |
1480 | **When to Use:**
1481 |
1482 | When dealing with relatively small datasets or applications that don’t require extensive scaling.
1483 | When needing a quick and straightforward solution without redesigning the application architecture.
1484 |
1485 | ## 2. Horizontal Scaling (Scaling Out)
1486 |
1487 | Horizontal scaling involves adding more servers or instances to distribute the load. This approach scales the database by partitioning data and distributing it across multiple nodes or instances.
1488 |
1489 | **Advantages:**
1490 |
1491 | - **Scalability:** Can handle large amounts of data and high traffic by adding more nodes as needed.
1492 | - **Redundancy and Fault Tolerance:** Provides better fault tolerance and redundancy since the system can continue to operate even if some nodes fail.
1493 | - **Cost Efficiency:** Often more cost-effective for handling large-scale data compared to continuously upgrading hardware.
1494 |
1495 | **Disadvantages:**
1496 |
1497 | - **Complexity:** Involves more complex management, including data partitioning (sharding), consistency, and coordination across multiple nodes.
1498 | - **Consistency:** Maintaining consistency across distributed nodes can be challenging, often requiring additional mechanisms like distributed transactions or eventual consistency models.
1499 | - **Data Distribution:** Requires careful design of data distribution and routing mechanisms to ensure optimal performance.
1500 |
1501 | **When to Use:**
1502 |
1503 | When dealing with large datasets, high traffic volumes, or applications that need to scale dynamically.
1504 | When designing systems that must be resilient to hardware failures and require high availability.
1505 |
1506 | # Implementing Horizontal Scaling in MongoDB
1507 |
1508 | ## Sharding
1509 |
1510 | Sharding is the process of distributing data across multiple servers, known as shards. Each shard holds a subset of the data, allowing MongoDB to handle large datasets and high throughput more efficiently.
1511 |
1512 | - **Shard:** A single MongoDB instance (or a replica set) that holds a portion of the data.
1513 | - **Shard Key:** A field in the documents used to distribute the data across shards. The choice of shard key is crucial for balancing the load and ensuring efficient querying.
1514 | - **Config Servers:** Store metadata about the sharded cluster and keep track of the location of data across shards. They are used to manage the cluster and provide routing information.
1515 | - **Mongos:**A routing service that directs client requests to the appropriate shard(s) based on the shard key and metadata from the config servers.
1516 |
1517 | **Example:**
1518 |
1519 | Suppose you have a large collection of user data that you want to shard based on user IDs. MongoDB would distribute the data across multiple shards, each responsible for a subset of user IDs. This allows for parallel processing of queries and reduces the load on any single shard.
1520 |
1521 | ## Replication in MongoDB
1522 |
1523 | Replication is the process of synchronizing data across multiple servers.
1524 |
1525 | Think about a scenario if your main process or Primary instance of your mongo db fails in production, then the Db switched to the secondary process
1526 |
1527 | Replication provides redundancy and increases data availability with multiple copies of data on different database servers. Replication protects a database from the loss of a single server.
1528 |
1529 | Replication also allows you to recover from hardware failure and service interruptions. With additional copies of the data, you can dedicate one to disaster recovery, reporting, or backup.
1530 |
1531 | MongoDB achieves replication by the use of `Replica Set`.
1532 |
1533 | ### Replica Set
1534 |
1535 | A `replica set` is a group of mongod instances that host the same data set.
1536 |
1537 | In a replica, one node is primary node that receives all write operations. All other instances, such as secondaries, apply operations from the primary so that they have the same data set.
1538 |
1539 | Replica set can have only one primary node.
1540 |
1541 | ### Oplog (operations log)
1542 |
1543 | `oplog` (operations log) to ensure that all nodes in a replica set maintain consistent data. The `oplog` is a key component in the replication process, allowing secondary nodes to replicate the operations that occur on the primary node.
1544 |
1545 | - The oplog records all write operations on the primary node in a replica set.
1546 | - Secondary nodes replicate these operations by continuously reading and applying entries from the oplog.
1547 | - The oplog ensures that all nodes in the replica set have an identical copy of the data, supporting automatic failover and data redundancy.
1548 | - The size of the oplog and its proper management are crucial for the efficient operation of the replica set, especially in maintaining synchronization and handling failover scenarios.
1549 |
1550 | ## Combining Sharding and Replica Sets
1551 |
1552 | In a typical production setup, MongoDB clusters combine both sharding and replica sets to achieve high scalability, availability, and reliability:
1553 |
1554 | - **Sharded Cluster:** Manages the distribution of data across multiple shards. Each shard may be a replica set to ensure high availability and fault tolerance.
1555 |
1556 | - **Replica Sets within Shards:** Provides redundancy and failover support for each shard. This means that even if a shard fails, other replicas can continue to provide data and services.
1557 |
1558 | # Journaling in MongoDB
1559 |
1560 | Journaling is a crucial feature in MongoDB that helps ensure data durability and recoverability in the event of a server crash or unexpected shutdown.
1561 |
1562 | ### The Problem Without Journaling
1563 |
1564 | In typical MongoDB operations, when data is written to a collection, it is first mapped to an in-memory view known as the `shared view`. MongoDB periodically flushes this in-memory data to the disk, typically every 60 seconds. However, this creates a window of vulnerability. If the server crashes within this 60-second period, any data that was in the shared view but not yet written to disk would be lost.
1565 |
1566 | 1. **Shared View vs. Private View:**
1567 |
1568 | - The shared view is the in-memory view that reflects the current state of the data, visible to operations.
1569 |
1570 | - The private view is a snapshot of the shared view taken before any modifications are made. Changes are first applied to this private view before being committed to the shared view.
1571 |
1572 | 2. **Journal File:**
1573 |
1574 | - The journal file is where MongoDB logs the intent of every operation before it modifies the data. This file doesn’t store the actual data but rather a record of all operations (like inserts, updates, deletes) that have been performed.
1575 |
1576 | - Each write operation is first recorded in the journal file and then applied to the private view. Once the data is safely written to the journal, MongoDB can proceed with applying changes to the shared view.
1577 |
1578 | 3. **Data Recovery Using the Journal:**
1579 |
1580 | - If the server crashes, MongoDB can use the journal file to recover the data that was in the process of being written but not yet flushed to disk.
1581 |
1582 | - Upon restart, MongoDB reads the journal file, replays the recorded operations, and applies them to the shared view. This allows MongoDB to "replay" the operations that would have otherwise been lost due to the crash.
1583 |
1584 | 4. **Journal Commit Interval:**
1585 |
1586 | - MongoDB commits the journal to disk every 100 milliseconds by default, which significantly reduces the risk of data loss compared to the 60-second flush interval of the shared view.
1587 |
1588 | # CAP THEOREM
1589 |
1590 | The CAP theorem states that in a distributed system, it is impossible to guarantee all three of the following properties simultaneously: **Consistency**, **Availability**, and **Partition Tolerance**. Instead, a system can only achieve at most two of these properties at the same time.
1591 |
1592 | ### 1. Consistency
1593 |
1594 | Consistency means that every read operation in the distributed system returns the most recent write. In other words, all nodes in the system see the same data at the same time. If a system is consistent, then after a write operation is completed, all subsequent reads will reflect that write.
1595 |
1596 | **Example:** Imagine a distributed database with three nodes. When a write operation (like updating a value) is performed, consistency ensures that all three nodes immediately reflect this change. If you query any of these nodes, you will get the same, up-to-date result.
1597 |
1598 | **Trade-off:** Achieving consistency may require communication between nodes to synchronize data, which can introduce latency. In some scenarios, to maintain consistency, the system might reject a request if not all nodes can be synchronized, thereby impacting availability.
1599 |
1600 | ### 2. Availability
1601 |
1602 | Availability ensures that every request (read or write) to the system receives a response, even if some nodes in the system are down. The system remains operational and provides a response to every query, though the response might not always reflect the latest data.
1603 |
1604 | **Example:** In the same distributed database with three nodes, even if one node fails, the system continues to serve read and write requests from the other two nodes. The system prioritizes providing a response over ensuring that all nodes have the most up-to-date data.
1605 |
1606 | **Trade-off:** To maintain high availability, a system might allow for stale data to be served, meaning that not all nodes are guaranteed to be consistent at any given moment. This can result in eventual consistency, where nodes become consistent over time.
1607 |
1608 | ### Partition Tolerance
1609 |
1610 | Partition tolerance means that the system continues to operate even if there is a network partition separating different nodes in the distributed system. A network partition can occur due to various reasons, such as network failures, where communication between nodes is disrupted.
1611 |
1612 | **Example:** If a network partition occurs and two nodes in the distributed database cannot communicate with each other, the system can still function. Each partitioned node can continue to process requests independently.
1613 |
1614 | **Trade-off:** To maintain partition tolerance, a system may have to sacrifice either consistency or availability. For example, during a network partition, a system might prioritize availability by continuing to accept writes on both partitions, leading to temporary inconsistency between them.
1615 |
1616 | # MongoDB ACID Transactions
1617 |
1618 | In MongoDB, a transaction is like a package of actions that you want to do all together. Think of it as a to-do list where everything must be completed. If something goes wrong, MongoDB will undo all the changes so that your data remains safe and consistent.
1619 |
1620 | ### What Are ACID Transactions?
1621 |
1622 | A transaction is a set of operations that are executed as a single, atomic unit. Transactions provide data consistency by ensuring that either all the operations within the transaction are committed to the database or none of them are.
1623 |
1624 | ACID Properties ensures the integrity and reliability of the database. The term ACID stands for **Atomicity**, **Consistency**, **Isolation**, and **Durability**. Let’s understand each of these ACID transaction properties with their examples.
1625 |
1626 | 1. **Atomicity**
1627 |
1628 | Atomicity ensures that all the operations within a transaction are completed successfully as a single unit. If any operation within the transaction fails, the entire transaction is rolled back, leaving the database in its original state.
1629 |
1630 | 2. **Consistency**
1631 |
1632 | Consistency ensures that a transaction brings the database from one valid state to another valid state, maintaining all defined rules, such as constraints and triggers. If a transaction violates any integrity constraints, it is rolled back, and the database remains consistent.
1633 |
1634 | 3. **Isolation**
1635 |
1636 | Isolation ensures that the operations within a transaction are invisible to other operations until the transaction is committed. This means that other operations cannot see the intermediate states of a transaction, preventing issues such as dirty reads or non-repeatable reads.
1637 |
1638 | 4. **Durability**
1639 |
1640 | Durability ensures that once a transaction is committed, its changes are permanently stored in the database, even in the event of a system failure. This means that the data is safe and will survive crashes or power outages.
1641 |
1642 |
1643 | # Materialized View
1644 |
1645 | A view in MongoDB is a virtual collection that represents the results of an aggregation pipeline query on one or more existing collections. It does not hold any data itself.
1646 |
1647 | **A materialized view is a database object that contains the results of a query, a materialized view is physically stored in the database and needs to be explicitly refreshed when the underlying data changes.**
1648 |
1649 | In MongoDB, materialized views are not natively supported as a built-in feature like they are in some relational databases..
1650 |
1651 | you can achieve a materialized view-like functionality in MongoDB using the $out stage in an aggregation pipeline. The $out stage allows you to write the results of an aggregation pipeline to a new collection or overwrite an existing collection. This effectively materializes the result set of your query, making it available for future queries without recomputing the results each time.
1652 |
1653 | | **Feature** | **Regular View (MongoDB)** | **Materialized View-Like Collection (Using $out)** |
1654 | |--------------------|:----------------------------------------------------------------------:|:-------------------------------------------------------------------:|
1655 | | **Storage** | No physical storage (virtual, only the aggregation pipeline is stored) | Physically stored in a new collection |
1656 | | **Data Freshness** | Always up-to-date; data fetched dynamically | Stale after creation; requires manual or scheduled refreshes |
1657 | | **Performance** | May impact performance for complex or frequent queries | Faster for repeated access; data is precomputed |
1658 | | **Use Cases** | Real-time data presentation | Reporting, analytics, and dashboards where fast access is necessary |
1659 | | **Read/Write** | Read-only | Can be read and written like a regular collection |
1660 |
1661 | ## Query Routing
1662 |
1663 | Query routing in MongoDB refers to the process of directing client queries to the appropriate shard or replica set member within a sharded or replicated MongoDB cluster. This process is crucial for ensuring that queries are efficiently executed and that the data is retrieved from the correct location
1664 |
1665 |
1666 |
1667 |
--------------------------------------------------------------------------------
/NodeJs & Express Js/Express.md:
--------------------------------------------------------------------------------
1 | # EXPRESS
2 | Express is a lightweight Node.js framework that provides robust set of features for web and mobile application
3 |
4 | It provides set of features that streamline the development of server-side applications, making it easier for developers to manage routing, middleware, and HTTP requests.
5 |
6 | ```js
7 |
8 | const express = require('express')
9 | const app = express()
10 | const port = 3000
11 |
12 | app.get('/', (req, res) => {
13 | res.send('Hello World!')
14 | })
15 |
16 | app.listen(port, () => {
17 | console.log(`Example app listening on port ${port}`)
18 | })
19 |
20 | ```
21 |
22 | ## PORT
23 | In Express.js, you can set up the port your application will run on using environment variables. Environment variables allow you to configure your application based on different environments (development, production, etc.) without hardcoding values directly into your code. This practice makes your application more flexible and secure.
24 |
25 | ```js
26 | const express = require('express');
27 | const app = express();
28 |
29 | // Set the port using environment variables or a default value
30 | const PORT = process.env.PORT || 3000;
31 |
32 | app.listen(PORT, () => {
33 | console.log(`Server is running on port ${PORT}`);
34 | });
35 |
36 | ```
37 |
38 | ## HTTP Methods in Express.js
39 | HTTP methods define the type of operation to be performed on a given resource when making a request to a server. Here are the most common HTTP methods used in web development:
40 |
41 | ### GET
42 |
43 | * **Purpose:** Retrieve data from the server.
44 | * **Usage:** When a client (usually a browser) wants to fetch data or a resource from the server without making any changes to the data on the server.
45 |
46 | **Example:** A user visits a webpage or requests a list of items from an API.
47 |
48 | ```js
49 |
50 | app.get('/users', (req, res) => {
51 | res.send('Fetching list of users');
52 | });
53 |
54 | ```
55 |
56 | ### POST
57 |
58 | * **Purpose:** Send data to the server to create or update a resource.
59 | * **Usage:** When a client submits form data, uploads a file, or sends any other kind of data to the server.
60 |
61 | **Example:** A user submits a registration form.
62 |
63 | ```js
64 |
65 | app.post('/users', (req, res) => {
66 | res.send('Creating a new user');
67 | });
68 |
69 | ```
70 |
71 | ### PUT
72 |
73 | * **Purpose:** Update an existing resource on the server.
74 | * **Usage:** When a client needs to update data or replace an existing resource entirely.
75 |
76 | **Example:** A user updates their profile information.
77 |
78 | ```js
79 |
80 | app.put('/users/:id', (req, res) => {
81 | res.send(`Updating user with ID ${req.params.id}`);
82 | });
83 |
84 | ```
85 |
86 | ### DELETE
87 |
88 | * **Purpose:** Remove a resource from the server.
89 | * **Usage:** When a client wants to delete data from the server.
90 |
91 | **Example:** A user deletes their account.
92 |
93 | ```js
94 | app.delete('/users/:id', (req, res) => {
95 | res.send(`Deleting user with ID ${req.params.id}`);
96 | });
97 |
98 | ```
99 |
100 |
101 | ### PATCH
102 |
103 | * **Purpose:** Apply partial modifications to a resource.
104 | * **Usage:** When a client needs to update part of a resource, rather than replacing the entire resource.
105 |
106 | **Example:** A user updates their email address but not the entire profile.
107 |
108 | ```js
109 |
110 | app.patch('/users/:id', (req, res) => {
111 | res.send(`Partially updating user with ID ${req.params.id}`);
112 | });
113 |
114 | ```
115 |
116 | ## Idempotence
117 | Idempotence in HTTP methods refers to the property of certain HTTP methods where making multiple identical requests has the same effect as making a single request. In other words, an idempotent operation can be performed multiple times without changing the result beyond the initial application
118 |
119 | ### Idempotent Methods:
120 |
121 | **GET:** The GET method is used to retrieve data from the server. No matter how many times you send the same GET request, the server's state remains unchanged. For example, fetching a user’s profile via a GET request won’t alter the profile itself.
122 |
123 | **PUT:** The PUT method is used to update or create a resource. Sending the same PUT request multiple times will result in the same outcome as sending it once. For example, if you update a user's information using a PUT request, doing so multiple times with the same data won’t change the outcome after the first request.
124 |
125 | **DELETE:** The DELETE method is used to delete a resource. If you delete the same resource multiple times, the first request deletes it, and subsequent requests have no effect since the resource no longer exists.
126 |
127 | **HEAD:** Similar to GET, but it only retrieves the headers and not the body. Like GET, it's idempotent.
128 |
129 | **OPTIONS:** This method is used to describe the communication options for the target resource. It does not change the state of the resource, making it idempotent.
130 |
131 | ### Non-Idempotent Methods:
132 |
133 | **POST:** The POST method is used to create a new resource. Sending the same POST request multiple times may create multiple resources (e.g., creating multiple user accounts with the same data), so it is not idempotent.
134 |
135 | **PATCH:** The PATCH method is used to make partial updates to a resource. Depending on how it's implemented, it may or may not be idempotent. For example, if you PATCH a user's balance by adding $10, multiple PATCH requests will result in an increased balance each time, making it non-idempotent.
136 |
137 | ## HTTP STATUS CODES
138 |
139 | HTTP status codes are standard responses sent by a server to indicate the result of a client's request. They are categorized into five classes, each representing a different type of response:
140 |
141 | 1. **1xx: Informational Responses**
142 | These codes indicate that the request was received and is being processed.
143 |
144 | 2. **2xx: Success**
145 | These codes indicate that the request was successfully received, understood, and accepted.
146 |
147 | * **200 OK:** The request was successful, and the server returned the requested data.
148 | * **201 Created:** The request was successful, and a new resource was created as a result.
149 |
150 | 3. **3xx: Redirection**
151 | These codes indicate that further action is needed to complete the request.
152 |
153 | * **301 Moved Permanently:** The requested resource has been permanently moved to a new URL.
154 | * **302 Found:** The requested resource resides temporarily under a different URL.
155 |
156 | 4. **4xx: Client Errors**
157 | These codes indicate that there was an error with the request made by the client.
158 |
159 | * **400 Bad Request:** The server could not understand the request due to invalid syntax.
160 | * **401 Unauthorized:** The client must authenticate itself to get the requested response.
161 | * **403 Forbidden:** The client does not have access rights to the content.
162 | * **404 Not Found:** The server could not find the requested resource.
163 |
164 | 5. **5xx: Server Errors**
165 | These codes indicate that the server encountered an error and could not fulfill the request.
166 |
167 | * **500 Internal Server Error:** The server encountered an unexpected condition that prevented it from fulfilling the request.
168 |
169 | * **503 Service Unavailable:** The server is not ready to handle the request, often due to maintenance or overload.
170 |
171 | ### Sending Status Codes in Express
172 | In Express, you can send HTTP status codes using the res.status() method. This method sets the HTTP status code for the response and can be chained with res.send() or other methods to send the response body.
173 |
174 | Here’s an example of how to use it:
175 |
176 | ```js
177 | const express = require('express');
178 | const app = express();
179 |
180 | app.get('/', (req, res) => {
181 | res.status(200).send('OK');
182 | });
183 |
184 | app.get('/not-found', (req, res) => {
185 | res.status(404).send('Not Found');
186 | });
187 |
188 | app.get('/error', (req, res) => {
189 | res.status(500).send('Internal Server Error');
190 | });
191 |
192 | app.listen(3000, () => {
193 | console.log('Server is running on port 3000');
194 | });
195 |
196 | ```
197 |
198 | ## MIDDLEWARE
199 |
200 | Middleware functions are the backbone of an Express.js application. They are functions that have access to the request object (`req`), the response object (`res`), and the next middleware function in the application’s request-response cycle. Middleware functions can perform a variety of tasks, such as:
201 |
202 | * Executing code.
203 | * Modifying the request and response objects.
204 | * Ending the request-response cycle.
205 | * Calling the next middleware function in the stack.
206 |
207 | In an Express app, middleware functions are executed sequentially, forming a middleware stack. This stack allows you to organize and handle different aspects of a request, from parsing data to logging and error handling.
208 |
209 | ### Types of Middleware in Express.js
210 |
211 | #### Application-Level Middleware
212 |
213 | **Definition:** Middleware that is bound to an instance of the Express app object. It can be used across all routes or limited to specific routes.
214 |
215 | **Usage:**
216 |
217 | It can be used to perform operations like logging, authentication, or any other processing that needs to be applied to all or specific routes.
218 |
219 | Example:
220 |
221 | ```js
222 |
223 | const express = require('express');
224 | const app = express();
225 |
226 | // Application-level middleware
227 | app.use((req, res, next) => {
228 | console.log('Request URL:', req.originalUrl);
229 | next();
230 | });
231 |
232 | app.get('/home', (req, res) => {
233 | res.send('Home Page');
234 | });
235 |
236 | app.listen(3000, () => {
237 | console.log('Server running on port 3000');
238 | });
239 | ```
240 | In this example, the middleware logs the request URL for every incoming request.
241 |
242 |
243 | #### Router-Level Middleware
244 |
245 | **Definition:** Middleware that is bound to an instance of the Express router object. It is used in the same way as application-level middleware, except that it is applied only to the routes within that router.
246 |
247 | **Usage:**
248 |
249 | Useful for grouping routes together with specific middleware that should only apply to those routes.
250 |
251 | Example:
252 | ```js
253 | const express = require('express');
254 | const router = express.Router();
255 |
256 | // Router-level middleware
257 | router.use((req, res, next) => {
258 | console.log('Router Middleware:', req.originalUrl);
259 | next();
260 | });
261 |
262 | router.get('/about', (req, res) => {
263 | res.send('About Page');
264 | });
265 |
266 | const app = express();
267 | app.use('/info', router);
268 |
269 | app.listen(3000, () => {
270 | console.log('Server running on port 3000');
271 | });
272 | ```
273 | This middleware applies only to routes that start with /info.
274 |
275 | #### Error-Handling Middleware
276 |
277 | **Definition:** Middleware that handles errors that occur during the processing of requests. Error-handling middleware is defined with four arguments: err, req, res, and next.
278 |
279 | **Usage:**
280 |
281 | To catch and handle errors that occur during request processing. It can send error responses to the client or log the error details.
282 |
283 | Example:
284 |
285 | ```js
286 | const express = require('express');
287 | const app = express();
288 |
289 | app.get('/error', (req, res) => {
290 | throw new Error('Something went wrong!');
291 | });
292 |
293 | // Error-handling middleware
294 | app.use((err, req, res, next) => {
295 | console.error(err.stack);
296 | res.status(500).send('Internal Server Error');
297 | });
298 |
299 | app.listen(3000, () => {
300 | console.log('Server running on port 3000');
301 | });
302 | ```
303 | Here, if an error occurs, it is caught by the error-handling middleware, which sends a 500 status response.
304 |
305 | #### Built-in Middleware
306 | **Definition:** Express provides some built-in middleware functions that can be used directly without needing to write custom middleware.
307 |
308 | **Common Built-in Middleware:**
309 |
310 | 1. **express.static:** Serves static files, such as HTML, CSS, and JavaScript.
311 | 2. **express.json:** Parses incoming JSON requests and makes the payload available on req.body.
312 | 3. **express.urlencoded:** Parses incoming requests with URL-encoded payloads (from HTML forms) and makes the data available on req.body.
313 |
314 | Example:
315 | ```js
316 | const express = require('express');
317 | const app = express();
318 |
319 | // Built-in middleware for serving static files
320 | app.use(express.static('public'));
321 |
322 | app.listen(3000, () => {
323 | console.log('Server running on port 3000');
324 | });
325 | ```
326 | This serves static files from the public directory.
327 |
328 | #### Third-Party Middleware
329 |
330 | **Definition:** Middleware provided by third-party libraries that can be installed via npm. These middlewares offer additional functionality like handling cookies, sessions, authentication, etc.
331 |
332 | **Popular Examples:**
333 |
334 | 1. **morgan:** HTTP request logger middleware.
335 | 2. **cookie-parser:** Parses Cookie header and populates req.cookies with an object.
336 | body-parser: Parses incoming request bodies (replaced by express.json and express.urlencoded in Express 4.16+).
337 |
338 | Example:
339 | ```js
340 | const express = require('express');
341 | const morgan = require('morgan');
342 | const app = express();
343 |
344 | // Third-party middleware for logging HTTP requests
345 | app.use(morgan('combined'));
346 |
347 | app.listen(3000, () => {
348 | console.log('Server running on port 3000');
349 | });
350 | ```
351 | This logs detailed information about each request.
352 |
353 | ## Static Files handling
354 |
355 | In an Express.js application, serving static files (such as images, CSS files, and JavaScript files) is a common requirement. Static files are those that do not change dynamically and are served directly to the client. Express makes it easy to serve these files using the `express.static()` middleware.
356 |
357 | ```js
358 |
359 | const express = require('express');
360 | const app = express();
361 |
362 | // Serving static files from the "public" directory
363 | app.use(express.static('public'));
364 |
365 | app.get('/', (req, res) => {
366 | res.send('Home Page');
367 | });
368 |
369 | app.listen(3000, () => {
370 | console.log('Server is running on port 3000');
371 | });
372 |
373 | ```
374 |
375 | In this example:
376 |
377 | * The express.static('public') middleware serves all files in the public directory. This means that if you have an index.html file in the public directory, it can be accessed via http://localhost:3000/index.html.
378 |
379 | * If a request is made to a route that does not match any of the static files, Express will continue down the middleware stack, eventually reaching the route handlers.
380 |
381 | You can also serve multiple directories or specify a virtual path prefix:
382 |
383 | ```js
384 | // Serving static files from "public" directory
385 | app.use('/static', express.static('public'));
386 |
387 | // Now the static files can be accessed via http://localhost:3000/static/filename.ext
388 | ```
389 |
390 | ## Cookies, Authentication, and Session Management in Express
391 |
392 | ### Cookies
393 |
394 | Cookies are small pieces of data stored on the client’s browser, often used for tracking, storing user preferences, or managing sessions. In Express, you can easily manage cookies using the `cookie-parser` middleware.
395 |
396 | Setting Up **cookie-parser:**
397 |
398 | First, install the `cookie-parser`middleware:
399 |
400 | ```js
401 | npm install cookie-parser
402 |
403 | ```
404 |
405 | Next, use it in your Express application:
406 |
407 | ```js
408 | const express = require('express');
409 | const cookieParser = require('cookie-parser');
410 | const app = express();
411 |
412 | app.use(cookieParser());
413 |
414 | ```
415 |
416 | **Setting a Cookie:**
417 |
418 | To set a cookie, use the res.cookie() method:
419 |
420 | ```js
421 |
422 | app.get('/set-cookie', (req, res) => {
423 | res.cookie('username', 'Aswanth', { maxAge: 900000, httpOnly: true });
424 | res.send('Cookie has been set');
425 | });
426 |
427 | ```
428 |
429 | In this example:
430 |
431 | * **'username', 'Aswanth':** Sets a cookie named username with the value `Aswanth`.
432 | * **maxAge: 900000:** Sets the cookie to expire in 15 minutes.
433 | * **httpOnly: true:** Ensures the cookie is only accessible via the web server, enhancing security.
434 |
435 |
436 | **Reading a Cookie:**
437 | You can access the cookies sent by the client using `req.cookies:`
438 |
439 | ```js
440 |
441 | app.get('/get-cookie', (req, res) => {
442 | const username = req.cookies.username;
443 | res.send(`Cookie retrieved: ${username}`);
444 | });
445 |
446 | ```
447 |
448 | **Deleting a Cookie:**
449 | To delete a cookie, use `res.clearCookie():`
450 |
451 | ```js
452 | app.get('/clear-cookie', (req, res) => {
453 | res.clearCookie('username');
454 | res.send('Cookie has been cleared');
455 | });
456 |
457 | ```
458 |
459 | ### Session Management
460 |
461 | Sessions are used to maintain the state across multiple requests in a web application. In Express, session management is commonly handled using the `express-session` middleware.
462 |
463 | Install the express-session package:
464 |
465 | ```js
466 | npm install express-session
467 |
468 | ```
469 |
470 | ### Authentication
471 | Authentication is the process of verifying the identity of a user or system. It's about confirming who someone is.
472 |
473 | ### Authorization
474 | Authorization is the process of determining what an authenticated user is allowed to do. It involves checking permissions or access levels.
475 |
476 |
477 |
478 | ## Cross-Origin Resource Sharing (CORS)
479 |
480 | CORS is a security feature implemented in web browsers to control how resources (like images, scripts, or APIs) from one origin (domain) can be shared or accessed by another origin. It plays a crucial role in web security by preventing malicious websites from making unauthorized requests to your web server
481 |
482 | ```js
483 |
484 | const express = require('express');
485 | const cors = require('cors');
486 | const app = express();
487 |
488 | app.use(cors()); // Enable CORS for all routes and origins
489 |
490 | // You can also configure CORS options
491 | app.use(cors({
492 | origin: 'http://frontend.example.com', // Allow only this origin
493 | methods: 'GET,POST', // Allow only these methods
494 | credentials: true // Allow credentials (cookies, etc.)
495 | }));
496 |
497 | app.get('/data', (req, res) => {
498 | res.json({ message: 'This is a CORS-enabled response' });
499 | });
500 |
501 | app.listen(3000, () => {
502 | console.log('Server running on port 3000');
503 | });
504 |
505 | ```
506 |
507 | ## REST API
508 |
509 | A REST API (Representational State Transfer Application Programming Interface) is a software architectural style for creating web services. It defines a set of constraints for how the architecture of a distributed, internet-scale hypermedia system, such as the web, should behave.
510 |
511 | ### Key Characteristics of REST APIs:
512 |
513 | * **Stateless:** Each request from a client contains all the information needed to understand and process the request. The server doesn't maintain session state between requests.
514 | * **Client-Server Architecture:** Clear separation of concerns between the client and server.
515 | * **Cacheable:** Responses can be cached to improve performance.
516 | * **Uniform Interface:** Uses standard HTTP methods (GET, POST, PUT, DELETE) and standard HTTP status codes.
517 | * **Layered System:** Multiple layers of servers can be used to improve scalability and security.
518 | * **Code on Demand (Optional):** Clients can download executable code to extend functionality.
519 |
520 | ### Core HTTP Methods in REST APIs
521 |
522 | **GET:** Retrieves data from a specified resource.
523 | **POST:** Creates a new resource.
524 | **PUT:** Updates an existing resource.
525 | **DELETE:** Deletes a resource.
526 | **OPTIONS:** Used to determine the supported HTTP methods for a resource.
527 |
528 |
529 | ## Node.js process.exitCode Property
530 |
531 | There are two ways that are generally used to terminate a Node.js program which is using process.exit() or process.exitCode variable
532 | process.exit code variable is an integer that represents the code passed to the process.exit() function or when the process exits on its own. It allows the Node.js program to exit naturally and avoids the Node program to do additional work around event loop scheduling, and it is much safer than passing exit code to process.exit().
533 |
534 | ```js
535 | const express = require('express')
536 | const app = express()
537 |
538 | let a = 10;
539 | let b = 20;
540 |
541 | if (a == 10) {
542 | console.log(a)
543 | process.exitCode(1);
544 | }
545 |
546 | console.log(b);
547 |
548 | app.listen(3000, () => console.log('Server ready'))
549 |
550 |
551 | // output 10
552 |
553 | ```
554 |
--------------------------------------------------------------------------------
/PostgreSQL/PostgreSQL.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aswanthnarayan/ProgrammingNotes/15f0b2f512dff406e490b14a26797bd823bb1e34/PostgreSQL/PostgreSQL.md
--------------------------------------------------------------------------------
/Typescript/TypeScript.md:
--------------------------------------------------------------------------------
1 | # Type Script
2 |
3 | Typescript is a typed superset of JavaScript. TypeScript offers all of JavaScript’s features, and an additional layer on top of these: TypeScript’s type system
4 |
5 | JavaScript provides language primitives like string and number, but it doesn’t check that you’ve consistently assigned these. TypeScript does
6 |
7 | ## Type safety
8 | Type safety means that a programming language ensures values have the correct types at compile time, preventing unintended operations and reducing runtime errors.
9 |
10 | In TypeScript, type safety ensures that:
11 |
12 | - Variables hold only values of the declared type.
13 | - Functions receive and return the correct types.
14 | - Type mismatches are caught at compile time, before running the code.
15 |
16 | ```ts
17 | let age: number = 25;
18 | age = "hello"; // Error: Type 'string' is not assignable to type 'number'.
19 | ```
20 |
21 |
22 | ## Inference
23 |
24 | Typescript knows javascript language and will generate types automatically most of the time , this is called inference .but you can also specify types explicitly
25 |
26 | ```js
27 | let helloWorld = "Hello World";
28 | ```
29 | *Above line is inferred to be string*
30 |
31 | ## type Aliases
32 |
33 | - `type` is a keyword in TypeScript that we can use to define the shape of data.
34 | - It does not create new types, it simply renames existing ones (Alias).
35 | - `type` can alias primitives, unions, intersections, tuples, and objects.
36 |
37 | ```ts
38 | type ID = number; // Alias for number
39 | type Coordinates = [number, number]; // Alias for a tuple
40 |
41 | let userId: ID = 123; // Same as 'let userId: number = 123'
42 | let point: Coordinates = [10, 20]; // Tuple
43 | ```
44 |
45 | ## Type Assertions
46 | Type Assertion is a way to tell TypeScript the exact type of a value when TypeScript cannot infer it automatically.
47 | - It does not perform type conversion, only informs TypeScript about the type.
48 | - Used when you know the type better than TypeScript (e.g., from API responses, DOM elements).
49 |
50 | There are two ways to write a type assertion in TypeScript:
51 |
52 | 1. Using the `as` keyword
53 |
54 | ```ts
55 | let value: any = "Hello, TypeScript";
56 |
57 | // Method 1: Using `as` syntax (Recommended)
58 | let strLength1: number = (value as string).length;
59 | console.log(strLength1); // 16
60 | ```
61 |
62 | 2. Using the `` syntax
63 |
64 | ```ts
65 | let value: any = "Hello, TypeScript";
66 |
67 | // Method 2: Using `` syntax
68 | let strLength2: number = value.length;
69 | console.log(strLength2); // 16
70 | ```
71 | - Both methods tell TypeScript that value is a string, so we can safely access .length.
72 |
73 | - The `` syntax does not work in JSX/TSX files (React projects), so as syntax is preferred.
74 |
75 | ## Type Casting
76 | - Type Casting is the process of converting a variable from one type to another at runtime.
77 | - Unlike Type Assertion, which only tells TypeScript the type without changing it, Type Casting actually converts the value.
78 |
79 | ```ts
80 | let num: number = 42;
81 | let str: string = String(num); // Converts number to string
82 |
83 | console.log(typeof str, str); // "string", "42"
84 | ```
85 | ### Force Casting
86 | Force Casting (also called double casting or casting with unknown) is when we bypass TypeScript’s type checks and manually tell TypeScript that a value is of a specific type, even if it's not actually safe.
87 | - It is done using as unknown as Type to override TypeScript’s type checking.
88 |
89 | ```ts
90 | let value: any = "Hello";
91 |
92 | // Force cast `value` to a number (unsafe)
93 | let num: number = value as unknown as number;
94 |
95 | console.log(num); // Runtime error if used incorrectly
96 | ```
97 | # Types
98 |
99 | TypeScript provides a robust type system that helps developers work with fundamental units of data such as `numbers`, `strings`, `booleans`, `objects`, and more. It builds upon JavaScript's existing types while introducing additional features like `enums` for better organization and type safety. TypeScript's type system ensures code reliability and readability, making it easier to catch errors and maintain large-scale applications
100 |
101 | ## Bascic Types
102 |
103 | 1. ### Boolean
104 |
105 | The most basic datatype is the simple true/false value, which JavaScript and TypeScript call a `boolean` value.
106 |
107 | ```ts
108 | let isDone: boolean = false;
109 | ```
110 |
111 | 2. ### Number
112 |
113 | - As in JavaScript, all numbers in TypeScript are floating point values.
114 | - These floating point numbers get the type `number`.
115 | - In addition to hexadecimal and decimal literals, TypeScript also supports binary and octal literals
116 |
117 | ```ts
118 | let decimal: number = 6;
119 | let hex: number = 0xf00d;
120 | let binary: number = 0b1010;
121 | let octal: number = 0o744;
122 | ```
123 |
124 | 3. ### String
125 |
126 | To represent text, TypeScript uses the `string` type. You can use either double or single quotes to create a string value.
127 |
128 | ```ts
129 | let color: string = "blue";
130 | color = 'red';
131 | ```
132 |
133 | You can also use *template strings*, which can span multiple lines and have embedded expressions.
134 | These strings are surrounded by the backtick/backquote (`` ` ``) character, and embedded expressions are of the form `${ expr }`.
135 |
136 | ```ts
137 | let fullName: string = `Bob Bobbington`;
138 | let age: number = 37;
139 | let sentence: string = `Hello, my name is ${ fullName }.
140 |
141 | I'll be ${ age + 1 } years old next month.`;
142 | ```
143 |
144 | 4. ### Array
145 |
146 | TypeScript, like JavaScript, allows you to work with arrays of values.
147 | Array types can be written in one of two ways.
148 | In the first, you use the type of the elements followed by `[]` to denote an array of that element type:
149 |
150 | ```ts
151 | let list: number[] = [1, 2, 3];
152 | ```
153 |
154 | The second way uses a generic array type, `Array`:
155 |
156 | ```ts
157 | let list: Array = [1, 2, 3];
158 | ```
159 |
160 | 5. ### Tuple
161 |
162 | Tuple types allow you to express an array with a fixed number of elements whose types are known, but need not be the same. For example, you may want to represent a value as a pair of a `string` and a `number`:
163 |
164 | ```ts
165 | // Declare a tuple type
166 | let x: [string, number];
167 | // Initialize it
168 | x = ["hello", 10]; // OK
169 | // Initialize it incorrectly
170 | x = [10, "hello"]; // Error
171 | ```
172 |
173 | When accessing an element with a known index, the correct type is retrieved:
174 |
175 | ```ts
176 | console.log(x[0].substring(1)); // OK
177 | console.log(x[1].substring(1)); // Error, 'number' does not have 'substring'
178 | ```
179 |
180 | Accessing an element outside the set of known indices fails with an error:
181 |
182 | ```ts
183 | x[3] = "world"; // Error, Property '3' does not exist on type '[string, number]'.
184 |
185 | console.log(x[5].toString()); // Error, Property '5' does not exist on type '[string, number]'.
186 | ```
187 |
188 | 6. ### Enum
189 |
190 | An enum is a way of giving more friendly names to sets of numeric values.It allow developers to define set of named constants.Typescript allow both numeric and string based enums.
191 |
192 | ```ts
193 | enum Color {Red, Green, Blue}
194 | let c: Color = Color.Green;
195 | ```
196 |
197 | By default, enums begin numbering their members starting at `0`.
198 | You can change this by manually setting the value of one of its members.
199 | For example, we can start the previous example at `1` instead of `0`:
200 |
201 | ```ts
202 | enum Color {Red = 1, Green, Blue}
203 | let c: Color = Color.Green;
204 | ```
205 |
206 | Or, even manually set all the values in the enum:
207 |
208 | ```ts
209 | enum Color {Red = 1, Green = 2, Blue = 4}
210 | let c: Color = Color.Green;
211 | ```
212 |
213 | A handy feature of enums is that you can also go from a numeric value to the name of that value in the enum.
214 | For example, if we had the value `2` but weren't sure what that mapped to in the `Color` enum above, we could look up the corresponding name:
215 |
216 | ```ts
217 | enum Color {Red = 1, Green, Blue}
218 | let colorName: string = Color[2];
219 |
220 | console.log(colorName); // Displays 'Green' as its value is 2 above
221 | ```
222 |
223 | 7. ### Any
224 |
225 | Sometimes we do not always have prior knowledge about the type of some variables, especially when there are user-entered values from third party libraries. In such cases, we need a provision that can deal with dynamic content. The Any type comes in handy here
226 |
227 | ```ts
228 | let something: any = "Hello World!";
229 | something = 23;
230 | something = true;
231 | ```
232 |
233 |
234 | 8. ### Void
235 |
236 | `void` type is used where there is no data. For example, if a function does not return any value then you can specify void as return type
237 |
238 | ```ts
239 | function warnUser(): void {
240 | console.log("This is my warning message");
241 | }
242 | ```
243 |
244 | There is no meaning to assign void to a variable, as only null or undefined is assignable to void.
245 |
246 | ```ts
247 | let nothing: void = undefined;
248 | let num: void = 1; // Error
249 | ```
250 |
251 | 9. ### Null and Undefined
252 |
253 | In TypeScript, both `null` and `undefined` have their own distinct types: null and undefined. However, similar to void, they are not particularly useful on their own:
254 |
255 | ```ts
256 | // These variables can only hold their respective values
257 | let u: undefined = undefined;
258 | let n: null = null;
259 | ```
260 | **use cases**
261 |
262 | If a variable should accept string, null, or undefined, you can explicitly define it using a union
263 |
264 | ```ts
265 | let value: string | null | undefined;
266 | ```
267 |
268 | 10. ### Never
269 |
270 | - The `never` type represents the type of values that never occur.
271 | - The never type represents values which are never observed. In a return type, this means that the function throws an exception or terminates execution of the program
272 |
273 | example of functions returning `never`:
274 |
275 | ```ts
276 | // Function returning never must have unreachable end point
277 | function fail(message: string): never {
278 | throw new Error(message);
279 | }
280 | ```
281 | - never also appears when TypeScript determines there’s nothing left in a union.
282 |
283 | ```ts
284 | function fn(x: string | number) {
285 | if (typeof x === "string") {
286 | // do something
287 | } else if (typeof x === "number") {
288 | // do something else
289 | } else {
290 | x; // has type 'never'!
291 | }
292 | }
293 | ```
294 |
295 | 11. ### Object
296 |
297 | In TypeScript, the object type represents non-primitive values, meaning it includes anything that is not a `number`, `string`, `boolean`, `bigint`, `symbol`, `null`, or `undefined`.
298 |
299 | ```ts
300 | let obj: object = { name: "Alice", age: 25 };
301 | obj = [1, 2, 3]; // Arrays are also objects
302 | obj = function () { console.log("Hello"); }; // Functions are objects too
303 | ```
304 |
305 | - The object type allows assignment of any non-primitive value.
306 | - It does not specify the shape of an object (use interfaces or type aliases for that).
307 | - Unlike any, it prevents assigning primitive values like number or string.
308 |
309 | ```ts
310 | let obj: object;
311 | obj = 42; // Error: Type 'number' is not assignable to type 'object'
312 | obj = "hello"; // Error
313 | ```
314 |
315 | For defining `structured objects`, it's better to use an `interface` or `type alias` instead of object
316 |
317 | ```ts
318 | // Using Interface
319 | interface User {
320 | name: string;
321 | age: number;
322 | }
323 | let user: User = { name: "Bob", age: 30 };
324 | ```
325 | **or**
326 |
327 | ```ts
328 | // Using Type Alias
329 | type User = { name: string; age: number };
330 | let user: User = { name: "Bob", age: 30 };
331 | ```
332 |
333 | ## Advanced Types
334 |
335 | 1. ### Intersection Type
336 | An intersection type in TypeScript is created using the `&` operator. It allows you to combine multiple types into one, meaning the resulting type must have all the properties of the intersected types.
337 |
338 | ```ts
339 | type Person = { name: string };
340 | type Employee = { id: number };
341 |
342 | type EmployeeDetails = Person & Employee; // Intersection type
343 |
344 | const employee: EmployeeDetails = {
345 | name: "Alice",
346 | id: 101
347 | }; // ✅ Valid: Has both 'name' and 'id'
348 | ```
349 |
350 | - They merge multiple types, ensuring that the result has all the required properties.
351 | - If types have overlapping properties, they must be compatible.
352 |
353 | ```ts
354 | type A = { x: string };
355 | type B = { x: number };
356 |
357 | type C = A & B; // Error: 'x' cannot be both string and number
358 | ```
359 |
360 | 2. ### Interface
361 | TypeScript offers a first-class primitive for defining objects that extend from other objects - an interface.
362 | Interface defines a contract that an object must adhere to
363 |
364 | ```ts
365 | interface Client {
366 | name: string;
367 | address: string;
368 | }
369 | ```
370 | They're inspired by object-oriented programming and allow you to use inheritance to create types:
371 |
372 | ```ts
373 | interface WithId {
374 | id: string;
375 | }
376 |
377 | interface User extends WithId {
378 | name: string;
379 | }
380 |
381 | const user: User = {
382 | id: "123",
383 | name: "Karl"
384 | };
385 |
386 | ```
387 |
388 | also you can extend using ```Intersection Type```
389 |
390 | ```ts
391 | type WithId = {
392 | id: string;
393 | };
394 |
395 | type User = WithId & {
396 | name: string;
397 | };
398 |
399 | const user: User = {
400 | id: "123",
401 | name: "Karl",
402 | };
403 |
404 | ```
405 | *but this method is slightly less optimal because it requires creating a new type for each combination.*
406 |
407 | 3. ### Union Types
408 | A union type is TypeScript's way of saying that a value can be "either this type or that type".
409 |
410 | This situation comes up in JavaScript all the time. Imagine you have a value that is a string on Tuesdays, but null the rest of the time:
411 |
412 | in Javascript
413 |
414 | ```js
415 | const message = Date.now() % 2 === 0 ? 'Hello Tuesdays!' : null
416 |
417 | const message: "Hello Tuesdays!" | null
418 | ```
419 |
420 | - In TypeScript, you can do the same thing using a union type:
421 |
422 | - To create a union type, the `|` operator is used to separate the types. Each type of the union is called a 'member' of the union.
423 |
424 | For example, you might have an id that could be either a string or a number
425 |
426 | ```ts
427 | const logId = (id: string | number) => {
428 | console.log(id)
429 | }
430 | ```
431 | *here we can only pass string or number as a type else shows error*
432 |
433 | 4. ### Literal Types
434 |
435 | Just as TypeScript allows us to create union types from multiple types, it also allows us to create types which represent a specific primitive value. These are called literal types.
436 |
437 | Literal types can be used to represent strings, numbers, or booleans that have specific values.
438 |
439 | ```ts
440 | type YesOrNo = 'yes' | 'no'
441 | type StatusCode = 200 | 404 | 500
442 | type TrueOrFalse = true | false
443 | ```
444 |
445 | In the YesOrNo type, the `|` operator is used to create a union of the string literals "yes" and "no". This means that a value of type YesOrNo can only be one of these two strings.
446 |
447 | *actually Literal Types powers the autocomplete we've seen in functions like **document.addEventListener** in typescript*
448 |
449 | 5. ### Utility Types
450 |
451 | We've seen how using interface extends can help us model inheritance, but TypeScript also gives us tools to directly manipulate object types. With its built-in utility types, we can remove properties from types, make them optional, and more.
452 |
453 | #### 1.Partial Type
454 |
455 | - The Partial utility type lets you create a new object type from an existing one, except all of its properties are optional.
456 |
457 | Ex : Consider an Album interface that contains detailed information about an album
458 |
459 | ```ts
460 | interface Album {
461 | id: number;
462 | title: string;
463 | artist: string;
464 | releaseYear: number;
465 | genre: string;
466 | }
467 | ```
468 | When we want to update an album's information, we might not have all the information at once. For example, it can be difficult to decide what genre to assign to an album before it's released.
469 |
470 | Using the Partial utility type and passing in Album, we can create a type that allows us to update any subset of an album's properties:
471 |
472 | ```ts
473 | type PartialAlbum = Partial;
474 | ```
475 |
476 | Now we have a PartialAlbum type where id, title, artist, releaseYear, and genre are all optional.
477 |
478 | This means we can create a function which only receives a subset of the album's properties:
479 |
480 | ```ts
481 | const updateAlbum = (album: PartialAlbum) => {
482 | // ...
483 | };
484 |
485 | updateAlbum({ title: "Geogaddi", artist: "Boards of Canada" });
486 | ```
487 |
488 | #### 2.Required Type
489 |
490 | - On the opposite side of Partial is the Required type, which makes sure all of the properties of a given object type are required.
491 |
492 | This Album interface has the releaseYear and genre properties marked as optional:
493 |
494 | ```ts
495 | interface Album {
496 | title: string;
497 | artist: string;
498 | releaseYear?: number;
499 | genre?: string;
500 | }
501 | ```
502 |
503 | - We can use the Required utility type to create a new RequiredAlbum type:
504 |
505 | ```ts
506 | type RequiredAlbum = Required;
507 | ```
508 | With RequiredAlbum, all of the original Album properties become required, and omitting any of them would result in an error:
509 |
510 | #### 3. Pick Type
511 | The Pick utility type allows you to create a new object type by picking certain properties from an existing object.
512 |
513 | For example, say we want to create a new type that only includes the `title` and `artist` properties from the `Album` type:
514 |
515 | ```js
516 | type AlbumData = Pick;
517 | ```
518 | - This results in `AlbumData` being a type that only includes the `title` and `artist` properties.
519 |
520 | - This is extremely useful when you want to have one object that relies on the shape of another object. We'll explore this more in the chapter on deriving types from other types.
521 |
522 | #### 4. Omit Type
523 |
524 | The Omit helper type is kind of like the opposite of Pick. It allows you to create a new type by excluding a subset of properties from an existing type.
525 |
526 | For example, we could use Omit to create the same AlbumData type we created with Pick, but this time by excluding the id, releaseYear and genre properties:
527 | ```ts
528 | type AlbumData = Omit;
529 | ```
530 | - A common use case is to create a type without id, for situations where the id has not yet been assigned:
531 |
532 | ```ts
533 | type AlbumData = Omit;
534 | ```
535 | This means that as Album gains more properties, they will flow down to AlbumData too.
536 |
537 |
538 | #### 5. Readonly Type
539 |
540 | - The Readonly utility type lets you create a new object type from an existing one, except all of its properties are readonly.
541 |
542 | ```ts
543 | type Person = {
544 | name: string;
545 | age: number;
546 | };
547 |
548 | const freezePerson = (person: Readonly) => {
549 | console.log(`Name: ${person.name}, Age: ${person.age}`);
550 |
551 | person.age = 30; // Error: Cannot assign to 'age' because it is a read-only property
552 | };
553 |
554 | const user: Readonly = { name: "Alice", age: 25 };
555 |
556 | // This function can read properties but not modify them
557 | freezePerson(user);
558 |
559 | ```
560 | 6. ### Generic Types
561 |
562 | **Generics:**
563 |
564 | Generics allow you to create reusable, flexible, and type-safe code by making types dynamic. Instead of hardcoding a specific type, generics let you define a type as a parameter that can be used later.
565 |
566 | A generic type acts like a type function that takes a type as an argument and returns a type. This makes it useful for creating reusable and adaptable code structures.
567 |
568 | *Ex:Generic Function:*
569 |
570 | ```ts
571 | function identity(value: T): T {
572 | return value;
573 | }
574 |
575 | console.log(identity(10)); // ✅ 10
576 | console.log(identity("Hello")); // ✅ "Hello"
577 | ```
578 |
579 | *Ex:Generic type alias:*
580 |
581 | ```ts
582 | type Pair = { first: T; second: U };
583 |
584 | const coordinates: Pair = { first: 10, second: 20 };
585 | const userPair: Pair = { first: "Alice", second: 25 };
586 |
587 | console.log(coordinates); // ✅ { first: 10, second: 20 }
588 | console.log(userPair); // ✅ { first: "Alice", second: 25 }
589 | ```
590 | - Here We can pass any type as an argument to the Pair type.
591 | - We have more control over the type rather than hardcoding a specific type. or using `any` as a type parameter.
592 |
593 | 7. ### Template Literal Types
594 | Similar to how template literals in JavaScript allow you to interpolate values into strings, template literal types in TypeScript can be used to interpolate other types into string types.
595 |
596 | For example, let's create a PngFile type that represents a string that ends with ".png":
597 | ```ts
598 | type PngFile = `${string}.png`;
599 | ```
600 | Now when we type a new variable as PngFile, it must end with ".png":
601 |
602 | ```ts
603 | let myImage: PngFile = "my-image.png"; // OK
604 | ```
605 | When a string does not match the pattern defined in the PngFile type, TypeScript will raise an error:
606 | ```ts
607 | let myImage: PngFile = "my-image.jpg";
608 | //Error: Type '"my-image.jpg"' is not assignable to type '`${string}.png`'.
609 | ```
610 | 8. ### Mapped Types
611 | Mapped types in TypeScript allow you to create a new object type based on an existing type by iterating over its keys and values. This can be let you be extremely expressive when creating new object types.
612 |
613 | - A mapped type uses the `in` keyword to iterate over the keys of an existing type:
614 |
615 | ```ts
616 | type MappedType = {
617 | [K in keyof T]: T[K];
618 | };
619 | ```
620 |
621 | - The `keyof` keyword is used to get the keys of the existing type.
622 | - The `in` keyword is used to iterate over the keys of the existing type.
623 | - The `T[K]` syntax is used to access the value of the key `K` in the type `T`.
624 |
625 | **Example for copying a type USing Mapped Type:**
626 |
627 | ```ts
628 | type User = { name: string; age: number };
629 |
630 | type UserCopy = { [K in keyof User]: User[K] }; // Same as User
631 |
632 | const user: UserCopy = { name: "Alice", age: 25 }; // ✅ Valid
633 | ```
634 |
635 | **Example 2: Making Properties Readonly**
636 |
637 | ```ts
638 | type ReadonlyUser = { readonly [K in keyof T]: T[K] };
639 |
640 | type User = { name: string; age: number };
641 |
642 | const user: ReadonlyUser = { name: "Alice", age: 25 };
643 |
644 | user.name = "Bob"; // ❌ Error: Cannot assign to 'name' because it is readonly
645 | ```
646 |
647 | *You might wonder why we used `Mapped type` for this. If have the same result using `Readonly` utility type.*
648 |
649 | - Actually The built-in `Readonly` utility type in TypeScript is internally implemented using a `mapped type`.
650 |
651 | 9. ### Conditional Types
652 | Conditional types allow you to create types that depend on a condition. They work similarly to JavaScript's if statements but at the type level.
653 |
654 | - In simpler terms, Conditional Types Work by Checking if a Generic Type Extends a Defined Type and Returning Values Accordingly
655 |
656 | Where to use?
657 | *Imagine we have to define type for a function that takes a type as a parameter and returns a new type based on the condition*
658 |
659 | ```ts
660 | type TypeCheck = T extends string ? string[] : number[];
661 |
662 | let data1: TypeCheck; // string[]
663 | let data2: TypeCheck; // number[]
664 | ```
665 |
666 | - Here using Conditional type we check the type is string or number and return string[] or number[] accordingly.
667 |
668 |
669 | # Classes and OOPS in TS
670 |
671 | TypeScript enhances JavaScript’s OOP capabilities by adding strict typing, access modifiers, and interfaces to classes. It supports the four OOP principles:
672 |
673 | 1️⃣ Encapsulation – Bundling data and behavior.
674 | 2️⃣ Abstraction – Hiding implementation details.
675 | 3️⃣ Inheritance – Extending functionality.
676 | 4️⃣ Polymorphism – Overriding and method flexibility.
677 |
678 | ## Classes
679 |
680 | `class` is a blueprint for creating objects. It defines the structure and behavior of the object.
681 |
682 | ```js
683 | class Person {
684 | name: string;
685 | age: number;
686 |
687 | constructor(name: string, age: number) {
688 | this.name = name;
689 | this.age = age;
690 | }
691 |
692 | greet(): void {
693 | console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
694 | }
695 | }
696 |
697 | const person1 = new Person("Alice", 25);
698 | person1.greet(); // ✅ "Hello, my name is Alice and I am 25 years old."
699 | ```
700 |
701 | ## Implementation of OOPs Principles
702 |
703 | ### Encapsulation
704 | Encapsulation is the practice of hiding the internal details of an object from the outside world. In TypeScript, this is achieved using access modifiers, such as private, protected, and public.
705 |
706 | ```ts
707 | class Employee {
708 | public name: string; // Accessible anywhere
709 | private salary: number; // Accessible only inside the class
710 |
711 | constructor(name: string, salary: number) {
712 | this.name = name;
713 | this.salary = salary;
714 | }
715 |
716 | getSalary(): number {
717 | return this.salary;
718 | }
719 | }
720 |
721 | const emp = new Employee("Bob", 50000);
722 | console.log(emp.name); // Allowed (public)
723 | console.log(emp.getSalary()); // Allowed (public method)
724 | console.log(emp.salary); // Error: 'salary' is private
725 | ```
726 | **Access Modifiers:**
727 | TypeScript provides access modifiers to control the visibility of class members (properties and methods). These are:
728 |
729 | - `public` → Accessible everywhere (default).
730 | - `private` → Accessible only within the class.
731 | - `protected` → Accessible within the class and its subclasses.
732 |
733 | | **Modifier** | **Inside Class** | **Subclass** | **Outside Class** |
734 | |:-------------:|:----------------:|:------------:|:-----------------:|
735 | | **public** | YES | YES | YES |
736 | | **private** | YES | NO | NO |
737 | | **protected** | YES | YES | NO |
738 |
739 | ### Inheritance
740 | Inheritance allows a class to inherit properties and behavior from another class. It enables code reuse and promotes a hierarchy of classes. It can done by using the `extends` keyword.
741 |
742 | ```ts
743 | class Animal {
744 | constructor(public name: string) {}
745 |
746 | makeSound(): void {
747 | console.log(`${this.name} makes a sound.`);
748 | }
749 | }
750 |
751 | class Dog extends Animal {
752 | bark(): void {
753 | console.log(`${this.name} barks.`);
754 | }
755 | }
756 |
757 | const myDog = new Dog("Buddy");
758 | myDog.makeSound(); // ✅ "Buddy makes a sound."
759 | myDog.bark(); // ✅ "Buddy barks."
760 | ```
761 | ### Polymorphism
762 | Polymorphism allows a single interface (method or class) to be used for different types of objects. It enables reusability and flexibility in code by allowing different classes to share the same method names but with different behaviors.
763 |
764 | **Types of Polymorphism in TypeScript**
765 |
766 | 1. **Method Overriding (Runtime Polymorphism)** → A subclass provides a new implementation for a method inherited from a parent class.
767 |
768 | ```ts
769 | class Animal {
770 | makeSound(): void {
771 | console.log("Some generic animal sound.");
772 | }
773 | }
774 |
775 | class Dog extends Animal {
776 | makeSound(): void { // Overriding parent method
777 | console.log("Woof! Woof!");
778 | }
779 | }
780 |
781 | const myDog = new Dog();
782 | myDog.makeSound(); // ✅ "Woof! Woof!"
783 |
784 | ```
785 |
786 | 2. **Method Overloading (Compile-time Polymorphism)** → A single class has multiple method signatures with different parameters.
787 |
788 | ```ts
789 | class MathOperations {
790 | add(a: number, b: number): number; // Overload signature
791 | add(a: string, b: string): string; // Overload signature
792 | add(a: any, b: any): any { // Actual implementation
793 | return a + b;
794 | }
795 | }
796 |
797 | const math = new MathOperations();
798 | console.log(math.add(5, 10)); // ✅ 15 (number + number)
799 | console.log(math.add("Hello, ", "World!")); // ✅ "Hello, World!" (string + string)
800 | ```
801 | ### Abstraction
802 | Abstraction is the process of hiding the internal details of a system from the outside world. It allows you to focus on the important parts of the system and ignore the less important parts.
803 |
804 | - Abstract classes cannot be instantiated and must be extended by other classes.
805 |
806 | ```ts
807 | abstract class Shape {
808 | abstract getArea(): number; // Must be implemented by subclasses
809 | }
810 |
811 | class Circle extends Shape {
812 | constructor(private radius: number) {
813 | super();
814 | }
815 |
816 | getArea(): number {
817 | return Math.PI * this.radius * this.radius;
818 | }
819 | }
820 |
821 | const myCircle = new Circle(5);
822 | console.log(myCircle.getArea()); // ✅ 78.54
823 | ```
824 |
825 | ## Difference Between Interface, Class, and Abstract Class in TypeScript
826 |
827 | | **Feature** | **Interface** | **Class** | **Abstract Class** |
828 | |:--------------------------------------------------:|:-----------------------------------------------------:|:-------------------------------------------:|:-----------------------------------------------:|
829 | | **Purpose** | Defines a structure (contract) without implementation | Creates objects with both data and behavior | Acts as a blueprint with partial implementation |
830 | | **Can Have Method Implementations?** | No (only method signatures) | YES | Yes (can have abstract and concrete methods) |
831 | | **Can Have a Constructor?** | NO | YES | YES |
832 | | **Can Have Properties With Values?** | NO (only declarations) | YES | YES |
833 | | **Access Modifiers (public, private, protected)?** | NO | YES | YES |
834 | | **Can Extend Another Class?** | NO (but can extend another interface) | YES (extends) | YES (extends) |
835 | | **Can Implement an Interface?** | YES (implements) | YES (implements) | YES (implements) |
836 | | **Can a Class Extend Multiple?** | Yes (Multiple implements) | NO (Only one extends) | NO (Only one extends) |
837 | | **Can Be Instantiated (Used to Create Objects)?** | NO | YES | NO (must be extended by a subclass) |
838 | | **Usage** | Used to enforce structure (e.g., shape of an object) | Used to create objects | Used to enforce structure + shared behavior |
839 |
840 | ## Getters and Setters
841 |
842 | Getters and setters are methods that allow you to access and modify properties of an object in a controlled way. They provide a way to retrieve and set values for private properties of a class.
843 |
844 | ```ts
845 | class BankAccount {
846 | private _balance: number = 0;
847 |
848 | get balance(): number {
849 | return this._balance;
850 | }
851 |
852 | set balance(amount: number) {
853 | if (amount >= 0) {
854 | this._balance = amount;
855 | } else {
856 | console.log("Invalid balance amount.");
857 | }
858 | }
859 | }
860 |
861 | const account = new BankAccount();
862 | account.balance = 1000; // ✅ Sets balance
863 | console.log(account.balance); // ✅ Gets balance (1000)
864 | account.balance = -500; // ❌ "Invalid balance amount."
865 | ```
866 |
867 | # Important Topics
868 |
869 | ## Declaration Merging
870 | Declaration merging is a feature in TypeScript that allows multiple declarations of the same name to be combined into a single definition at compile time.
871 | ```ts
872 | interface User {
873 | name: string;
874 | }
875 |
876 | interface User {
877 | age: number;
878 | }
879 |
880 | // TypeScript merges both interfaces into one:
881 | const user: User = {
882 | name: "Alice",
883 | age: 25,
884 | };
885 |
886 | console.log(user.name, user.age); // ✅ "Alice", 25
887 | ```
888 | - Helps extend existing interfaces without modifying the original definition.
889 | - Useful when adding extra properties to third-party interfaces.
890 |
891 | ## Function Signature in TypeScript
892 | A function signature defines the parameter types and return type of a function without providing its implementation. It acts as a blueprint for functions, ensuring type safety and consistency.
893 |
894 | ```ts
895 | // Function signature (only type declaration)
896 | type MathOperation = (a: number, b: number) => number;
897 |
898 | // Function implementation matching the signature
899 | const add: MathOperation = (x, y) => x + y;
900 | const multiply: MathOperation = (x, y) => x * y;
901 |
902 | console.log(add(5, 10)); // ✅ 15
903 | console.log(multiply(5, 10)); // ✅ 50
904 | ```
905 | *Here, MathOperation is a function signature, ensuring that add and multiply both accept two numbers and return a number.*
906 |
907 | ## Duck Typing
908 | Duck typing is a concept in TypeScript (and other dynamically typed languages) where an object's type is determined by its shape (properties and methods) rather than explicitly declaring its type.
909 |
910 | - In TypeScript, if an object has the required properties and methods of a type, it is considered to be of that type, even if it wasn’t explicitly declared as such.
911 |
912 |
913 | ```ts
914 | interface Add {
915 | (a: number, b: number): number;
916 | }
917 |
918 | const addNumbers: Add = (x, y) => x + y; // ✅ Allowed (same function signature)
919 |
920 | console.log(addNumbers(5, 10)); // 15
921 | ```
922 |
923 | *Since addNumbers matches the function signature of Add, it is automatically considered of type Add.*
924 |
925 | or Duck Typing Restriction
926 |
927 | ```ts
928 | interface Car {
929 | brand: string;
930 | drive(): void;
931 | }
932 |
933 | const bike = {
934 | brand: "Yamaha",
935 | // Missing 'drive' method
936 | };
937 |
938 | let myCar: Car = bike; // Error: Property 'drive' is missing
939 | ```
940 | *bike is not assignable to Car because it does not have a drive() method.*
941 |
942 | ## String Interpolation
943 | String interpolation is a way to embed variables or expressions inside a string using template literals (backticks `) instead of regular string concatenation.
944 |
945 | ```ts
946 | const name = "Alice";
947 | const age = 25;
948 |
949 | console.log(`Hello, my name is ${name} and I am ${age} years old.`);
950 | // ✅ "Hello, my name is Alice and I am 25 years old."
951 | ```
952 |
953 | ## Narrowing
954 | Narrowing is the process of refining a general type (like unknown or a union type) into a more specific type using TypeScript’s type-checking techniques.
955 |
956 | - Narrowing prevents runtime errors by ensuring that only valid operations are performed on a value.
957 |
958 | Example: Without Narrowing (Causes Error)
959 |
960 | ```ts
961 | function printLength(value: string | number) {
962 | console.log(value.length); // ❌ Error: Property 'length' does not exist on type 'number'.
963 | }
964 | ```
965 |
966 | ### 1. Type Guard Narrowing (typeof)
967 | Use typeof to check primitive types before performing operations.
968 |
969 | ```ts
970 | function printLength(value: string | number) {
971 | if (typeof value === "string") {
972 | console.log(`String length: ${value.length}`); // ✅ Allowed
973 | } else {
974 | console.log(`Number: ${value}`); // ✅ Allowed
975 | }
976 | }
977 |
978 | printLength("Hello"); // ✅ "String length: 5"
979 | printLength(42); // ✅ "Number: 42"
980 | ```
981 |
982 | ### 2. Type Guard Narrowing (instanceof)
983 | Use instanceof to check object types before performing operations.
984 |
985 | ```ts
986 | class Dog {
987 | bark() {
988 | console.log("Woof!");
989 | }
990 | }
991 |
992 | class Cat {
993 | meow() {
994 | console.log("Meow!");
995 | }
996 | }
997 |
998 | function makeSound(animal: Dog | Cat) {
999 | if (animal instanceof Dog) {
1000 | animal.bark(); // ✅ Safe to call
1001 | } else {
1002 | animal.meow(); // ✅ Safe to call
1003 | }
1004 | }
1005 |
1006 | const dog = new Dog();
1007 | makeSound(dog); // ✅ "Woof!"
1008 | ```
1009 |
1010 | ### 3. Type Guard Narrowing (in)
1011 | Use in to check if a value exists in an array or object.
1012 |
1013 | ```ts
1014 | type User = { name: string; email: string };
1015 | type Admin = { name: string; permissions: string[] };
1016 |
1017 | function checkUser(user: User | Admin) {
1018 | if ("permissions" in user) {
1019 | console.log(`Admin permissions: ${user.permissions.join(", ")}`);
1020 | } else {
1021 | console.log(`User email: ${user.email}`);
1022 | }
1023 | }
1024 |
1025 | const admin: Admin = { name: "Alice", permissions: ["read", "write"] };
1026 | checkUser(admin); // ✅ "Admin permissions: read, write"
1027 | ```
1028 | ## Mixins
1029 | Mixins are a way to combine multiple class behaviors into a single class without using traditional inheritance.
1030 | - They allow reusing methods from multiple sources without deep class hierarchies.
1031 | - TypeScript does not support multiple inheritance, so Mixins provide an alternative
1032 |
1033 | Mixin help to
1034 | - **Reusability** – Share behavior across multiple classes.
1035 | - **Avoid Deep Inheritance** – Prevents complex class hierarchies.
1036 | - **Multiple Behaviors** – A class can inherit features from multiple mixins.
1037 |
1038 | ```ts
1039 | // Mixin Function
1040 | type Constructor = new (...args: any[]) => T;
1041 |
1042 | function CanEat(Base: T) {
1043 | return class extends Base {
1044 | eat() {
1045 | console.log("Eating...");
1046 | }
1047 | };
1048 | }
1049 |
1050 | function CanSleep(Base: T) {
1051 | return class extends Base {
1052 | sleep() {
1053 | console.log("Sleeping...");
1054 | }
1055 | };
1056 | }
1057 |
1058 | // Base Class
1059 | class Animal {
1060 | name: string;
1061 | constructor(name: string) {
1062 | this.name = name;
1063 | }
1064 | }
1065 |
1066 | // Applying Mixins
1067 | class Dog extends CanEat(CanSleep(Animal)) {}
1068 |
1069 | const myDog = new Dog("Buddy");
1070 | myDog.eat(); // ✅ "Eating..."
1071 | myDog.sleep(); // ✅ "Sleeping..."
1072 | ```
1073 |
1074 | *Dog now has eat() and sleep() methods without directly inheriting them.*
1075 |
1076 | ## Decorators
1077 | A decorator in TypeScript is a special function that is used to modify classes, methods, properties, or parameters at design time.
1078 | - Decorators enhance or modify how classes and their members behave.
1079 | - They are prefixed with @ and can be applied to classes, methods, properties, accessors, and parameters.
1080 | - TypeScript decorators are mostly used in frameworks like Angular and NestJS for dependency injection, metadata handling, and more
1081 |
1082 | to enable decorators, we need to use the `--experimentalDecorators` flag when compiling TypeScript code in tsConfig.json.
1083 |
1084 | ### 1. Class Decorators (Modifying a Class)
1085 | A class decorator is applied to a class definition and can modify or replace the class.
1086 |
1087 | ```ts
1088 | function Logger(constructor: Function) {
1089 | console.log(`Class "${constructor.name}" was created.`);
1090 | }
1091 |
1092 | @Logger
1093 | class User {
1094 | constructor() {
1095 | console.log("User instance created.");
1096 | }
1097 | }
1098 |
1099 | // Output:
1100 | // "Class 'User' was created."
1101 | // "User instance created."
1102 | ```
1103 |
1104 | ### 2. Method Decorators (Modifying a Method)
1105 | A method decorator modifies how a method works.
1106 |
1107 | ```ts
1108 | function Log(target: any, methodName: string, descriptor: PropertyDescriptor) {
1109 | const originalMethod = descriptor.value;
1110 |
1111 | descriptor.value = function (...args: any[]) {
1112 | console.log(`Calling ${methodName} with arguments:`, args);
1113 | return originalMethod.apply(this, args);
1114 | };
1115 | }
1116 |
1117 | class MathOperations {
1118 | @Log
1119 | add(a: number, b: number) {
1120 | return a + b;
1121 | }
1122 | }
1123 |
1124 | const math = new MathOperations();
1125 | console.log(math.add(2, 3));
1126 |
1127 | // Output:
1128 | // ✅ "Calling add with arguments: [2, 3]"
1129 | // ✅ 5
1130 | ```
1131 |
1132 | ### 3. Property Decorators (Modifying a Property)
1133 | A property decorator can add metadata or modify property behavior.
1134 |
1135 | ```ts
1136 | function ReadOnly(target: any, propertyKey: string) {
1137 | Object.defineProperty(target, propertyKey, {
1138 | writable: false
1139 | });
1140 | }
1141 |
1142 | class Person {
1143 | @ReadOnly
1144 | name: string = "Alice";
1145 | }
1146 |
1147 | const p = new Person();
1148 | p.name = "Bob"; // Error: Cannot assign to 'name' because it is read-only.
1149 | ```
1150 | ## Dependency Injection
1151 | Dependency Injection (DI) is a design pattern used to inject dependencies (objects or services) into a class instead of creating them inside the class. This improves modularity, testability, and maintainability.
1152 |
1153 | - Instead of a class creating its dependencies, they are provided from the outside.
1154 | - DI helps reduce coupling between classes, making the code more flexible.
1155 |
1156 | Coupling refers to the degree of dependency between different components (classes, functions, or modules) in a system.
1157 |
1158 | | **Type** | **Definition** | **Example** |
1159 | |--------------------|---------------------------------------------------------------------------------------|----------------------------------------------------------------------------------|
1160 | | **Tight Coupling** | Strong dependency between components. Changes in one component affect others. | A class directly creates an instance of another class. |
1161 | | **Loose Coupling** | Minimal dependency between components. Changes in one component do not affect others. | A class receives dependencies from outside (e.g., via constructor or interface). |
1162 |
1163 | ### Example Without Dependency Injection (Tight Coupling)
1164 | ```ts
1165 | class EmailService {
1166 | sendEmail(message: string) {
1167 | console.log(`Sending email: ${message}`);
1168 | }
1169 | }
1170 |
1171 | class UserService {
1172 | private emailService = new EmailService(); // Hardcoded dependency
1173 |
1174 | notifyUser() {
1175 | this.emailService.sendEmail("Welcome to our app!");
1176 | }
1177 | }
1178 | ```
1179 |
1180 | ### Example With Dependency Injection (Loose Coupling)
1181 |
1182 | ```ts
1183 | class EmailService {
1184 | sendEmail(message: string) {
1185 | console.log(`Sending email: ${message}`);
1186 | }
1187 | }
1188 |
1189 | class UserService {
1190 | private emailService: EmailService;
1191 |
1192 | constructor(emailService: EmailService) {
1193 | this.emailService = emailService; // ✅ Injected dependency
1194 | }
1195 |
1196 | notifyUser() {
1197 | this.emailService.sendEmail("Welcome to our app!");
1198 | }
1199 | }
1200 |
1201 | // Inject EmailService when creating UserService
1202 | const emailService = new EmailService();
1203 | const userService = new UserService(emailService);
1204 |
1205 | userService.notifyUser(); // "Sending email: Welcome to our app!"
1206 | ```
1207 |
1208 | # Common Syntax and Best Practices
1209 |
1210 | ## Objects
1211 | ```ts
1212 | const user: { name: string; age: number } = { name: "Alice", age: 25 };
1213 | console.log(user.name); // ✅ "Alice"
1214 | ```
1215 | ## Interfaces
1216 | ```ts
1217 | interface Person {
1218 | name: string;
1219 | age?: number; // Optional property
1220 | }
1221 | const person: Person = { name: "Bob" };
1222 | ```
1223 | ## Arrays
1224 | ```ts
1225 | const numbers: number[] = [1, 2, 3];
1226 | console.log(numbers[0]); // ✅ 1
1227 | ```
1228 | ## Tuples
1229 | ```ts
1230 | const person: [string, number] = ["Alice", 25];
1231 | console.log(person[0]); // ✅ "Alice"
1232 | ```
1233 | ## Enums
1234 | ```ts
1235 | enum Status { Active, Inactive }
1236 | const userStatus: Status = Status.Active;
1237 | console.log(userStatus); // ✅ 0 (index)
1238 | ```
1239 | ### Union Types
1240 | ```ts
1241 | let value: string | number;
1242 | value = "Hello"; // Allowed
1243 | value = 42; // Allowed
1244 | ```
1245 | ## Type Aliases
1246 | ```ts
1247 | type User = { name: string; age: number };
1248 | const user: User = { name: "Alice", age: 25 };
1249 | ```
1250 | ## Functions
1251 |
1252 | ### 1. Normal Function (Named Function)
1253 | ```ts
1254 | function add(a: number, b: number): number {
1255 | return a + b;
1256 | }
1257 | console.log(add(2, 3)); // ✅ 5
1258 | ```
1259 | ### 2.Anonymous Function
1260 | ```ts
1261 | const multiply = function (a: number, b: number): number {
1262 | return a * b;
1263 | };
1264 | console.log(multiply(2, 3)); // ✅ 6
1265 | ```
1266 | ### 3. Arrow Function
1267 | ```ts
1268 | const subtract = (a: number, b: number): number => a - b;
1269 | console.log(subtract(5, 2)); // ✅ 3
1270 | ```
1271 | ## Rest Parameters (...args)
1272 | ```ts
1273 | function sum(...nums: number[]): number {
1274 | return nums.reduce((acc, num) => acc + num, 0);
1275 | }
1276 | console.log(sum(1, 2, 3)); // ✅ 6
1277 | ```
1278 | ## Spread Operator
1279 | ```ts
1280 | const arr1 = [1, 2];
1281 | const arr2 = [...arr1, 3, 4];
1282 | console.log(arr2); // ✅ [1, 2, 3, 4]
1283 | ```
1284 | ## Promises
1285 | ```ts
1286 | const fetchData = (): Promise => {
1287 | return new Promise((resolve) => setTimeout(() => resolve("Data loaded"), 1000));
1288 | };
1289 | fetchData().then(console.log); // ✅ "Data loaded"
1290 | ```
1291 | ## Async/Await
1292 | ```ts
1293 | async function getData() {
1294 | const data = await fetchData();
1295 | console.log(data); // ✅ "Data loaded"
1296 | }
1297 | getData();
1298 | ```
1299 | ## Classes and Inheritance
1300 | ```ts
1301 | class Animal {
1302 | constructor(public name: string) {}
1303 | makeSound() {
1304 | console.log("Animal sound");
1305 | }
1306 | }
1307 |
1308 | class Dog extends Animal {
1309 | makeSound() {
1310 | console.log("Woof!");
1311 | }
1312 | }
1313 |
1314 | const dog = new Dog("Buddy");
1315 | dog.makeSound(); // ✅ "Woof!"
1316 | ```
1317 | ## Generics
1318 | ```ts
1319 | function identity(value: T): T {
1320 | return value;
1321 | }
1322 | console.log(identity(10)); // ✅ 10
1323 | console.log(identity("Hello")); // ✅ "Hello"
1324 | ```
1325 | ## Type Assertion
1326 | ```ts
1327 | let value: any = "Hello";
1328 | let strLength: number = (value as string).length;
1329 | console.log(strLength); // ✅ 5
1330 | ```
--------------------------------------------------------------------------------