<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Abdisalan</title>
    <description>The latest articles on DEV Community by Abdisalan (@abdisalan_js).</description>
    <link>https://dev.to/abdisalan_js</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F154185%2F9ae66d86-6c88-4135-967c-fd8b001c6986.jpg</url>
      <title>DEV Community: Abdisalan</title>
      <link>https://dev.to/abdisalan_js</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/abdisalan_js"/>
    <language>en</language>
    <item>
      <title>5 Edge Cases No Programmer Likes Handling</title>
      <dc:creator>Abdisalan</dc:creator>
      <pubDate>Tue, 04 Oct 2022 06:32:39 +0000</pubDate>
      <link>https://dev.to/abdisalan_js/5-edge-cases-no-programmer-likes-handling-25nh</link>
      <guid>https://dev.to/abdisalan_js/5-edge-cases-no-programmer-likes-handling-25nh</guid>
      <description>&lt;p&gt;Life is usually simple and our clever little programs can handle most things thrown at it... but sometimes, it's not enough.&lt;/p&gt;

&lt;p&gt;That's where edge cases come in. Little, one-off, problems we must handle that disrupt the natural flow of our code.&lt;/p&gt;

&lt;p&gt;Here's five edge cases I don't like handling as a Software Engineer.&lt;/p&gt;

&lt;h2&gt;
  
  
  #5 Plural wording(s)
&lt;/h2&gt;

&lt;p&gt;Showing the user "item" when there's one item. Then also showing them "items" when it's more than one or zero.&lt;/p&gt;

&lt;p&gt;We've all been guilty of writing “item(s)”  with a parenthesis before, right? 🤨 But sometimes, we've gotta fix the bug.&lt;/p&gt;

&lt;p&gt;Look at this monstrosity I had to write the other day. I’m not proud of it, but it works.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"You have &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; item&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'s'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  #4 Styling the last element in a list
&lt;/h2&gt;

&lt;p&gt;You've probably run into this if you're coding React or Vue. Imagine you've rendering a list of items like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stuff&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SuperCoolItem&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="na"&gt;stuff&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="na"&gt;stuff&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;marginBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--krSQZxtG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4nwl5k7y5w5eufbvzk3g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--krSQZxtG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4nwl5k7y5w5eufbvzk3g.png" alt="Numbers 1 through 9 in a 3 by 3 grid. There's enough padding between rows 1, 2, and 3. However there is too much padding below the 3rd row." width="502" height="671"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That bottom margin works well...until the last element. So what do we do?&lt;/p&gt;

&lt;p&gt;We check if it’s the last element and then set the margin to zero. If you know a better way to do this, perhaps with a cool CSS trick, leave a comment on how! I would look it up, but I’ve moved on to other tasks ☕&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;stuff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SuperCoolItem&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="na"&gt;stuff&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="na"&gt;stuff&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;marginBottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  #3 Null
&lt;/h2&gt;

&lt;p&gt;Oops! Did you forget to check if the object you were using was actually null? Yea, me too! And in production...&lt;/p&gt;

&lt;p&gt;At this point, when I'm not writing TypeScript, I expect these to happen.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JavaScript:
Uncaught TypeError: criticalBusinessObject is undefined

Python:
AttributeError: 'NoneType' object has no attribute 'id'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  #2 Time Zones
&lt;/h2&gt;

&lt;p&gt;Oh, your cron jobs were set with a UTC time zone? Really? All our customers are on Pacific time, Abdi! Stop trying to confuse them with a magic timezone no one uses! (sorry to my African and European readers). I’m not even gonna get into it that some time zones are off by 30 minutes 💀.&lt;/p&gt;

&lt;p&gt;This is all a lead-in to the real reason I wrote this article. The biggest, most painful issue that comes up twice every year…&lt;/p&gt;

&lt;h2&gt;
  
  
  #1 Daylight Savings Time
&lt;/h2&gt;

&lt;p&gt;Perhaps the most destructive construct invented by the hubris of man.&lt;/p&gt;

&lt;p&gt;Here’s one of the scariest moments in my career. I’m sipping my latte on a beautiful, early spring morning and I hear this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;All our customers got their text messages 1 hour late! I want every engineer in the meeting room now!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;— startup CTO&lt;/p&gt;

&lt;p&gt;In America, only 48 US states observe it. That leaves Hawaii and most of Arizona (Navajo Nation observes Daylight Saving). Also, only about half the countries in the world observe it, and they don't even agree on when it should happen!&lt;/p&gt;

&lt;h3&gt;
  
  
  Thanks for reading 😊
&lt;/h3&gt;

&lt;p&gt;Those are my top 5! What are yours? Leave a comment below and let's chat about what we don't like 😼&lt;/p&gt;

&lt;p&gt;For my fellow Americans, don’t forget that Daylight Savings is November 6 this year and the clocks are &lt;em&gt;falling back&lt;/em&gt;. “Spring forward, Fall back” — good way of remembering.&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@elisa_ventur?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Elisa Ventur&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/despair?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>jokes</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How One Developer Recreated AirDrop Using Just JavaScript</title>
      <dc:creator>Abdisalan</dc:creator>
      <pubDate>Sat, 12 Dec 2020 21:15:50 +0000</pubDate>
      <link>https://dev.to/abdisalan_js/how-one-developer-recreated-airdrop-using-just-javascript-2403</link>
      <guid>https://dev.to/abdisalan_js/how-one-developer-recreated-airdrop-using-just-javascript-2403</guid>
      <description>&lt;p&gt;Have you ever used AirDrop on iPhone or Mac?&lt;/p&gt;

&lt;p&gt;Okay, If you haven't then can you imagine seamlessly sharing files between phones or a laptop at the tap of a button?&lt;/p&gt;

&lt;p&gt;&lt;a href="http://snapdrop.net" rel="noopener noreferrer"&gt;SnapDrop.net&lt;/a&gt;, created by Robin Linus, lets you &lt;em&gt;directly&lt;/em&gt; share files between any device with a browser. Doesn't matter if it's between iPhone and Android or a tablet with a PC.&lt;/p&gt;

&lt;p&gt;And no uploading to and downloading from the cloud needed. 😲&lt;/p&gt;

&lt;p&gt;So &lt;em&gt;how the heck&lt;/em&gt; does it work?&lt;/p&gt;

&lt;p&gt;After analyzing it line by line, I figured out its brilliant architecture. In this post I'll show you how it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use This New Technology
&lt;/h2&gt;

&lt;p&gt;Knowing this technology could set you apart from other engineers who haven't yet explored what it has to offer.&lt;/p&gt;

&lt;p&gt;This awesome technology is WebRTC (Web Real-Time Communication) and it only came out a few years ago. Its data channel enables SnapDrop to send bytes (even audio and video!) directly from one peer to another.&lt;/p&gt;

&lt;p&gt;(Think of a peer as a device, like your phone or laptop)&lt;/p&gt;

&lt;p&gt;However, WebRTC can't connect two users without some help. It needs a signaling server, in other words, something to discover other peers and show it how to connect.&lt;/p&gt;

&lt;h2&gt;
  
  
  WebRTC is Impossible To Use Without This
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbz9vsj51cnhvsize6i60.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbz9vsj51cnhvsize6i60.png" alt="Diagram of Architecture. NodeJS Server connected to a phone and computer over websockets. Phone and computer are connected with WebRTC"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ICE (Interactive Connectivity Establishment) is how a computer can draw a map from the internet to itself when it doesn't have a public IP address. This is due to NAT (Network Address Translation) that happens between your router and computer.&lt;/p&gt;

&lt;p&gt;Once the map has been made, you'll have find some way for these two devices to share their maps with each other. SnapDrop does this through a NodeJS server that communicates between each peer using WebSockets — another awesome protocol.&lt;/p&gt;

&lt;p&gt;Now you're probably thinking, is this secure?&lt;/p&gt;

&lt;h2&gt;
  
  
  Okay, But How Do You Secure This Thing?
&lt;/h2&gt;

&lt;p&gt;WebRTC in transit encrypts its data by default. That's cool and all but you also probably don't want to be sharing files with random people.&lt;/p&gt;

&lt;p&gt;SnapDrop only shares the ICE between two computers with the same IP address — meaning they're on the same network/wifi.&lt;/p&gt;

&lt;p&gt;It does this by creating rooms for each IP address and differentiates devices by generating a unique id.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="cm"&gt;/* Code to handle joining peers from the server */&lt;/span&gt;
&lt;span class="nf"&gt;_joinRoom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;peer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// if room doesn't exist, create it&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_rooms&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;peer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_rooms&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;peer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// add this peer to room&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_rooms&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;peer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;peer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;peer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You might not want to use this app while on public wifi since then anyone could send files to you. But in this pandemic, who's going outside anyway? 🤷‍♀️&lt;/p&gt;

&lt;p&gt;The code snippet above makes an interesting choice by storing the peers in an object on the server class. Normally you would expect a database to be used but this might be to simplify things and the app probably doesn't have a lot of traffic.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Familiar User Interface and User Experience
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftxz1083c3h39rzeqk079.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftxz1083c3h39rzeqk079.png" alt="SnapDrop Site with icons for 2 computers and a phone"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The style is almost exactly like AirDrop. Each device has a fun name and an icon to help distinguish each peer. Not only that but its also a progressive web app which gives it a few nice features like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Feels like a native app&lt;/li&gt;
&lt;li&gt;Notifications&lt;/li&gt;
&lt;li&gt;Live Updates&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What If The Device Doesn't Support WebRTC?
&lt;/h2&gt;

&lt;p&gt;By now most devices/browsers support WebRTC but in the event that they don't, SnapDrop has a fallback! In this case it uses the already established WebSocket connection to send the file data.&lt;/p&gt;

&lt;p&gt;However, this is less efficient and less secure because the data needs to first go to the server and before it reaches its final destination.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isRtcSupported&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;peer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rtcSupported&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;peers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;peer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RTCPeer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;peer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;peers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;peer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WSPeer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;peer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Event-Driven Code Style
&lt;/h2&gt;

&lt;p&gt;The code base is completely event-driven. You use this style when you want to decouple services from each other and allow processing as actions occur.&lt;/p&gt;

&lt;p&gt;This compliments WebRTC and WebSockets because they're also event-driven. When a message comes in, or a new peer joins, or a file wants to be sent — that's an event.&lt;/p&gt;

&lt;p&gt;It's really tough to follow at first because its not a linear process. Here's the class for registering and firing events.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Events&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;fire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatchEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CustomEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;detail&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Which lets you write event-driven code like this&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="nx"&gt;Events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;signal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_onMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;br&gt;
&lt;span class="nx"&gt;Events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;peers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_onPeers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;br&gt;
&lt;span class="nx"&gt;Events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;files-selected&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_onFilesSelected&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;br&gt;
&lt;span class="nx"&gt;Events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;send-text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_onSendText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;br&gt;
&lt;span class="nx"&gt;Events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;peer-left&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_onPeerLeft&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Check Out The Code Yourself&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;I hope you learned something today! If you want to explore the code for yourself, here's the github repository. &lt;a href="https://github.com/RobinLinus/snapdrop" rel="noopener noreferrer"&gt;https://github.com/RobinLinus/snapdrop&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The creator was also kind enough to create a docker compose file so that you could run and host this yourself. I wonder how many people are running their own SnapDrop instance?&lt;/p&gt;

&lt;h2&gt;
  
  
  Thanks for Reading!
&lt;/h2&gt;

&lt;p&gt;What do you think of this type of blog post? I feel like I had to write about it because this project taught me a few valuable lessons. Leave comment below and I'll get back to everyone!&lt;/p&gt;

&lt;p&gt;See you in the next one ✌&lt;/p&gt;

&lt;h2&gt;
  
  
  P.S. Support SnapDrop
&lt;/h2&gt;

&lt;p&gt;Wow! Didn’t think this would be so popular! 10,000+ of you have seen this article!&lt;/p&gt;

&lt;p&gt;Please consider supporting the project because it is free and has NO ADs and NO data collection.&lt;/p&gt;

&lt;p&gt;Link here: &lt;a href="https://github.com/RobinLinus/snapdrop#support-the-snapdrop-community" rel="noopener noreferrer"&gt;https://github.com/RobinLinus/snapdrop#support-the-snapdrop-community&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Code a Video Streaming Server using MongoDB</title>
      <dc:creator>Abdisalan</dc:creator>
      <pubDate>Sat, 28 Nov 2020 02:21:00 +0000</pubDate>
      <link>https://dev.to/abdisalan_js/how-to-stream-video-from-mongodb-using-nodejs-4ibi</link>
      <guid>https://dev.to/abdisalan_js/how-to-stream-video-from-mongodb-using-nodejs-4ibi</guid>
      <description>&lt;p&gt;Do you want to create a video streaming app and store videos in MongoDB? If you JUST want to learn about the streaming part, I made another (kind of successful) &lt;a href="https://dev.to/abdisalan_js/how-to-code-a-video-streaming-server-using-nodejs-2o0"&gt;post on it using purely NodeJS.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;BUT!&lt;/p&gt;

&lt;p&gt;If you also want to know how to store your videos in MongoDB and stream them from there through NodeJS, this is the post for you!&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Result
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fd01x8mfi44wdfkvmv6cr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fd01x8mfi44wdfkvmv6cr.png" alt="Buffing video of a bird"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just like the pure NodeJS solution, our final result will be a single HTML5 video that's streaming video from our server. Look at the grey bar in the timeline! That's buffering! 😃&lt;/p&gt;

&lt;p&gt;If you want to git clone the project, here's the link to the repo &lt;a href="https://github.com/Abdisalan/blog-code-examples/tree/master/mongo-http-video" rel="noopener noreferrer"&gt;https://github.com/Abdisalan/blog-code-examples/tree/master/mongo-http-video&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Easy Mode
&lt;/h2&gt;

&lt;p&gt;If you have docker installed, you can use my docker compose file to run the project without needing to install any packages. You just need to run these docker compose commands as well as copy the &lt;code&gt;bigbuck.mp4&lt;/code&gt; file from the &lt;code&gt;http-video-stream&lt;/code&gt; folder to the &lt;code&gt;mongo-http-video&lt;/code&gt; folder.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;span class="c"&gt;# When you're done with it, you can tear it down using&lt;/span&gt;
docker-compose down &lt;span class="nt"&gt;-v&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And the project will be running on &lt;code&gt;localhost:8000&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The rest of the article is instructions on how to build it from scratch. Enjoy!&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1: MongoDB
&lt;/h2&gt;

&lt;p&gt;MongoDB does not support Windows Subsystem for Linux (WSL), so you're better off using docker if you want to use WSL. Otherwise this should work in Windows just fine.&lt;/p&gt;

&lt;p&gt;Install MongoDB, and if you're on windows these next commands (exe files) should be located in &lt;code&gt;C:\Program Files\MongoDB\Server\4.4\bin&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Open a terminal in that folder OR add it to your PATH and start the &lt;code&gt;mongod&lt;/code&gt; process.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

mongod


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Part 2: Setup Node Project
&lt;/h2&gt;

&lt;p&gt;In another terminal, these commands will create a project folder and start your node project.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;mkdir &lt;/span&gt;mongo-video-stream
&lt;span class="nb"&gt;cd &lt;/span&gt;mongo-video-stream
npm init
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save&lt;/span&gt; express nodemon mongodb


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Part 3: index.html
&lt;/h2&gt;

&lt;p&gt;We need to create an page with an HTML5 Video element and set the source to &lt;code&gt;"/mongo-video"&lt;/code&gt; where our server will stream the video from mongoDB.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;HTTP Video Stream From MongoDB&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;video&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"videoPlayer"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"650"&lt;/span&gt; &lt;span class="na"&gt;controls&lt;/span&gt; &lt;span class="na"&gt;muted=&lt;/span&gt;&lt;span class="s"&gt;"muted"&lt;/span&gt; &lt;span class="na"&gt;autoplay&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/mongo-video"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"video/mp4"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/video&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Part 4: Index.js
&lt;/h2&gt;

&lt;p&gt;Lets setup our node server so that the root &lt;code&gt;"/"&lt;/code&gt; endpoint serves our index.html page.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Listening on port 8000!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Part 5: package.json -- Run our server
&lt;/h2&gt;

&lt;p&gt;Add a &lt;code&gt;start&lt;/code&gt; script to your &lt;code&gt;package.json&lt;/code&gt; so that we can run our server using &lt;code&gt;npm start&lt;/code&gt; command.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nodemon index.js"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now you should be able to run &lt;code&gt;npm start&lt;/code&gt;. Open your browser and go to &lt;code&gt;http://localhost:8000&lt;/code&gt; to see if it worked!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffj7fah22pgwdz7a6aiop.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffj7fah22pgwdz7a6aiop.png" alt="missing video"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Midway Check In
&lt;/h2&gt;

&lt;p&gt;How are you doing? Maybe drink some water, fix your posture, and relax your shoulders 😁&lt;/p&gt;

&lt;p&gt;You're about to get to the good part!&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 6: index.js (Uploading)
&lt;/h2&gt;

&lt;p&gt;We add an endpoint where we can upload a local video to mongodb. The video file I'm using is  &lt;code&gt;bigbuck.mp4&lt;/code&gt; and can be found on my github at &lt;a href="https://github.com/Abdisalan/blog-code-examples/tree/master/http-video-stream" rel="noopener noreferrer"&gt;https://github.com/Abdisalan/blog-code-examples/tree/master/http-video-stream&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However you can use your own video file!&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mongodb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongodb&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongodb://localhost:27017&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Sorry about this monstrosity -- just for demo purposes&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/init-video&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;mongodb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MongoClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// connect to the videos database&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;videos&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Create GridFS bucket to upload a large file&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;mongodb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GridFSBucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// create upload stream using GridFS bucket&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;videoUploadStream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;openUploadStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bigbuck&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// You can put your file instead of bigbuck.mp4&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;videoReadStream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createReadStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./bigbuck.mp4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Finally Upload!&lt;/span&gt;
    &lt;span class="nx"&gt;videoReadStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;videoUploadStream&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// All done!&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Done...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Listening on port 8000!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After saving the index.js file, your server should restart (because we're using nodemon). Once you have the video ready, you can go to &lt;code&gt;localhost:8000/init-video&lt;/code&gt; in your browser and it should have uploaded your local file to mongodb!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Almost there!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you want to double check that the file was uploaded, open another terminal and connect to mongodb.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

mongo


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then go to the videos database and count the number of documents in the &lt;code&gt;fs.files&lt;/code&gt; collection by GridFS.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

use videos
db.fs.files.count&lt;span class="o"&gt;()&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The count should be how many times you went to &lt;code&gt;localhost:8000/init-video&lt;/code&gt; because it uploads our video file every time you load &lt;code&gt;/init-video&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 7: index.js (Streaming)
&lt;/h2&gt;

&lt;p&gt;Lastly, we're gonna add the &lt;code&gt;/mongo-video&lt;/code&gt; endpoint to stream our video!&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/mongo-video&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;mongodb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MongoClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Check for range headers to find our start time&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Requires Range header&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;videos&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// GridFS Collection&lt;/span&gt;
    &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs.files&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;findOne&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No video uploaded!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="c1"&gt;// Create response headers&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;videoSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\D&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;videoSize&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contentLength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Range&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`bytes &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;videoSize&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Accept-Ranges&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bytes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Length&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;contentLength&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;video/mp4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;

      &lt;span class="c1"&gt;// HTTP Status 206 for Partial Content&lt;/span&gt;
      &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;206&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// Get the bucket and download stream from GridFS&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;mongodb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GridFSBucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;downloadStream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;openDownloadStreamByName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bigbuck&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;start&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="c1"&gt;// Finally pipe video to response&lt;/span&gt;
      &lt;span class="nx"&gt;downloadStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Save the file and go to &lt;code&gt;localhost:8000&lt;/code&gt; one more time and the video should be streaming!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;With this, you can make your own basic YouTube or Netflix app!&lt;/p&gt;

&lt;p&gt;For an in-depth line by line explanation with theory on how this works, &lt;a href="https://youtu.be/y6Z-SZt-Xvw" rel="noopener noreferrer"&gt;consider watching my YouTube video.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was a basic overview of how to get this working, if you want any in-depth blog posts on any of these topics (mongodb, streaming theory), feel free to comment down below!&lt;/p&gt;

&lt;p&gt;Happy Streaming! ✌&lt;/p&gt;

&lt;h3&gt;
  
  
  Disclaimer
&lt;/h3&gt;

&lt;p&gt;You probably shouldn't use this in production because its not the most optimized architecture 😋&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>How to Code a Video Streaming Server using NodeJS</title>
      <dc:creator>Abdisalan</dc:creator>
      <pubDate>Sun, 25 Oct 2020 01:52:05 +0000</pubDate>
      <link>https://dev.to/abdisalan_js/how-to-code-a-video-streaming-server-using-nodejs-2o0</link>
      <guid>https://dev.to/abdisalan_js/how-to-code-a-video-streaming-server-using-nodejs-2o0</guid>
      <description>&lt;p&gt;Do you want to stream video in your app without needing users to download the entire video? Here's how to do exactly that using NodeJS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Result
&lt;/h2&gt;

&lt;p&gt;Here's the end result of what we're gonna make.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu40kym1av7643egw2bgv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu40kym1av7643egw2bgv.png" alt="Video player with buffering timeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that light grey bar on the video timeline? That's the HTML5 Video Element buffering the video from our NodeJS server!&lt;/p&gt;

&lt;p&gt;If you want to git clone the code and play with it yourself, here's the link to my GitHub Repo! &lt;a href="https://github.com/Abdisalan/blog-code-examples/tree/master/http-video-stream" rel="noopener noreferrer"&gt;https://github.com/Abdisalan/blog-code-examples/tree/master/http-video-stream&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Part 1: Setup npm project
&lt;/h2&gt;

&lt;p&gt;You'll need to install NodeJS and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir http-video-stream
cd http-video-stream
npm init
npm install --save express nodemon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 2: index.html
&lt;/h2&gt;

&lt;p&gt;We need to create a HTML5 Video element, and set the source as &lt;code&gt;"/video"&lt;/code&gt;, which is where server's endpoint is.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;HTTP Video Stream&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;video&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"videoPlayer"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"650"&lt;/span&gt; &lt;span class="na"&gt;controls&lt;/span&gt; &lt;span class="na"&gt;muted=&lt;/span&gt;&lt;span class="s"&gt;"muted"&lt;/span&gt; &lt;span class="na"&gt;autoplay&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/video"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"video/mp4"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/video&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 3: index.js
&lt;/h2&gt;

&lt;p&gt;Now lets setup our node server so that on &lt;code&gt;"/"&lt;/code&gt; endpoint it serves our index.html page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Listening on port 8000!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part 4: package.json -- Run our server
&lt;/h2&gt;

&lt;p&gt;Add a &lt;code&gt;start&lt;/code&gt; script to your &lt;code&gt;package.json&lt;/code&gt; so that we can run our server using &lt;code&gt;npm start&lt;/code&gt; command.&lt;br&gt;
There's more in your &lt;code&gt;package.json&lt;/code&gt; file but I just want you to copy this start script. It uses &lt;code&gt;nodemon&lt;/code&gt; to run &lt;code&gt;index.js&lt;/code&gt; and restarts the server every time you save the &lt;code&gt;index.js&lt;/code&gt; file so you don't need to restart the server yourself!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "scripts": {
    "start": "nodemon index.js"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you should be able to run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and see our app running on port 8000. Open your browser and go to &lt;code&gt;http://localhost:8000&lt;/code&gt; to see if it worked.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 5: index.js (Again)
&lt;/h2&gt;

&lt;p&gt;We're almost there!&lt;br&gt;
For this final stage, you'll need to either find an mp4 video file, or download the one I've provided in my GitHub project link.&lt;br&gt;
&lt;a href="https://github.com/Abdisalan/blog-code-examples/tree/master/http-video-stream" rel="noopener noreferrer"&gt;https://github.com/Abdisalan/blog-code-examples/tree/master/http-video-stream&lt;/a&gt;&lt;br&gt;
Here's the &lt;code&gt;"/video"&lt;/code&gt; endpoint for our server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// in the imports above&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/video&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Ensure there is a range given for the video&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Requires Range header&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// get video stats (about 61MB)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;videoPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bigbuck.mp4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;videoSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;statSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bigbuck.mp4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Parse Range&lt;/span&gt;
  &lt;span class="c1"&gt;// Example: "bytes=32324-"&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CHUNK_SIZE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 1MB&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\D&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;CHUNK_SIZE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;videoSize&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Create headers&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contentLength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Range&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`bytes &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;videoSize&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Accept-Ranges&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bytes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Length&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;contentLength&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;video/mp4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// HTTP Status 206 for Partial Content&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;206&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// create video read stream for this particular chunk&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;videoStream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createReadStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;videoPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Stream the video chunk to the client&lt;/span&gt;
  &lt;span class="nx"&gt;videoStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The HTML5 video element makes a request to the &lt;code&gt;/video&lt;/code&gt; endpoint, and the server returns a file stream of the video, along with headers to tell which part of the video we're sending over.&lt;/p&gt;

&lt;p&gt;For a chunk size, I've decided 1MB but you could change that to whatever you like! Another great benefit of this is that we don't need to code the stream to continuously deliver the video data, the browser handles that gracefully for us.&lt;/p&gt;

&lt;p&gt;For an in-depth line by line playback on how this works, consider watching &lt;a href="https://youtu.be/ZjBLbXUuyWg" rel="noopener noreferrer"&gt;my YouTube video on this topic.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, you've got a working video streaming server using NodeJS!&lt;/p&gt;

&lt;p&gt;Happy Streaming! ✌&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>4 Ways To Traverse Binary Trees (with animations!)</title>
      <dc:creator>Abdisalan</dc:creator>
      <pubDate>Mon, 07 Sep 2020 02:41:37 +0000</pubDate>
      <link>https://dev.to/abdisalan_js/4-ways-to-traverse-binary-trees-with-animations-5bi5</link>
      <guid>https://dev.to/abdisalan_js/4-ways-to-traverse-binary-trees-with-animations-5bi5</guid>
      <description>&lt;h1&gt;
  
  
  Brush up with Tree Data Structure
&lt;/h1&gt;

&lt;p&gt;Here's a Binary Search Tree (BST). Every circle is called a node and each node can be connected to 2 other nodes -- one on the left and right. That's why they're called Binary Trees, they have 2 "child" nodes and it looks like a tree!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4t1sycs1xsvt4qqs1m57.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4t1sycs1xsvt4qqs1m57.png" alt="A Binary Tree"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The left child node is always smaller or equal in value than the parent, and the right is always greater or equal. Some implementations allow only the left or right node to be equal to the parent. Personally, I like putting equal nodes, to the left side 😁&lt;/p&gt;

&lt;p&gt;BTW, here's a Binary Search Tree using python3!&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TreeNode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The default values for the left and right tree are null/None and default val is 0.&lt;/p&gt;

&lt;h1&gt;
  
  
  Traversals
&lt;/h1&gt;

&lt;p&gt;For each traversal I'm going to give a brief description of how it moves through the binary tree, starting from the root (the top). Then show the code for traversal using python and lastly a GIF visualizing how the program moves through the tree! Also all of the gifs will end early without going through the entire tree because the gif sizes were getting too big and I had to cut it short 🤷‍♂️.&lt;/p&gt;

&lt;p&gt;The first 3 are very similar and only differ by one line of code but give very different results! I call them the traversal triplets.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Order
&lt;/h2&gt;

&lt;p&gt;This method moves through the tree "in order". Meaning that it will print every node’s value in order from smallest to greatest.&lt;/p&gt;

&lt;p&gt;Using recursion, the function will call itself on the left sub-tree, then print the current value, and then call itself on the right sub-tree.&lt;br&gt;
The result is that it prints the tree's values.... in order. &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;in_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="nf"&gt;in_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;in_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fw0z2pz1f7th1k0ut8rbr.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fw0z2pz1f7th1k0ut8rbr.gif" alt="In Order Traversal Animation"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Depth-First Search (also known as pre-order)
&lt;/h1&gt;

&lt;p&gt;Depth-First Search is the classic traversal method for trees and also graphs. This method is also known as the pre-order traversal because it first operates on the current node, then the left and right child nodes.&lt;/p&gt;

&lt;p&gt;Depth first search is very popular for general traversal as well as making copies of the tree.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dfs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;dfs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;dfs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqpsgkhgccjrjn9ybxb6l.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqpsgkhgccjrjn9ybxb6l.gif" alt="Pre Order Traversal Animation"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Post Order
&lt;/h1&gt;

&lt;p&gt;The last of the traversal triplets. It first operates on the left and right child nodes then the current node.&lt;/p&gt;

&lt;p&gt;Post Order is very useful for deleting a tree, as it goes from the bottom up.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;post_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="nf"&gt;post_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;post_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzv1x6vo9p8cqopqzod0n.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzv1x6vo9p8cqopqzod0n.gif" alt="Post Order Traversal Animation"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Breadth-First Search (also Level Order)
&lt;/h1&gt;

&lt;p&gt;This one is a little more tricky and can only be done using a  queue. It might be possible with recursion but it's easier to understand iteratively. It uses a queue when traversing so it goes through the tree as nodes are added to it. As a result, it goes through the tree, level by level. This makes breadth-first search a popular search algorithm in graphs as well.&lt;/p&gt;

&lt;p&gt;Although I couldn't make an animation for this one, I created a numbered diagram to show what order the nodes would be printed!&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# deque is a python queue library
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;deque&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bfs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;deque&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;popleft&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Feijg2o9eo8xtqk40q91d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Feijg2o9eo8xtqk40q91d.png" alt="Numbered Level Order Traversal"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;By understanding these 4 traversal methods, you can demystify most interview problems involving binary trees. A lot of them can be broken down into easily solvable chunks if you know the right traversal method to use! If you're curious about the exact methodology, I've got a guide coming out soon! I hope it'll be the only resource needed for solving binary tree problems.&lt;/p&gt;

&lt;p&gt;Also, all animations were courtesy of &lt;a href="http://btv.melezinek.cz/binary-search-tree.html" rel="noopener noreferrer"&gt;http://btv.melezinek.cz/binary-search-tree.html&lt;/a&gt;. Make sure to check them out if you want to play around with the animations! &lt;/p&gt;
&lt;h1&gt;
  
  
  By The Way I'm Making a Guide
&lt;/h1&gt;

&lt;p&gt;I'm making a guide on how to solve almost any Binary Tree problem on LeetCode (and therefore in an interview)! Join me on my journey by &lt;a href="https://twitter.com/abdisalan_js" rel="noopener noreferrer"&gt;following me on Twitter!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's a sneak peek 😃&lt;br&gt;
&lt;iframe class="tweet-embed" id="tweet-1300153885642776576-197" src="https://platform.twitter.com/embed/Tweet.html?id=1300153885642776576"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1300153885642776576-197');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1300153885642776576&amp;amp;theme=dark"
  }



&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>programming</category>
      <category>career</category>
    </item>
    <item>
      <title>Cracking the Binary Tree Interview</title>
      <dc:creator>Abdisalan</dc:creator>
      <pubDate>Sat, 29 Aug 2020 18:31:37 +0000</pubDate>
      <link>https://dev.to/abdisalan_js/cracking-the-binary-tree-interview-37pn</link>
      <guid>https://dev.to/abdisalan_js/cracking-the-binary-tree-interview-37pn</guid>
      <description>&lt;p&gt;Hi everyone!&lt;/p&gt;

&lt;p&gt;I recently finished 3 months of interviewing, and I received multiple offers! It was no walk in the park because my data-structures knowledge wasn't the best.&lt;/p&gt;

&lt;p&gt;In particular, I was terrible at solving binary tree questions. So I practiced and practiced and practiced until I became confident I could solve almost any binary tree questions on LeetCode/HackerRank.&lt;/p&gt;

&lt;p&gt;I want to prepare a guide that explains my process for solving these questions to help anyone struggling in this area or just want to refine their skills.&lt;/p&gt;

&lt;p&gt;My question is, what would you expect from a complete guide on solving Binary Tree questions? My working outline so far is as follows:&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Foundation&lt;/em&gt;&lt;br&gt;
-Tree DS: class, insertion, deletion, array-based trees&lt;br&gt;
-All Tree Traversals (recursive)&lt;br&gt;
-All Tree Traversals (iterative)&lt;br&gt;
-Tree specific Algorithms&lt;/p&gt;

&lt;p&gt;&lt;em&gt;How to Solve&lt;/em&gt;&lt;br&gt;
-How to determine the type of question and solution (my guide)&lt;br&gt;
-Common gotchas&lt;br&gt;
-20+ Question Solution Explanations&lt;/p&gt;




&lt;p&gt;Do you feel like something is missing? Please comment on any ideas you have or if you want to receive this guide when it releases! &lt;/p&gt;

&lt;p&gt;I'll be working on this over the coming weeks and releasing it in pieces over twitter and devto. If you want to follow my process and get a behind the scenes look, &lt;a href="https://twitter.com/abdisalan_js"&gt;follow me on Twitter!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@zane4004?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Zane Lee&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/fractal?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>career</category>
      <category>programming</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>How to Measure Cohort Retention using BigQuery</title>
      <dc:creator>Abdisalan</dc:creator>
      <pubDate>Fri, 28 Aug 2020 22:02:27 +0000</pubDate>
      <link>https://dev.to/popsql/how-to-measure-cohort-retention-using-bigquery-29ig</link>
      <guid>https://dev.to/popsql/how-to-measure-cohort-retention-using-bigquery-29ig</guid>
      <description>&lt;p&gt;With some simple visitor data, you can tell how you're retaining your customers on a month by month basis. &lt;strong&gt;That's super valuable!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can follow along at home. On the Google Cloud Platform, we'll use one of BigQuery's public datasets (details below). It's real visitor data from the Google Store in 2017.&lt;/p&gt;

&lt;p&gt;If you want to use your own data, the queries in this guide can be converted to work with your favorite SQL dialect. All your data needs is a timestamp of when your users visit your site and a visitor ID to track them.&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;What This Analysis Will Produce&lt;br&gt;
Cohort Retention Definition&lt;br&gt;
Cohort Retention Framework&lt;br&gt;
BigQuery Data&lt;br&gt;
SQL&lt;br&gt;
Part One: Find Our Cohorts&lt;br&gt;
Part Two: Measure Activity After Cohort Month&lt;br&gt;
Final: Divide the Number of Remaining Users by the Cohort Size&lt;br&gt;
Conclusion&lt;br&gt;
Future Use and Modifications&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What This Analysis Will Produce
&lt;/h2&gt;

&lt;p&gt;Here's a graph showing what percent of users came back to the Google Store after visiting for the first time. It's grouped by what month they first visited and shows what percent remain after subsequent months.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsqmoc6rykodqzxoxh5il.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsqmoc6rykodqzxoxh5il.png" alt="Chart showing Google Store Cohort Retention in 2017"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here are the cohort sizes, for the more detail oriented folks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbakyby5fzr83vl7f6oal.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbakyby5fzr83vl7f6oal.png" alt="Another Table showing Cohort Retention"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Cohort Retention Definition
&lt;/h1&gt;

&lt;p&gt;What's a cohort? Essentially a group of people.&lt;/p&gt;

&lt;p&gt;How are we grouping our customers? I've decided to group them by the month that they visited the site.&lt;/p&gt;

&lt;p&gt;How do we know if we retained a user? We can know if they visit the site again in a subsequent month. For example if they visited in June then again in July, they were retained. But the months are independent — They could visit in June, and not show up again until August. We wouldn't count July, but would count August.&lt;/p&gt;

&lt;h1&gt;
  
  
  Cohort Retention Framework
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Group all our users into cohorts based on the month they first came to the store and count the total.&lt;/li&gt;
&lt;li&gt;Count how many users came back each month, starting from their cohort month.&lt;/li&gt;
&lt;li&gt;Calculate the percentage of cohort remaining after each month&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  BigQuery Data
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Feel free to skip this section if you don't want to use the example data from BigQuery.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;BigQuery has a large number of public datasets and Google Store Analytics from 2017 is one of them.&lt;/p&gt;

&lt;p&gt;You'll need to make a Google Cloud Platform account, create a project, and &lt;a href="https://popsql.com/learn-sql/bigquery/accessing-bigquery-public-datasets" rel="noopener noreferrer"&gt;add the public dataset to your project.&lt;/a&gt; Next, since we can't edit the public dataset, you'll need to &lt;a href="https://cloud.google.com/bigquery/docs/copying-datasets" rel="noopener noreferrer"&gt;copy the data from the public dataset to your project.&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  SQL
&lt;/h1&gt;

&lt;p&gt;In BigQuery, I named my project "Cohort Analysis" and named my duplicate table "Google Store Analytics" so you'll see the prefix &lt;code&gt;cohort-analysis-284422.Google_Store_Analytics&lt;/code&gt; often in this article. To follow along, replace this prefix with the name of your project and table in BigQuery.&lt;/p&gt;

&lt;p&gt;For each part, I'll also be creating views to make the queries reusable and easier to work with!&lt;/p&gt;

&lt;h2&gt;
  
  
  Part One: Find Our Cohorts
&lt;/h2&gt;

&lt;p&gt;First we find out the first time each customer visited the site this year and create a view so that we can reference this query later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="nv"&gt;`cohort-analysis-284422.Google_Store_Analytics.cohort`&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt;
    &lt;span class="k"&gt;extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;timestamp_seconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;visitStartTime&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;cohort_month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;fullVisitorId&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nv"&gt;`cohort-analysis-284422.Google_Store_Analytics.ga_sessions_2017*`&lt;/span&gt;
&lt;span class="k"&gt;group&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;fullVisitorId&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Example Results:
cohort_month    fullVisitorId   
2017-05-12    0206596068278667912
2017-05-12    3310123534725675314
2017-04-25    3153380067864919818
2017-06-23    1216639212736323098
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also find out the size of each cohort by counting the number of unique ids that show up for the first time in a month.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="nv"&gt;`cohort-analysis-284422.Google_Store_Analytics.cohort_size`&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt;
    &lt;span class="k"&gt;extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;month&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cohort_month&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;cohort_month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;num_users&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nv"&gt;`cohort-analysis-284422.Google_Store_Analytics.cohort`&lt;/span&gt;
&lt;span class="k"&gt;group&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;cohort_month&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Example Results:
cohort_month    num_users   
1             52613
2             49133
3             55346
4             52873
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Part Two: Measure Activity After Cohort Month
&lt;/h2&gt;

&lt;p&gt;Next, we find what months there's been activity after their cohort month. For example If their cohort was January and they came to the site on February, then it notes activity on month one — one month after their cohort month.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="nv"&gt;`cohort-analysis-284422.Google_Store_Analytics.user_activities`&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;date_diff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;timestamp_seconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;visitStartTime&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="k"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cohort_month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;MONTH&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;month_number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;GA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fullVisitorId&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nv"&gt;`cohort-analysis-284422.Google_Store_Analytics.ga_sessions_2017*`&lt;/span&gt; &lt;span class="n"&gt;GA&lt;/span&gt;
&lt;span class="k"&gt;left&lt;/span&gt; &lt;span class="k"&gt;join&lt;/span&gt; &lt;span class="nv"&gt;`cohort-analysis-284422.Google_Store_Analytics.cohort`&lt;/span&gt; &lt;span class="k"&gt;C&lt;/span&gt;
&lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;GA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fullVisitorId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fullVisitorId&lt;/span&gt;
&lt;span class="k"&gt;group&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Example Results:
month_number    fullVisitorId
0             7868243379843705173
0             5418231530547311489
0             4704421551407457903
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we count how many users were retained in each month after their cohort month and name it retention_table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="nv"&gt;`cohort-analysis-284422.Google_Store_Analytics.retention_table`&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt;
    &lt;span class="k"&gt;extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;MONTH&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="k"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cohort_month&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;cohort_month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;month_number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;num_users&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nv"&gt;`cohort-analysis-284422.Google_Store_Analytics.user_activities`&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;
&lt;span class="k"&gt;left&lt;/span&gt; &lt;span class="k"&gt;join&lt;/span&gt; &lt;span class="nv"&gt;`cohort-analysis-284422.Google_Store_Analytics.cohort`&lt;/span&gt; &lt;span class="k"&gt;C&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fullVisitorId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fullVisitorId&lt;/span&gt;
&lt;span class="k"&gt;group&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Example Results:
cohort_month    month_number    num_users
1             0             52613
1             1             2198
1             2             908
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final: Divide the Number of Remaining Users by the Cohort Size
&lt;/h2&gt;

&lt;p&gt;Finally we get the cohort percent retention after each month.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="nv"&gt;`cohort-analysis-284422.Google_Store_Analytics.final`&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;
&lt;span class="k"&gt;select&lt;/span&gt;
  &lt;span class="n"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cohort_month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_users&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;total_users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;month_number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;CAST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_users&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_users&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;percentage&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nv"&gt;`cohort-analysis-284422.Google_Store_Analytics.retention_table`&lt;/span&gt; &lt;span class="n"&gt;R&lt;/span&gt;
&lt;span class="k"&gt;left&lt;/span&gt; &lt;span class="k"&gt;join&lt;/span&gt; &lt;span class="nv"&gt;`cohort-analysis-284422.Google_Store_Analytics.cohort_size`&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cohort_month&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cohort_month&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cohort_month&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should end up with a final result that looks like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Foctang4f78enp1dtvyzh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Foctang4f78enp1dtvyzh.png" alt="Table showing final cohort retentions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this data I also made this bar graph to show the drop off in users each month.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsqmoc6rykodqzxoxh5il.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsqmoc6rykodqzxoxh5il.png" alt="Chart showing Google Store Cohort Retention in 2017"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Again, figuring out how you're retaining your users is super valuable! You can see in this chart that the January cohort is consistently more retained than other cohorts. This could be for various reasons and knowing why could help your business capitalize on this fact.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future Use and Modifications
&lt;/h2&gt;

&lt;p&gt;Anyone who has used Google Analytics on their site knows that this cohort analysis is immediately available to them for free. But this manual method is much more flexible!&lt;/p&gt;

&lt;p&gt;Imagine that you also want to find retention numbers for customers who have paid for a product? What about customers who have used your latest feature or were referred by a friend? There are tons of insights you can get from visitor data which makes this data super powerful for guiding your business.&lt;/p&gt;

&lt;p&gt;Thank you for reading and I'll see you in the next article!&lt;/p&gt;

&lt;p&gt;✌🏾&lt;/p&gt;

</description>
      <category>sql</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>SQL Practice Problem to Help You Pass Your Interview</title>
      <dc:creator>Abdisalan</dc:creator>
      <pubDate>Fri, 21 Aug 2020 22:23:42 +0000</pubDate>
      <link>https://dev.to/abdisalan_js/sql-practice-question-newest-dog-owner-45m1</link>
      <guid>https://dev.to/abdisalan_js/sql-practice-question-newest-dog-owner-45m1</guid>
      <description>&lt;p&gt;In the 50+ programming interviews I've done, I've only been asked two SQL questions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I failed both of those questions.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwjpukjldg74ol2nuqvam.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwjpukjldg74ol2nuqvam.png" alt="Sad Pug Dog"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While I won't give the questions away, I will give you a problem to practice so that you can succeed where I failed!&lt;/p&gt;

&lt;p&gt;This question combines many principles you'll need to quickly solve SQL interview problems.&lt;/p&gt;

&lt;p&gt;Hopefully you'll be better prepared than I was 😅&lt;/p&gt;

&lt;h2&gt;
  
  
  The Dog Database
&lt;/h2&gt;

&lt;p&gt;Imagine you're running a dog shelter and you have a database of dogs and owners. Every dog has one owner, but owners can have many dogs.&lt;/p&gt;

&lt;p&gt;Here's the owner and dogs table written in PostgreSQL.&lt;/p&gt;

&lt;h3&gt;
  
  
  Owner Table
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;owners&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Dogs Table
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;dogs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;owner_id&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;owners&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;breed&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;adopted_on&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that there is a one to many relationship between the owners and dogs table. There is one owner id tied to each dog and enforced by a foreign key contraint i.e. you can only use owner ids that actually exist in the owners table.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Question
&lt;/h2&gt;

&lt;p&gt;Now, that the tables are setup, we can get to the real question.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Write an SQL query that gives the latest dog each owner adopted along with the name of the owner.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Pretty simple right?&lt;/p&gt;

&lt;p&gt;Here's some example data to help you out.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;owners&lt;/span&gt;
 &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="c1"&gt;----+--------&lt;/span&gt;
  &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;PersonA&lt;/span&gt;
  &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;PersonB&lt;/span&gt;

&lt;span class="n"&gt;dogs&lt;/span&gt;
 &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;owner_id&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="n"&gt;breed&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;adopted_on&lt;/span&gt;
&lt;span class="c1"&gt;----+----------+-----------+--------------&lt;/span&gt;
  &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;        &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;chow&lt;/span&gt; &lt;span class="n"&gt;chow&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;2019&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;03&lt;/span&gt;
  &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;        &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;dalmation&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;2019&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;03&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;07&lt;/span&gt;
  &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;        &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;beagle&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;2020&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;09&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;
  &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;        &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;pit&lt;/span&gt; &lt;span class="n"&gt;bull&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;2020&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;08&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The answer to the question should give you a result that looks like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="err"&gt;✅&lt;/span&gt; &lt;span class="k"&gt;RESULT&lt;/span&gt;
&lt;span class="n"&gt;name&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt;   &lt;span class="n"&gt;breed&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;adopted_on&lt;/span&gt;
&lt;span class="c1"&gt;----------+----------+------------&lt;/span&gt;
&lt;span class="n"&gt;PersonB&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;beagle&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;2020&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;09&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;
&lt;span class="n"&gt;PersonA&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;pit&lt;/span&gt; &lt;span class="n"&gt;bull&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;2020&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;08&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try this out for yourself first, then I'll go over the answer below. Don't worry about setting this up on your computer! Here's an SQL Fiddle (like CodePen but for SQL) for you test your answer!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://sqlfiddle.com/#!17/5059f/10" rel="noopener noreferrer"&gt;http://sqlfiddle.com/#!17/5059f/10&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Answer
&lt;/h2&gt;

&lt;p&gt;Let's go through this step by step. There's probably a few other ways of doing this but this is mine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 1: Getting the newest dogs
&lt;/h3&gt;

&lt;p&gt;First we find each newest adoption date by each owner.&lt;br&gt;
To do this, I use the max function on the &lt;code&gt;adopted_on&lt;/code&gt; column after grouping by owners. I make sure to also get the &lt;code&gt;owner_id&lt;/code&gt;, that way we can use it to join on another table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;owner_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;adopted_on&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;dogs&lt;/span&gt; &lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;owner_id&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;RESULT&lt;/span&gt;
&lt;span class="n"&gt;owner_id&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;     &lt;span class="k"&gt;max&lt;/span&gt;
&lt;span class="c1"&gt;---------+--------------&lt;/span&gt;
       &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="mi"&gt;2020&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;09&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;
       &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="mi"&gt;2020&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;08&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Part 2: Getting the breed of the newest dogs
&lt;/h3&gt;

&lt;p&gt;Next, we join the last query with the dogs table (itself) to get the breed of the dog and match by the adoption date as well as the owner.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;dogs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;breed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dogs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;adopted_on&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;dogs&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;owner_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;adopted_on&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;dogs&lt;/span&gt; &lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;owner_id&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;newest_dogs&lt;/span&gt;
&lt;span class="k"&gt;ON&lt;/span&gt;
    &lt;span class="n"&gt;dogs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;owner_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newest_dogs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;owner_id&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt;
    &lt;span class="n"&gt;dogs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;adopted_on&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newest_dogs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;max&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;RESULT&lt;/span&gt;
  &lt;span class="n"&gt;breed&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;adopted_on&lt;/span&gt; 
&lt;span class="c1"&gt;-----------+--------------&lt;/span&gt;
  &lt;span class="n"&gt;beagle&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="mi"&gt;2020&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;09&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;
  &lt;span class="n"&gt;pit&lt;/span&gt; &lt;span class="n"&gt;bull&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="mi"&gt;2020&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;08&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Final: Get the names of the owners
&lt;/h3&gt;

&lt;p&gt;Lastly, we join the result of the last query on the owners table to get their name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;owners&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dogs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;breed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dogs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;adopted_on&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;dogs&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;owner_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;adopted_on&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;dogs&lt;/span&gt; &lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;owner_id&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;newest_dogs&lt;/span&gt;
&lt;span class="k"&gt;ON&lt;/span&gt;
  &lt;span class="n"&gt;dogs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;owner_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newest_dogs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;owner_id&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt;
  &lt;span class="n"&gt;dogs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;adopted_on&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newest_dogs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;max&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt;
&lt;span class="n"&gt;owners&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;dogs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;owner_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;owners&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="err"&gt;✅&lt;/span&gt; &lt;span class="k"&gt;FINAL&lt;/span&gt; &lt;span class="k"&gt;RESULT&lt;/span&gt;
&lt;span class="n"&gt;name&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;breed&lt;/span&gt;    &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;adopted_on&lt;/span&gt;
&lt;span class="c1"&gt;----------+----------+------------&lt;/span&gt;
&lt;span class="n"&gt;PersonB&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;beagle&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;2020&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;09&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;
&lt;span class="n"&gt;PersonA&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;pit&lt;/span&gt; &lt;span class="n"&gt;bull&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;2020&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;08&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Although the question was simple, there were a few tricky queries we had to make! We needed to join tables two times and find the max aggregate on one of the tables.&lt;/p&gt;

&lt;p&gt;I hope you learned something from this exercise! If you want to experiment with my final answer, I've also included a SQL Fiddle with the final answer below.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://sqlfiddle.com/#!17/5059f/9" rel="noopener noreferrer"&gt;http://sqlfiddle.com/#!17/5059f/9&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading! If you want more content, &lt;a href="https://twitter.com/abdisalan_js" rel="noopener noreferrer"&gt;follow me on twitter!&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;&lt;span&gt;Cover Photo by &lt;a href="https://unsplash.com/@berkaygumustekin?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Berkay Gumustekin&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/puppy?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/span&gt;&lt;/center&gt;

&lt;p&gt;✌️&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>sql</category>
    </item>
    <item>
      <title>1 SQL Query You Should Stop Using</title>
      <dc:creator>Abdisalan</dc:creator>
      <pubDate>Tue, 16 Jun 2020 16:04:21 +0000</pubDate>
      <link>https://dev.to/abdisalan_js/1-sql-query-you-should-stop-using-1e5k</link>
      <guid>https://dev.to/abdisalan_js/1-sql-query-you-should-stop-using-1e5k</guid>
      <description>&lt;p&gt;Let's talk about pages. You know, like this&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c-Wg5moK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/l6suie8c0v02edmszv4y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c-Wg5moK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/l6suie8c0v02edmszv4y.png" alt="Google Search Result pages" width="684" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;or infinite scrolling pages like this&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WyLlM_tO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ihmvynigr6fax2ff1189.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WyLlM_tO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ihmvynigr6fax2ff1189.gif" alt="Dev.to infinite scrolling" width="346" height="572"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because we never want to give our website visitors all of our data, we present them in pages and let users load more as they please.&lt;/p&gt;

&lt;p&gt;One method of paging, AKA pagination, in SQL that's easy is to limit a query to a certain number and when you want the next page, set an offset.&lt;/p&gt;

&lt;p&gt;For example, here's a query for the second page of a blog&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * from posts
ORDER BY created_at
LIMIT 10
OFFSET 10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, for larger databases, this is not a good solution.&lt;/p&gt;

&lt;p&gt;To demonstrate, I created a database and filled it 2,000,000 tweets. Well, not real tweets but just rows of data.&lt;/p&gt;

&lt;p&gt;The database is on my laptop and is only 500mb in size so don't worry too much about the specific numbers in my results but what they represent.&lt;/p&gt;

&lt;p&gt;First, I'm going to explain why using offset for pagination is not a good idea, and then present a few better ways of doing pagination.&lt;/p&gt;

&lt;h3&gt;
  
  
  Offset Pagination
&lt;/h3&gt;

&lt;p&gt;Here's a graph showing how much time it takes to get each page. Notice that as the page number grows, the time needed to get that page increases linearly as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3cLzmJ7W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bdeltz9i930llxj9zu6x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3cLzmJ7W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bdeltz9i930llxj9zu6x.png" alt="Graph of query time increasing linearly" width="600" height="371"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Results:
200,000 rows returned
~17.7s
~11,300 rows per second
** unable to paginate all 2 million rows under 5 minutes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is because the way offsets works are by counting how many rows it should skip then giving your result. In other words, to get the results from rows 1,000 to 1,100 it needs to scan through the first 1,000 and then throw them away. Doesn't that seem a bit wasteful?&lt;/p&gt;

&lt;p&gt;And that's not the only reason why offset is bad. What if in the middle of paging, another row is added or removed? Because the offset counts the rows manually for each page, it could under count because of the deleted row or over count because of a new row. Querying through offset will result in duplicate or missing results if your data is ever-changing.&lt;/p&gt;

&lt;p&gt;There are better ways to paginate though! Here's one&lt;/p&gt;

&lt;h3&gt;
  
  
  Order Based Pagination
&lt;/h3&gt;

&lt;p&gt;You can page on pretty much anything you can order your data by.&lt;/p&gt;

&lt;p&gt;For example, If you have an increasing id you can use it as a cursor to keep track of what page you were on. First, you get your results, then use the id of the last result to find the next page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM tweet
WHERE id &amp;lt;= $last_id
ORDER BY id DESC
LIMIT 100

2,000,000 rows returned
~4.2s
~476,000 rows per second
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method is not only much faster but is also resilient to changing data! It doesn't matter if you deleted a row or added a new one since the pagination starts right where it left off.&lt;/p&gt;

&lt;p&gt;Here's another graph showing the time it takes to page through 2 million rows of data, 100 rows at a time. Notice that it stays consistent!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5ClhH_L2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/73clnw87dd8rfgtxtm4k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5ClhH_L2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/73clnw87dd8rfgtxtm4k.png" alt="Graph of query time staying constant" width="600" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The trade-off is that it cannot go to an arbitrary page, because we need the id to find the page. This is is a great trade-off for infinite scrolling websites like Reddit and Twitter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Time Pagination
&lt;/h3&gt;

&lt;p&gt;Here's a more practical example of pagination based on the &lt;code&gt;created_at&lt;/code&gt; field.&lt;/p&gt;

&lt;p&gt;It has the same advantages and one drawback as ID pagination. However, you will need to add an index for &lt;code&gt;(created_at, id)&lt;/code&gt; for optimal performance. I included id as well to break the tie on tweets created at the same time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE INDEX on tweet (created_at, id)

SELECT * from tweet
WHERE (created_at, id) &amp;lt;= ($prev_create_at, $prev_id)
ORDER BY created_at DESC, id DESC
LIMIT 100

2,000,000 rows returned
~4.70s
~425,000 rows per second
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Should you really stop using &lt;code&gt;OFFSET&lt;/code&gt; in your SQL queries? Probably.&lt;/p&gt;

&lt;p&gt;Practically, however, you could be completely fine with slightly slower results since users won't be blazing through your pages. It all depends on your system and what trade-offs you're willing to make to get the job done.&lt;/p&gt;

&lt;p&gt;I think offset has its place but not as a tool for pagination. It is much slower and less memory efficient than its easy alternatives. Thanks for reading!&lt;/p&gt;

&lt;p&gt;✌🏾&lt;/p&gt;

</description>
      <category>sql</category>
      <category>database</category>
      <category>performance</category>
    </item>
    <item>
      <title>How I get into “The Zone”</title>
      <dc:creator>Abdisalan</dc:creator>
      <pubDate>Sun, 08 Mar 2020 16:15:26 +0000</pubDate>
      <link>https://dev.to/abdisalan_js/how-i-get-into-the-zone-4g43</link>
      <guid>https://dev.to/abdisalan_js/how-i-get-into-the-zone-4g43</guid>
      <description>&lt;p&gt;&lt;a href="https://unsplash.com/@shootbyteo?utm_medium=referral&amp;amp;utm_campaign=photographer-credit"&gt;Photo by Matteo Di Iorio  on Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For those who don’t know, "the zone" refers to a mental state where one’s focus is solely on their craft and they can produce some of their best work.&lt;/p&gt;

&lt;p&gt;The way I get into the zone is pretty simple, so I thought I’d share.&lt;/p&gt;

&lt;h3&gt;
  
  
  The right setting ⏰
&lt;/h3&gt;

&lt;p&gt;After I’ve arrived at work and had my daily standup meeting with the team, I usually don’t have any meetings scheduled for a couple hours. Perfect time to get in the zone!&lt;/p&gt;

&lt;h3&gt;
  
  
  Caffeine ☕️ (usually but optional)
&lt;/h3&gt;

&lt;p&gt;I get a cup of coffee and start sipping as I go through my email, after about 15 minutes I'm finally awake for the first time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Meditation 🧘🏾‍♂️ (critical!)
&lt;/h3&gt;

&lt;p&gt;This is necessary for me because at the start of the day, I'm a little stressed about what needs to be done and in general have too much going on in my head.&lt;/p&gt;

&lt;p&gt;It helps me to write one or two tasks I intend to accomplish that morning and then meditate to clear my mind of everything.&lt;/p&gt;

&lt;p&gt;I put on headphones and listen to a guided meditation on &lt;a href="https://www.headspace.com"&gt;headspace.&lt;/a&gt; I need a minimum of 10-15 minutes before my body is relaxed, and my mind has calmed down.&lt;/p&gt;

&lt;p&gt;Once all that's done, I'm instantly in the zone. My to-do list is in front of me and I burst into action!&lt;/p&gt;

&lt;p&gt;What's your morning routine like? How do you get in the zone?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>productivity</category>
    </item>
    <item>
      <title>3 Tips If You're Afraid To Start A Project from Scratch</title>
      <dc:creator>Abdisalan</dc:creator>
      <pubDate>Fri, 28 Feb 2020 05:09:47 +0000</pubDate>
      <link>https://dev.to/abdisalan_js/3-tips-if-you-re-afraid-to-start-a-project-from-scratch-24bb</link>
      <guid>https://dev.to/abdisalan_js/3-tips-if-you-re-afraid-to-start-a-project-from-scratch-24bb</guid>
      <description>&lt;p&gt;&lt;a href="https://i.giphy.com/media/GcSqyYa2aF8dy/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/GcSqyYa2aF8dy/giphy.gif" alt="https://media.giphy.com/media/GcSqyYa2aF8dy/giphy.gif" width="268" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ✨ You Can Do This! I Believe In You! ✨
&lt;/h2&gt;

&lt;p&gt;Some words of encouragement before you start your big formidable coding project.&lt;/p&gt;

&lt;p&gt;Starting is the absolutely the hardest part, but it can take as little as making the git repo, or writing the bare minimum to get something running even if its &lt;code&gt;&amp;lt;html&amp;gt;&amp;lt;/html&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Share what you want to work on so that your friends can hold you accountable. It works even better if you both start a project and encourage each other to keep going!&lt;/p&gt;

&lt;h2&gt;
  
  
  No Bug Is Unsolvable
&lt;/h2&gt;

&lt;p&gt;Personally, this has discouraged me a lot.&lt;/p&gt;

&lt;p&gt;One thing that really frustrated me when I was starting out was that I was afraid I would run into a bug in my code or it wouldn't compile and no one could help me fix it.&lt;/p&gt;

&lt;p&gt;And sometimes it did happen. Entire projects I've poured hours and hours into that just fall to the way side because of that one bug that ruined the whole project.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;My biggest mistake was not reaching out. There are so many resources for people to check over your code, you're just going to have to be willing to share.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ask the internet, and you shall receive. Sometimes more than you want, but you'll likely get an answer if you post your issue online.&lt;/p&gt;

&lt;p&gt;Ask on StackOverflow, even though it can be intimidating but you'll have to push through it!&lt;/p&gt;

&lt;p&gt;Heck, ask me! Go to my twitter &lt;a href="https://twitter.com/abdisalan_js"&gt;@abdisalan_js&lt;/a&gt; and send me a DM of your bug and maybe I'll be able to help!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1vlQhJTv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yxy45i2jn5tnbd51ixrm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1vlQhJTv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yxy45i2jn5tnbd51ixrm.jpg" alt="Jack of all trades" width="880" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pick One Area and Get Good; Ignore the Other Fluff
&lt;/h2&gt;

&lt;p&gt;When I got started, I tried to master the entire profession. I did courses on C++ game development, Javascript, Python, 3d engine building, web development, php and more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I don't remember 99% of it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There's no strict areas or category, but sticking to one programming language vs many is a good start. If you've got some experience and are comfortable with one language, you could expand to a different language that works with it. For example, if you learned javascript for web development, it could help to learn python for making web APIs.&lt;/p&gt;

&lt;p&gt;The moral is to keep the vision narrow for now so that you can get better &lt;em&gt;faster&lt;/em&gt; and build on your confidence.&lt;/p&gt;

&lt;p&gt;Its also good for job search, which you'll eventually have to do. When employers look at your CV, they'll want to put you in a category, and you want to be strong in one category &lt;em&gt;at least&lt;/em&gt;. That's a discussion for another time though.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: Try to collaborate!
&lt;/h2&gt;

&lt;p&gt;Don't try to do this all on your own! Find someone, anyone, who might want to work on the project with you. Having someone else there can be a big motivator and you can get a lot more done.&lt;/p&gt;

&lt;p&gt;If you're both familiar with git, then this could be a good time to try sharing a repo and reviewing each others' code.&lt;/p&gt;

&lt;p&gt;Comment down below what project you're working on! Maybe someone else will be interested and make a pull request?&lt;/p&gt;

&lt;p&gt;Thanks for reading and I hope this helped you start that project you've been thinking of!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>learning</category>
      <category>tips</category>
      <category>career</category>
    </item>
    <item>
      <title>1 Weird CSS Property You Should Use In Your Next Project</title>
      <dc:creator>Abdisalan</dc:creator>
      <pubDate>Fri, 21 Feb 2020 05:38:19 +0000</pubDate>
      <link>https://dev.to/abdisalan_js/1-weird-css-property-you-should-use-in-your-next-project-37hl</link>
      <guid>https://dev.to/abdisalan_js/1-weird-css-property-you-should-use-in-your-next-project-37hl</guid>
      <description>

&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://abdisalan.com/posts/one-css-property-you-should-use-in-your-next-project"&gt;my blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;First, we need to familiarize you with the CSS Box Model.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Skip to the quiz in the next section if you already know the box model&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  CSS Box Model
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oWyigWR0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k21baf91v8mbwo18vj61.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oWyigWR0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k21baf91v8mbwo18vj61.png" alt="Content Box Model" width="516" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The box model describes the basic structure of one html element. Note that this is not to scale, so the pixels do not match up in the image! &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The blue dotted box is the &lt;code&gt;width x height&lt;/code&gt; of the content in the html element&lt;/li&gt;
&lt;li&gt;Purple space is padding in the html element that surrounds the content with empty space&lt;/li&gt;
&lt;li&gt;Border is the line around the html element. Used to set a border around the element.&lt;/li&gt;
&lt;li&gt;Margin is like padding (empty space) but goes outside the border — determines space between elements.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Understand? Good you're ready for the quiz&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick CSS Quiz
&lt;/h2&gt;

&lt;p&gt;Imagine that a you have a div with a width of &lt;code&gt;50px&lt;/code&gt;, height of &lt;code&gt;5px&lt;/code&gt;, a &lt;code&gt;1px&lt;/code&gt; border, and &lt;code&gt;10px&lt;/code&gt; of padding all around it.&lt;/p&gt;

&lt;p&gt;What is the &lt;em&gt;total&lt;/em&gt; width of this div, including the border and padding?&lt;/p&gt;

&lt;p&gt;⏳&lt;/p&gt;

&lt;p&gt;⏳&lt;/p&gt;

&lt;p&gt;⏳&lt;/p&gt;

&lt;p&gt;⏳&lt;/p&gt;

&lt;p&gt;⏳&lt;/p&gt;

&lt;p&gt;⏳&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Answer: 72px&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To get that answer you had to start with the width of &lt;code&gt;50px&lt;/code&gt; add the left-side and right-side of the border for &lt;code&gt;2px&lt;/code&gt; and lastly add the left-side and right-side padding for &lt;code&gt;20px&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZOC_FH6M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/940win7orfepkkl5ck9j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZOC_FH6M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/940win7orfepkkl5ck9j.png" alt="content-box-model-edited" width="516" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  But it doesn't have to be this way!
&lt;/h2&gt;

&lt;p&gt;Why did we need to make all these calculations to measure a simple width of a div? Why can't the css width actually refer to the &lt;em&gt;width&lt;/em&gt; of the div?&lt;/p&gt;

&lt;p&gt;Well there is another box-model we can use!&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing: &lt;code&gt;box-sizing&lt;/code&gt; css property
&lt;/h2&gt;

&lt;p&gt;First, I'll go over the default value for &lt;code&gt;box-sizing&lt;/code&gt;, which is &lt;code&gt;content-box&lt;/code&gt;. Then I'll go over the alternative setting, &lt;code&gt;border-box&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;In short, with &lt;code&gt;content-box&lt;/code&gt; the width and height properties in css refer to the width and height of the html &lt;em&gt;content&lt;/em&gt;, not including padding and border.&lt;br&gt;
With &lt;code&gt;border-box&lt;/code&gt; the width and height properties refer to the total width and height of the html, which includes the padding and border. &lt;/p&gt;
&lt;h2&gt;
  
  
  content-box (default)
&lt;/h2&gt;

&lt;p&gt;If &lt;code&gt;box-sizing: content-box&lt;/code&gt; property is set, the width and height property &lt;strong&gt;&lt;em&gt;only&lt;/em&gt;&lt;/strong&gt; applies to the content section. The resulting width of the entire html element is &lt;code&gt;72px&lt;/code&gt;, including the extra &lt;code&gt;20px&lt;/code&gt; from padding and &lt;code&gt;2px&lt;/code&gt; from the border. And the resulting height is &lt;code&gt;5px&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y9AVS8E6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gaz0zvp61hctz1dyakfz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y9AVS8E6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gaz0zvp61hctz1dyakfz.png" alt="content-box-css-model" width="516" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mnr4soFo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/19jkx6oeu1jvgh28xqkq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mnr4soFo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/19jkx6oeu1jvgh28xqkq.png" alt="box-model-content-box" width="880" height="611"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  ✨border-box ✨
&lt;/h2&gt;

&lt;p&gt;If &lt;code&gt;box-sizing: border-box&lt;/code&gt; property is set, the width and height property is applied to the &lt;strong&gt;&lt;em&gt;entire&lt;/em&gt;&lt;/strong&gt; element. The content section is calculated after including the padding and border so the width of the entire child element is &lt;code&gt;50px&lt;/code&gt; with a content width &lt;code&gt;28px&lt;/code&gt;, padding of &lt;code&gt;20px&lt;/code&gt; and &lt;code&gt;2px&lt;/code&gt; of border. The height of the content is now calculated to be &lt;code&gt;0&lt;/code&gt; because the &lt;code&gt;10px&lt;/code&gt; padding on top and bottom satisfy the &lt;code&gt;5px&lt;/code&gt; height requirement.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kF-w6DhD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0b6k5nf1i4jxnz5m2rod.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kF-w6DhD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0b6k5nf1i4jxnz5m2rod.png" alt="border-box-css-model" width="512" height="248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rpiTrda3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ns0v86u71q07xqibnv1q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rpiTrda3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ns0v86u71q07xqibnv1q.png" alt="box-model-border-box" width="880" height="606"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Playable CodePen
&lt;/h2&gt;

&lt;p&gt;I made demo in CodePen! Feel free to open up the inspector and see the changing width.&lt;/p&gt;

&lt;p&gt;When the box-sizing property is set to content-box, the width is &lt;code&gt;72px&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When the box-sizing property is set to border-box, the width is &lt;code&gt;50px&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codepen.io/abdisalan/full/NWqNYgJ"&gt;https://codepen.io/abdisalan/full/NWqNYgJ&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  History
&lt;/h2&gt;

&lt;p&gt;Of course you can't talk about the history of the web without mentioning Internet Explorer.&lt;/p&gt;

&lt;p&gt;The border-box model, where the width and height include the padding + border, was used and popularized by Internet Explorer. In contrast, the world wide web consortium (W3C) have decided that the content-box model is the standard and is currently used and the default for most modern browsers.&lt;/p&gt;
&lt;h2&gt;
  
  
  Which do you prefer?
&lt;/h2&gt;

&lt;p&gt;I personally prefer &lt;code&gt;border-box&lt;/code&gt;, but they each have their pros and cons. Tell me which one you prefer &lt;a href="https://twitter.com/abdisalan_js"&gt;on twitter!&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;border-box&lt;/code&gt; — You don't have to think about adding padding or border, they do the calculation for you and it's supported by older browsers.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;content-box&lt;/code&gt; — Default behavior in most browsers. Lets you dictate the size of the content so it might be easier to fit other elements within.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to include border-box in your next project, you can use this handy CSS rule to apply it to all your elements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hope you enjoyed this post and you start using &lt;code&gt;border-box&lt;/code&gt; in all your projects!&lt;/p&gt;

&lt;p&gt;✌️&lt;/p&gt;

</description>
      <category>css</category>
    </item>
  </channel>
</rss>
