<?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: Functional Javascript</title>
    <description>The latest articles on DEV Community by Functional Javascript (@functional_js).</description>
    <link>https://dev.to/functional_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%2F125381%2Fb56086eb-3a41-4435-93f3-64c68a5489c0.jpg</url>
      <title>DEV Community: Functional Javascript</title>
      <link>https://dev.to/functional_js</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/functional_js"/>
    <language>en</language>
    <item>
      <title>MongoDB - Slicing &amp; Dicing - Get Daily Activity - Series #15</title>
      <dc:creator>Functional Javascript</dc:creator>
      <pubDate>Fri, 19 Feb 2021 04:59:50 +0000</pubDate>
      <link>https://dev.to/functional_js/mongodb-slicing-and-dicing-query-daily-activity-series-15-45i8</link>
      <guid>https://dev.to/functional_js/mongodb-slicing-and-dicing-query-daily-activity-series-15-45i8</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;We can easily perform data analysis on our data by slicing our data into buckets based on dates.&lt;/p&gt;

&lt;p&gt;This query retrieves a report on how many "likes" per day were performed by users over the last 30 days.&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="nx"&gt;mgArr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nlpdb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;collEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users_actions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;matchExact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;actionCateg&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;fav&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;matchExact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;isFav&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;$group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="na"&gt;month&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$month&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="na"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$dayOfMonth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$_id&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="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$sum&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="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="nx"&gt;lastInserted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&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 Output:&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="cm"&gt;/*
[
  { _id: { year: 2021, month: 2, day: 18 }, count: 123 },
  { _id: { year: 2021, month: 2, day: 17 }, count: 2214 },
  { _id: { year: 2021, month: 2, day: 15 }, count: 369 },
  { _id: { year: 2021, month: 2, day: 14 }, count: 1353 },
  { _id: { year: 2021, month: 2, day: 12 }, count: 492 },
  { _id: { year: 2021, month: 2, day: 11 }, count: 1230 },
  { _id: { year: 2021, month: 2, day: 10 }, count: 1476 },
  { _id: { year: 2021, month: 2, day: 9 }, count: 4305 },
  { _id: { year: 2021, month: 2, day: 8 }, count: 1722 },
  { _id: { year: 2021, month: 2, day: 6 }, count: 984 },
  { _id: { year: 2021, month: 2, day: 5 }, count: 2706 },
  { _id: { year: 2021, month: 2, day: 4 }, count: 861 },
  { _id: { year: 2021, month: 2, day: 3 }, count: 369 },
  { _id: { year: 2021, month: 2, day: 2 }, count: 2829 },
  { _id: { year: 2021, month: 2, day: 1 }, count: 1230 },
  { _id: { year: 2021, month: 1, day: 29 }, count: 615 },
  { _id: { year: 2021, month: 1, day: 28 }, count: 3444 },
  { _id: { year: 2021, month: 1, day: 27 }, count: 369 },
  { _id: { year: 2021, month: 1, day: 26 }, count: 2706 },
  { _id: { year: 2021, month: 1, day: 25 }, count: 123 },
  { _id: { year: 2021, month: 1, day: 24 }, count: 1599 },
  { _id: { year: 2021, month: 1, day: 23 }, count: 246 },
  { _id: { year: 2021, month: 1, day: 22 }, count: 3567 },
  { _id: { year: 2021, month: 1, day: 21 }, count: 1353 },
  { _id: { year: 2021, month: 1, day: 20 }, count: 1722 },
  { _id: { year: 2021, month: 1, day: 19 }, count: 3813 },
  { _id: { year: 2021, month: 1, day: 18 }, count: 2091 },
  { _id: { year: 2021, month: 1, day: 17 }, count: 3321 },
  { _id: { year: 2021, month: 1, day: 16 }, count: 123 },
  { _id: { year: 2021, month: 1, day: 14 }, count: 246 }
]
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;p&gt;The query is using the MongoDB Aggregation Framework.&lt;/p&gt;

&lt;p&gt;The query pipeline is just an array of query stages.&lt;/p&gt;

&lt;p&gt;The stages are query syntax that is in a JavaScript object format.&lt;/p&gt;

&lt;p&gt;So each stage is a JS object that describes that portion of the query that's being composed.&lt;/p&gt;

&lt;p&gt;Thus we compose a query together by adding stages.&lt;/p&gt;

&lt;p&gt;As an analogy to SQL syntax, you can think of stages as SQL clauses like the SELECT clause, the WHERE clause, or the GROUP BY clause.&lt;/p&gt;

&lt;p&gt;The matchExact stage is my wrapper func, which returns the raw stage object syntax.&lt;br&gt;
The raw syntax would look like....&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="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;$match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;actionCateg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fav&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;isFav&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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 $group stage has an _id key. This DOES NOT represent the Primary Key (PK) of the Collection. It represents the uniquely grouped item in the grouping. In this case it's the combination of "year, month and day" that represents the unique record being summed.&lt;/p&gt;

&lt;p&gt;The "$_id" value actually represents the PK of the Collection. As you remember from the last article, the PK contains the timestamp information. The $year operator (think of these Mongodb operators as built-in utility functions) extracts the year part of the timestamp which is stored in the "$_id" (PK).&lt;/p&gt;

&lt;p&gt;In the last stage (lastInserted, my utility func) we retrieve the last 30 days.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;More magic with MongoDB coming up in future series articles.&lt;/p&gt;

&lt;p&gt;As always, if you have an questions or input, let me know.&lt;/p&gt;

</description>
      <category>database</category>
      <category>mongodb</category>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>MongoDB Marvels - Slicing Data by Dates - Series #14</title>
      <dc:creator>Functional Javascript</dc:creator>
      <pubDate>Wed, 17 Feb 2021 23:24:13 +0000</pubDate>
      <link>https://dev.to/functional_js/mongodb-marvels-slicing-data-by-dates-series-14-hc4</link>
      <guid>https://dev.to/functional_js/mongodb-marvels-slicing-data-by-dates-series-14-hc4</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Let's look at a simple query first as we prep ourselves for more thorough queries in this Series:&lt;/p&gt;

&lt;p&gt;Query for how many user actions per hour block.&lt;br&gt;
This will report which hour blocks the site is busiest.&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="nx"&gt;mgArr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nlpdb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;collEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users_actions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;$addFields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;hourUtc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;$hour&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$_id&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="na"&gt;hourPst&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;$hour&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-08:00&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="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;groupByKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hourPst&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;sortDesc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;count&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;
  
  
  Notes
&lt;/h2&gt;

&lt;p&gt;The server timestamp is in UTC Time (Coordinated Universal Time).&lt;/p&gt;

&lt;p&gt;The db query code also converts the timezone from UTC to PST.&lt;br&gt;
(In another post we'll extract the user's timezone from their device.)&lt;/p&gt;

&lt;p&gt;The query has 3 stages:&lt;/p&gt;

&lt;p&gt;The $addFields stage adds two computed fields to our resultset, "hourUtc" and "hourPst". (Just to show an example of how to get dates without and with an offset)&lt;/p&gt;

&lt;p&gt;The Group stage will pivot on the hour component of the date, for the PST timezone.&lt;/p&gt;

&lt;p&gt;Sort Descending, so we see the busiest hours at the top.&lt;/p&gt;

&lt;p&gt;We will get back 24 records (24 hours in each day), so we don't need to Paginate.&lt;/p&gt;

&lt;p&gt;The output:&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="cm"&gt;/*
 { count: 610, hourPst: 15 },
  { count: 58, hourPst: 20 },
  { count: 55, hourPst: 21 },
  { count: 51, hourPst: 23 },
  { count: 49, hourPst: 14 },
  { count: 41, hourPst: 10 },
  { count: 38, hourPst: 13 },
  { count: 34, hourPst: 22 },
  { count: 33, hourPst: 18 },
  { count: 32, hourPst: 16 },
  { count: 27, hourPst: 17 },
  { count: 24, hourPst: 11 },
  { count: 23, hourPst: 0 },
  { count: 17, hourPst: 19 },
  { count: 17, hourPst: 1 },
  { count: 15, hourPst: 12 },
  { count: 9, hourPst: 3 },
  { count: 5, hourPst: 2 },
  { count: 5, hourPst: 8 },
  { count: 3, hourPst: 6 }
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;p&gt;Looks like 3:00:00 to 3:59:59 PM is very busy for some reason. :)&lt;/p&gt;

&lt;p&gt;Though this is an example query, you can see how you can get meaningful and sometimes surprising insights into your data by carving it up into timeseries dimensions.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;We'll cover more power with dates and time series in this Series of Articles.&lt;/p&gt;

&lt;p&gt;As always, if you have an questions or input, let me know.&lt;/p&gt;

</description>
      <category>database</category>
      <category>mongodb</category>
      <category>javascript</category>
      <category>node</category>
    </item>
    <item>
      <title>MongoDB Marvels - Data Between Dates - Series #13</title>
      <dc:creator>Functional Javascript</dc:creator>
      <pubDate>Tue, 16 Feb 2021 18:43:32 +0000</pubDate>
      <link>https://dev.to/functional_js/mongodb-marvels-data-between-dates-series-13-5gcc</link>
      <guid>https://dev.to/functional_js/mongodb-marvels-data-between-dates-series-13-5gcc</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Let's look at a MongoDB query that uses the Mongo Aggregation Framework (AF) that retrieves a resultset of docs between two points in time.&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="nx"&gt;mgArr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nlpdb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;collEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users_actions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$addFields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$toDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$_id&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="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;$match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;$gte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2021-02-01T00:00:00.000Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="na"&gt;$lt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2021-02-15T00:00:00.000Z&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="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$sort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ts&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="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$skip&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&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;
  
  
  Notes
&lt;/h2&gt;

&lt;p&gt;There are 5 stages here.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;extract the timestamp from the _id field (PK), as a new field called "ts" (timestamp)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;filter (match) by dates that are greater than the earliest date and less than the latest date&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;sort by the earliest date (the 1 means ascending; a -1 would mean descending)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;let's add pagination, which requires two stages, $skip and $limit. $skip: 0 mean get the first page of results without skiping to the next page&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;limit the resultset to the first 100 results, as page 1 (no skip)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These 5 stages are the raw AF (Aggregation Framework) syntaxes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Version 2 - using functional wrappers
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;mgArr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nlpdb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;collEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users_actions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;addField_ts&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nx"&gt;matchBetweenDates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2021-02-01&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;2021-02-04&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;sortAsc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;paginate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&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="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;p&gt;We've made the code more terse and increased its readability by abstracting away the tedious and repetitious curl braces. Now it looks more functional, since it's just one function call after another, passing in our argument that are particular to this queries use case.&lt;/p&gt;

&lt;p&gt;Notice the naming convention for the addField_ts func. The underscore indicates a namespacing. I use namespacing to clearly specify a category of funcs. I have a number of "addField" funcs that add fields to a resultset for particular common use cases. Adding a new timestamp field is just one common use case.&lt;/p&gt;

&lt;p&gt;Notice it appears we have 4 stages now instead of 5. The paginate func composes two stages, $skip and $limit to give us a simpler pagination behavior. The paginate func returns the $skip and $limit, so technically there are still 5 stages sent to MongoDB as a raw query.&lt;/p&gt;

&lt;p&gt;I made the matchBetweenDates func to be inclusive of the start and end date.&lt;br&gt;
Here is the source code:&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="cm"&gt;/**
@func
get docs between two dates
inclusive of days

@param {string} start - the earliest day to include
@param {string} end - the latest day to include
@return {object}
*/&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;matchBetweenDates&lt;/span&gt; &lt;span class="o"&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="o"&gt;=&amp;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="na"&gt;$match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;$gte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;T00:00:00.000Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;$lte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;end&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;T23:59:59.000Z&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="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;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;We'll be covering more advanced usages of partitioning your data on date dimensions, to allow you better insights into your data, and make better predictions about the future.&lt;/p&gt;

&lt;p&gt;As always, if you have any questions on this let me know.&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>javascript</category>
      <category>database</category>
      <category>express</category>
    </item>
    <item>
      <title>MongoDB Marvels - Dancing with Dates - Series #12</title>
      <dc:creator>Functional Javascript</dc:creator>
      <pubDate>Mon, 15 Feb 2021 19:47:46 +0000</pubDate>
      <link>https://dev.to/functional_js/mongodb-marvels-dancing-with-dates-series-12-110h</link>
      <guid>https://dev.to/functional_js/mongodb-marvels-dancing-with-dates-series-12-110h</guid>
      <description>&lt;p&gt;MongoDB Marvels - Dancing with Dates - Series #12&lt;/p&gt;

&lt;h1&gt;
  
  
  MongoDB - Working with dates
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;If you insert a doc with no explicit PK (primary key) — which is by default a field with a _id key — Mongo will insert an autogenerated value for you.&lt;/p&gt;

&lt;p&gt;One useful feature is that embedded in that PK is the ISODate.&lt;/p&gt;

&lt;p&gt;We can extract it like this:&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="nx"&gt;mgArr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nlpdb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;collEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users_actions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$addFields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$toDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$_id&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;lastInserted&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="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;We get this output:&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="cm"&gt;/*
@output

{
    _id: 60245842f36c37895594ebb0,
    actionCateg: 'fav',
    hw_id: 'distrail__01',
    user_id: '6024574e948c3b4a8cb99d2e',
    hw: 'distrail',
    isFav: true,
    ts: 2021-02-10T22:03:46.000Z
  }
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;p&gt;Let me read in natural English what the query is doing:&lt;/p&gt;

&lt;p&gt;Return an array from the mongo collection,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;but in the first stage of the pipeline, shape the resultset by adding a new field to it called ts (meaning timestamp, which will represent the original insert date of the record).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the value of the new ts field will be retrieved from the _id field (the PK field).&lt;br&gt;
Notice two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;we use the mongo $toDate operator as a utility function that extracts the date from the _id field.
Note the interesting syntax, which is when we want to reference a field key from the value side ({$MONGO_OPERATOR: VALUESIDE}), we prefix the key name with the dollar sign sigil. Since it's on the value side, it must be a string, so it's wrapped in quotes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So to summarize, we added a field to our result set, whose key is "ts" and whose value is the extracted date from the _id field.&lt;/p&gt;

&lt;p&gt;The output resultset has a new field called ts that is not in the document in the db collection. It was calculated on the fly.&lt;/p&gt;

&lt;p&gt;This is a short example, but I wanted to explain it fully.&lt;/p&gt;

&lt;p&gt;Not related to "dates" — but just to explain — the second stage (and last stage) is my lastInserted utility func which simply retrieves the last inserted doc from the collection.&lt;br&gt;
Here's the source code for it if you're interested:&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="cm"&gt;/*
@param {number} lim - the count of the most recent inserted docs we want
@return {object[]} - an arr of two stages
*/&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lastInserted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lim&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;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;sortDesc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lim&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;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;As the Series continues we'll cover more interesting queries with dates.&lt;/p&gt;

&lt;p&gt;For example, We can select sets of docs between dates, like monthly, weekly, daily, or hourly.&lt;/p&gt;

&lt;p&gt;We can even create dimensions of time-series reports.&lt;/p&gt;

&lt;p&gt;The limit is your imagination. :)&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>database</category>
      <category>javascript</category>
      <category>express</category>
    </item>
    <item>
      <title>Delightful Database Design - Mastering MongoDB Queries - Series #11</title>
      <dc:creator>Functional Javascript</dc:creator>
      <pubDate>Fri, 12 Feb 2021 16:40:43 +0000</pubDate>
      <link>https://dev.to/functional_js/delightful-database-design-mastering-mongodb-queries-series-11b-351d</link>
      <guid>https://dev.to/functional_js/delightful-database-design-mastering-mongodb-queries-series-11b-351d</guid>
      <description>&lt;h3&gt;
  
  
  Legend
&lt;/h3&gt;

&lt;p&gt;AF = Aggregation Framework&lt;/p&gt;

&lt;h1&gt;
  
  
  Intro
&lt;/h1&gt;

&lt;p&gt;We've covered a lot of powerful features of shaping data that we retrieve from the database, but we've also barely scratched the surface.&lt;/p&gt;

&lt;p&gt;Other powerful data manipulation actions we can do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;joins (using the $lookup operator)&lt;/li&gt;
&lt;li&gt;writing results to new collections (using the $out operator)&lt;/li&gt;
&lt;li&gt;performing unions on dataset (using the $unionAll operator)&lt;/li&gt;
&lt;li&gt;merging datasets (using the $merge operator)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are all "stage operators". They are stages of our aggregation pipeline, which is our full query, and is represented as an arr of stages. Each stage is a single atomic unit of our database query.&lt;/p&gt;

&lt;p&gt;Here is some pseudocode to understand the structure of composing the database query:&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;aggregationPipeline&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="nx"&gt;$stage1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
 &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;$stage2&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
 &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;$stage3&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;Then we simply make the call to the database using the "aggregate" func.&lt;br&gt;
The aggregate func takes one parameter, the aggregation pipline arr; which is simply an arr of objs called stages.&lt;br&gt;
That's all there is to the "MongoDB Aggregation Framework" (AF) from the bird's eye view:&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="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&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="nx"&gt;dbName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;collName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;aggregate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aggregationPipeline&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toArray&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Question and Answer
&lt;/h2&gt;

&lt;p&gt;1.&lt;br&gt;
How does AF compare with other database query systems, like Mongoose or GraphQL.&lt;/p&gt;

&lt;h4&gt;
  
  
  AF vs Mongoose:
&lt;/h4&gt;

&lt;p&gt;The AF is well beyond the capability of Mongoose.&lt;br&gt;
When you're composing AF queries, you're writing queries directly for the MongoDB engine and optimizer. It natively understands the query and optimizes it. AF is the future direction of the MongoDB company and ecosystem. They are pouring tens of thousands of development and research hours into it to make it better every iteration.&lt;/p&gt;

&lt;h4&gt;
  
  
  AF vs GraphQL:
&lt;/h4&gt;

&lt;p&gt;These are two different products.&lt;br&gt;
For example, your GraphQL resolvers can use the AF to retrieve data. GraphQL has it's set of usecases that it is designed for, like bringing various (or disparate) datastores together into a coherent and consistent orchestration.&lt;br&gt;
AF is deceptively simple; But also deceptively powerful and performant. So unless your enterprise usecase calls for a GraphQL-style solution, you may be better off selecting the least amount of moving parts.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;In the next few series of articles, we'll do some advanced and creative data-shaping activities. Taking the AF approach makes this possible.&lt;/p&gt;

</description>
      <category>database</category>
      <category>mongodb</category>
      <category>javascript</category>
      <category>express</category>
    </item>
    <item>
      <title>Mastering The Database - Accessing Nested Records - Series #10</title>
      <dc:creator>Functional Javascript</dc:creator>
      <pubDate>Thu, 11 Feb 2021 17:13:10 +0000</pubDate>
      <link>https://dev.to/functional_js/mastering-the-database-accessing-nested-records-series-10-2oln</link>
      <guid>https://dev.to/functional_js/mastering-the-database-accessing-nested-records-series-10-2oln</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;In the last series we retrieved a random sample of docs.&lt;br&gt;
It was very simple. Essentially a oneliner.&lt;/p&gt;

&lt;p&gt;But supposes we wanted to select a random sample of items that existed as subdocs of the outer level docs in our app?&lt;/p&gt;

&lt;p&gt;Actually, it's not too hard.&lt;br&gt;
And we don't use any loops.&lt;br&gt;
Instead we "unwind", or your could think of it as "flattening" our arr of docs.&lt;/p&gt;

&lt;p&gt;If an artist has an arr of albums, then each artist doc has an arr of subdocs.&lt;/p&gt;

&lt;p&gt;If an artist's arr of albums each contain an arr of song, then we have a doc that has an arr of subdocs whose subdocs also have an arr of subdocs.&lt;/p&gt;

&lt;p&gt;Here is what the outer doc's data shape look like:&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="cm"&gt;/*
data shape:
 {
    "artist": "Julian Lennon",
    "albums": [
      {
        "albumTitle": "Valotte (1984)",
        "albumSongs": [
          {
            "song": "Valotte"
          },
          {
            "song": "O.K. for You"
          },
          {
            "song": "On the Phone"
//....
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the query to select a random set of song (in this case 5 of them)&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="nx"&gt;mgArr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nlpdb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;collEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;songsColl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;unwindArr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;albums&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;unwindArr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;albums.albumSongs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;randomSample&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="nx"&gt;projectIncludeNoId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;artist&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;albums.albumSongs.song&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;Here are five random songs.&lt;br&gt;
We've included the artist so we can see who the song is performed by:&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="cm"&gt;/*
output:

[
  {
    "artist": "Miley Cyrus",
    "albums": {
      "albumSongs": {
        "song": "Girls Just Wanna Have Fun"
      }
    }
  },
  {
    "artist": "Creedence Clearwater Revival",
    "albums": {
      "albumSongs": {
        "song": "Penthouse Pauper"
      }
    }
  },
  {
    "artist": "Judas Priest",
    "albums": {
      "albumSongs": {
        "song": "Out In The Cold"
      }
    }
  },
  {
    "artist": "Akon",
    "albums": {
      "albumSongs": {
        "song": "Throw Dat"
      }
    }
  },
  {
    "artist": "Nazareth",
    "albums": {
      "albumSongs": {
        "song": "Hit The Fan"
      }
    }
  }
]
*/&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;p&gt;1.&lt;br&gt;
The unwindArr is a wrapper func around the $unwind stage operator.&lt;br&gt;
The wrappers make the code look cleaner, and they're usually oneliners:&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unwindArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;$unwind&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="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2.&lt;br&gt;
We have to unwind the outer arr, then we can next unwind the inner arr. We could keep on going if there were more arrs. For example, each song could have an arr of songwriters.&lt;/p&gt;

&lt;p&gt;3.&lt;br&gt;
Once all the songs are unwound, we can grab a random sample of them using the $sample stage operator.&lt;br&gt;
The RandomSample wrapper is a simple oneliner:&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;randomSample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lim&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;$sample&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;lim&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;4.&lt;br&gt;
Notice the dot notation in the unwind func in order to express the path to the nest arrs.&lt;/p&gt;

&lt;p&gt;5.&lt;br&gt;
Finally, for ease of display reason, I "project" out only two fields. My wrapper func, the "NoId" variant, excludes the Primary Key. I use this variant just for testing&lt;br&gt;
The raw $project syntax would look like this (0 means exclude, 1 means include):&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="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;$project&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;_id&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="na"&gt;artist&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;albums.albumSongs.song&lt;/span&gt;&lt;span class="dl"&gt;"&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="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;6.&lt;br&gt;
Take note also, that conveniently, we can swap out and use either the wrapper funcs, or the raw MongoDB stage syntax with our call to the MongoDB aggregate func. This is because the wrapper funcs simply just returns the raw syntax anyhow, of each stage in the pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.mongodb.com/manual/reference/operator/aggregation/unwind"&gt;https://docs.mongodb.com/manual/reference/operator/aggregation/unwind&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.mongodb.com/manual/reference/operator/aggregation/sample"&gt;https://docs.mongodb.com/manual/reference/operator/aggregation/sample&lt;/a&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>mongodb</category>
      <category>javascript</category>
      <category>express</category>
    </item>
    <item>
      <title>Mastering The Database - Node.js, Express.js, MongoDB - Series #09</title>
      <dc:creator>Functional Javascript</dc:creator>
      <pubDate>Thu, 11 Feb 2021 04:54:18 +0000</pubDate>
      <link>https://dev.to/functional_js/mastering-the-database-node-js-express-js-mongodb-series-09-3oc5</link>
      <guid>https://dev.to/functional_js/mastering-the-database-node-js-express-js-mongodb-series-09-3oc5</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Let's retieve some random items from a database collection&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="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apiEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api_find_artists_random&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&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="o"&gt;=&amp;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="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mgArr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nlpdb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;collEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;songsColl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;randomSample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&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;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;p&gt;1.&lt;br&gt;
We are using MongoDB's aggregation framework to retrieve a random sample of artists.&lt;/p&gt;

&lt;p&gt;2.&lt;br&gt;
This query has one aggregation stage, called "randomSample", which is just a functional wrapper around the $sample stage operator:&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="cm"&gt;/**
@func
retrieve a random sample of docs

@param {number} lim
@return {object}
*/&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;randomSample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lim&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;$sample&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;lim&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;3.&lt;br&gt;
Notice our query is already wrapped in an Express Route. Any registered client call that hits that route will retrieve the results.&lt;/p&gt;
&lt;h2&gt;
  
  
  Client Call
&lt;/h2&gt;

&lt;p&gt;Here is our client call:&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;fetchArtistsRandom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetchArrNoParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apiEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api_find_artists_random&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Client Call Notes
&lt;/h2&gt;

&lt;p&gt;1.&lt;br&gt;
Notice the custom fetch wrapper func.&lt;/p&gt;

&lt;p&gt;2.&lt;br&gt;
The "NoParams" portion of the name means we do not pass up any parameters to the server.&lt;/p&gt;

&lt;p&gt;3.&lt;br&gt;
the "fetchArr" means it returns an arr of results. (as opposed to just a single doc, which is called fetchObj).&lt;/p&gt;

&lt;p&gt;4.&lt;br&gt;
Notice we pass in only the URL segment of the API. This fetch wrapper func will retrieve the server base url. This url is set at build time. The build tool will modify the config file with the proper base url to the server.&lt;/p&gt;

&lt;p&gt;5.&lt;br&gt;
The fetch wrapper func will call axios using the POST method. All calls use the POST method to avoid the disadvantages associated with the passing of data over the URL.&lt;/p&gt;

&lt;p&gt;6.&lt;br&gt;
The fetchArtistsRandom event handler func can be called from the onMount lifecyle func, or from a wired up click event.&lt;br&gt;
eg:&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="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fetchArtistsRandom&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example UI Display
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eNlhAyNU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0ie5yr7o2q4mbs7geuq8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eNlhAyNU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0ie5yr7o2q4mbs7geuq8.jpg" alt="Random Artists example" width="257" height="630"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Here we've shown an example querying data from an API Route, from the User Interface.&lt;br&gt;
It takes just a matter of a minutes to set up a query for the User Interface once you have a set of tools in place.&lt;/p&gt;

&lt;p&gt;If you have any questions, let me know.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;Select random items using the $sample stage operator:&lt;br&gt;
&lt;a href="https://docs.mongodb.com/manual/reference/operator/aggregation/sample"&gt;https://docs.mongodb.com/manual/reference/operator/aggregation/sample&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>express</category>
      <category>mongodb</category>
      <category>database</category>
    </item>
    <item>
      <title>MongoDB: Inserting Data - Series #08</title>
      <dc:creator>Functional Javascript</dc:creator>
      <pubDate>Tue, 09 Feb 2021 17:43:43 +0000</pubDate>
      <link>https://dev.to/functional_js/mongodb-inserting-data-series-08-h4e</link>
      <guid>https://dev.to/functional_js/mongodb-inserting-data-series-08-h4e</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;In the last article in the series I showed how to establish a connection to MongoDB.&lt;/p&gt;

&lt;p&gt;Here I'll show how to interact with data using that connection object.&lt;/p&gt;

&lt;p&gt;Here's a simple insert:&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="cm"&gt;/**
@func
insert a single doc into a coll

@param {string} dbName
@param {string} collName
@param {object} o - the doc to insert into the coll
@return {Promise&amp;lt;object&amp;gt; | null} the inserted doc, or null if exception
*/&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mgInsertOne&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;collName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;o&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mongoAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&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="nx"&gt;dbName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;collName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;insertOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;getDateStandardWithSeconds&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&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="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="nx"&gt;error&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="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&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;client&lt;/span&gt;&lt;span class="p"&gt;)&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="nx"&gt;close&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;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;mgInsertOne&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's an example usage:&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="nx"&gt;mgInsertOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;myCompanyDB&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;userColl&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="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fluffy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's the sample output:&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="cm"&gt;/*
@output
{
  ts: '[2021-02-09 Tue 09:21:21]',
  firstName: 'fluffy',
  _id: 6022c491834ad44058181f5b
}
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;p&gt;The "mgInsertOne" utility func will return our inserted record. This is useful for delivering feedback in the UI.&lt;/p&gt;

&lt;p&gt;Notice the utility func closes the client connection in the "finally" block&lt;/p&gt;

&lt;p&gt;If the DB does not exists, it gets created dynamically.&lt;/p&gt;

&lt;p&gt;If the collection does not exists, it gets created dynamically.&lt;/p&gt;

&lt;p&gt;If you don't supply a primary key, which is field called, "_id", then the framework autogenerates one for you.&lt;/p&gt;

&lt;p&gt;The client code of this func is a simple one liner. Wrap it in an Express.js route, push it to a provider like Heroku, and you're live within minutes — from composing the query — to having it available for clients to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;If you have any questions let me know.&lt;/p&gt;

&lt;p&gt;The best way to perform queries in Mongo is using their "aggregate" func. It takes an arr of objs. Each obj is a part of the query that we're composing. It's an extremely powerful command that allows to you to shape and reshape your data any way your wish.&lt;br&gt;
We'll cover more real-life examples of this powerful tool.&lt;br&gt;
Start reading from the beginning of this series to get an introduction to this "Aggregation Framework".&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>javascript</category>
      <category>database</category>
      <category>express</category>
    </item>
    <item>
      <title>MongoDB: Connect to the Mongo Driver - Series #07</title>
      <dc:creator>Functional Javascript</dc:creator>
      <pubDate>Mon, 08 Feb 2021 19:02:25 +0000</pubDate>
      <link>https://dev.to/functional_js/mongodb-connect-to-the-mongo-driver-series-07-1l3b</link>
      <guid>https://dev.to/functional_js/mongodb-connect-to-the-mongo-driver-series-07-1l3b</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;This is our lowest level code for establishing a connection to the Mongo database.&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="k"&gt;import&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mongodb&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@root/mid-libs_node/bl/envs/processEnv&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;opt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;useNewUrlParser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;useUnifiedTopology&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;connectTimeoutMS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;span class="cm"&gt;/*
@func
get a connection obj to atlas mongodb

@return {Promise&amp;lt;MongoClient&amp;gt; | null}
*/&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mongoAsync&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&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;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;MongoClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mongoUriAtlas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&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="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="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mongoAsync: CATCH: err.stack... &lt;/span&gt;&lt;span class="dl"&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;stack&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;mongoAsync&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;p&gt;1.&lt;br&gt;
We import the npm library, which is the Mongo Driver software that allows us to establish a connection to Mongo&lt;/p&gt;

&lt;p&gt;2.&lt;br&gt;
We import our database credentials from the git-ignored ".env" file.&lt;/p&gt;

&lt;p&gt;3.&lt;br&gt;
We set our options.&lt;br&gt;
The first two options removing warning flags.&lt;br&gt;
I set the connection timeout a little higher to facilite the pushing of multi-megabyte catalogs and corpora (the plural of corpus) of data.&lt;/p&gt;

&lt;p&gt;4.&lt;br&gt;
This wrapper func returns the Mongo client object, which gives your code full power.&lt;/p&gt;

&lt;p&gt;5.&lt;br&gt;
The responsibility is on the client code to close the connection.&lt;br&gt;
(I'll show the idiom for that later in the series)&lt;/p&gt;

&lt;p&gt;6.&lt;br&gt;
"Atlas" is the name of the MongoDb company's DBaaS (Database as a Service) offering.&lt;/p&gt;

&lt;p&gt;7.&lt;br&gt;
That's about it. It's really just a simple wrapper.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;If you have any questions let me know.&lt;/p&gt;

&lt;p&gt;Next I'll show you a couple example of using this wrapper around the Mongo Driver; so you can write fast—sometimes single-line—database queries.&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>javascript</category>
      <category>database</category>
      <category>express</category>
    </item>
    <item>
      <title>MongoDb - insert embedded documents - series #06</title>
      <dc:creator>Functional Javascript</dc:creator>
      <pubDate>Sun, 07 Feb 2021 18:25:56 +0000</pubDate>
      <link>https://dev.to/functional_js/mongodb-insert-embedded-documents-m0e</link>
      <guid>https://dev.to/functional_js/mongodb-insert-embedded-documents-m0e</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Let's say a user wants to send us some correspondence.&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;[aside]&lt;br&gt;
Do we want to store it with the user doc?&lt;br&gt;
Or store it in a doc in a separate collection?&lt;br&gt;
That's the "referencing vs embedding" question.&lt;br&gt;
There is a checklist of questions you can ask, and we'll cover that in depth later in the series.&lt;br&gt;
The short and fast answer for this use case is that you could go either way, and it'll work fine.&lt;br&gt;
[end aside]&lt;/p&gt;
&lt;/blockquote&gt;


&lt;/blockquote&gt;
&lt;br&gt;
&lt;/blockquote&gt;

&lt;p&gt;In any case, embedding content is the power of NoSQL.&lt;br&gt;
Below is a function that will do this.&lt;br&gt;
First let's visualize the user data model:&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="cm"&gt;/*
user data model

{
 _id: "",
 firstName: "",
 lastName: "",
 email: "",
 correspondence: [
  {text: "", email: "", ts: ""},
  {text: "", email: "", ts: ""},
 ]
}

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Mongo utility func
&lt;/h2&gt;

&lt;p&gt;See the notes below for an explanation&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="cm"&gt;/**
@func
update a doc
- by pushing an obj onto one of it's fields that is of type arr

@notes
isUpdate = false - if no match is found for the outer doc, then a new outer doc is inserted
isUpdate = true - if a match is found for the outer doc

@param {string} dbName
@param {string} collName
@param {object} objFilter - match on this criteria
@param {object} objToUpdateOrInsert - update the doc at that location with this data
@return {Promise&amp;lt;object&amp;gt;} - the updated record, whether inserted or updated
*/&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mgUpsertOnePush&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;collName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;objFilter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;objToUpdateOrInsert&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mongoAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;try&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;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&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="nx"&gt;dbName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;collName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;findOneAndUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;objFilter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$push&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;getDateStandardWithSeconds&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;objToUpdateOrInsert&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="na"&gt;upsert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;returnOriginal&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="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;updatedExisting (isUpdate): &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastErrorObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updatedExisting&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;le&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mgUpsertOnePush: CATCH: there was an error...&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&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;stack&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&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;client&lt;/span&gt;&lt;span class="p"&gt;)&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="nx"&gt;close&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;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;p&gt;1.&lt;br&gt;
The option, "upsert: true" is how we enable upserting in Mongo&lt;/p&gt;

&lt;p&gt;2.&lt;br&gt;
The option, "returnOriginal: false" forces Mongo to return back the doc AFTER it's been updated. We want this so we can display to the user a confirmation of what they just sent us.&lt;/p&gt;

&lt;p&gt;3.&lt;br&gt;
The Mongo command, "findOneAndUpdate" means only one doc will get modified, the first one found.&lt;/p&gt;

&lt;p&gt;4.&lt;br&gt;
The "$push" operator is the embedding power here. It pushes this doc onto one of the doc's fields that is of type arr.&lt;/p&gt;

&lt;p&gt;5.&lt;br&gt;
The log statement, that starts with "l("updatedExisting"", just tells us if an "insert" or "update" was performed. I.e. was a record found? Or is this a new record?&lt;/p&gt;

&lt;p&gt;6.&lt;br&gt;
The "le" func means "log erroro" and is just a wrapper func for "console.error"&lt;/p&gt;
&lt;h2&gt;
  
  
  Example Usage
&lt;/h2&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="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apiEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api_upsert_user__featureRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&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;body&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="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mgUpsertOnePush&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nlpdb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;collEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;correspondence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;featureRequest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;getDateStandardWithSeconds&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;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;
  
  
  Notes
&lt;/h2&gt;

&lt;p&gt;1.&lt;br&gt;
We set up an Express.js route to accept correspondence from all our client applications.&lt;/p&gt;

&lt;p&gt;2.&lt;br&gt;
The client submits four fields...&lt;br&gt;
user_id&lt;br&gt;
email&lt;br&gt;
name&lt;br&gt;
text&lt;/p&gt;

&lt;p&gt;3.&lt;br&gt;
The { email } argument of the call to mgUpsertOnePush is what it tries to match on. If it doesn't find a user doc with that email, it will insert a new user doc.&lt;br&gt;
This is useful if you accept correspondence from users who are not signed up already to your site.&lt;/p&gt;

&lt;p&gt;4.&lt;br&gt;
The last argument will find find a field in the user doc called, "correspondence" (or create it if it's not there already, as an arr), and will push this sub-document (which is the correspondence content) onto the end of the arr.&lt;/p&gt;
&lt;h2&gt;
  
  
  Test it out
&lt;/h2&gt;

&lt;p&gt;1.&lt;br&gt;
Let's fill in the form:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hfZv1rSs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/44r8jyot22gm32csg2fr.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hfZv1rSs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/44r8jyot22gm32csg2fr.JPG" alt="Alt Text" width="880" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2.&lt;br&gt;
Let's submit the form:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xcaTibF1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4j0d3e1ztvvwpjqcb7or.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xcaTibF1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4j0d3e1ztvvwpjqcb7or.JPG" alt="Alt Text" width="880" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3.&lt;br&gt;
Confirm the DB entry:&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="nx"&gt;lpromiseStringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;mgArr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nlpdb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;collEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;matchExact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&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;joe@sixpack.com&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="cm"&gt;/*
@output
[
  {
    "_id": "60203a9ef36c378955b02a9d",
    "email": "joe@sixpack.com",
    "correspondence": [
      {
        "name": "Joe Sixpack",
        "type": "featureRequest",
        "text": "This is my inquiry",
        "ts": "[2021-02-07 Sun 11:08:13]"
      }
    ],
    "ts": [
      "[2021-02-07 Sun 11:08:14]"
    ]
  }
]
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;If you have any questions, let me know.&lt;/p&gt;

&lt;p&gt;You many notice that doing upserts, inserts, updates, delete does not involve the MongoDB Aggregation Framework (AF). However with the AF, we still have the power to insert or update its resultsets if we choose to. We don't always have to return the resultset to the client. This allows us to reshape data. We'll talk about that later in the series.&lt;/p&gt;

&lt;p&gt;That's for reading. And let's let the journey continue! :)&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>javascript</category>
      <category>database</category>
      <category>express</category>
    </item>
    <item>
      <title>NodeJS, MongoDB - "OR" queries - series #05</title>
      <dc:creator>Functional Javascript</dc:creator>
      <pubDate>Sat, 06 Feb 2021 02:19:41 +0000</pubDate>
      <link>https://dev.to/functional_js/nodejs-expressjs-mongodb-or-queries-series-05-504</link>
      <guid>https://dev.to/functional_js/nodejs-expressjs-mongodb-or-queries-series-05-504</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;When querying the database in MongoDB, all "Matches" you perform are conjunctions (i.e. "AND" operations).&lt;/p&gt;

&lt;p&gt;To perform disjunction queries (i.e. "OR" operations), I'll use a wrapper func (helper func) called "matchOr".&lt;/p&gt;

&lt;p&gt;Here's an example. For an indepth explanation, see the Notes section below.&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="nx"&gt;lpromise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;mgArr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nlpdb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;collEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users_actions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;matchExact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;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;inquiry&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;matchOr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;existsNot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;isDeleted&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;isFalse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;isDeleted&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="nx"&gt;lastInserted&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="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Notes
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;USECASE Let's say users of our website are submitting inquiries. We want to have a look at the last few inquiries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We want to exclude deleted inquiries. Deleted docs (records) are soft-deletes, meaning they are flagged as deleted (isDeleted=true) rather than actually hard deleted from the db collection.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The disjunct (the "OR") situation is that if there is no isDeleted field then the doc has never been deleted. But if there is an isDeleted field, only in cases where it's value is true is it deleted.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The matchExact("type", "inquiry") stage filters by only correspondence types that are inquiries (this is an "AND" filter).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The matchOr stage reads as this, "return the record if there is no isDeleted field, OR, return the record if the isDeleted field exists but its value is false". With this we are filtering out any "isDeleted=true"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The last stage just retrieves the last 5 inserted records.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The raw Mongo Aggregation Framework Stage syntax would look like this...&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;$match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$or&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;isDeleted&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$exists&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;span class="na"&gt;isDeleted&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;So we've saved ourselves a bunch of curlies. :)&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If you have any questions, let me know, and I'll try my best to answer them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Other constructs in the example code here like "lpromise" and "mgArr" were explained earlier in this article series, so make sure you read those if you are new to the series.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tomorrow I'll show an interesting but very common type of operation:&lt;br&gt;
We want to update a document by pushing a document onto one of its fields that is of type array.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Res
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.mongodb.com/manual/reference/operator/query/or/"&gt;https://docs.mongodb.com/manual/reference/operator/query/or/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>express</category>
      <category>mongodb</category>
      <category>database</category>
    </item>
    <item>
      <title>NodeJS, ExpressJS,  MongoDB - Paginate - series #04</title>
      <dc:creator>Functional Javascript</dc:creator>
      <pubDate>Fri, 05 Feb 2021 02:49:50 +0000</pubDate>
      <link>https://dev.to/functional_js/nodejs-expressjs-redis-mongodb-series-04-jle</link>
      <guid>https://dev.to/functional_js/nodejs-expressjs-redis-mongodb-series-04-jle</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;A quick example on actually a very important feature: "paginate"&lt;/p&gt;

&lt;p&gt;Always paginate your resultsets. This protects your system from accidental or malicious oversized resultsets being retrieved.&lt;/p&gt;

&lt;p&gt;Pagination is very easy in MongoDB. See the notes section below.&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="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;apiEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api_find_artists__songRegex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="p"&gt;}&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;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;//#guard 1&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isNotBetween&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&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="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;page&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;//defaultVal&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;//#guard 2&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;isEmptyStrOrNil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&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="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;json&lt;/span&gt;&lt;span class="p"&gt;([{&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;the search term was empty&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;regex&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;RegExp&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;searchTerm&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;i&lt;/span&gt;&lt;span class="dl"&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="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;mgArr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nlpdb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;collEnum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;songsColl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;copyField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;searchResult&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;albums&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;unwindArr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;searchResult&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;unwindArr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;searchResult.albumSongs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;matchRegex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;searchResult.albumSongs.song&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;//54&lt;/span&gt;
    &lt;span class="nf"&gt;paginate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;page&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;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;See series #03 for an explanation of some of these stages like "copyField" and "unwindArr". Here we'll concentrate on the one database query stage, "paginate".&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The above Node.js Express router endpoint returns the paged results of a user search for a string of characters in a song.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The paginate wrapper func wraps the skip and limit funcs&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
@func
limit a resultset to a particular requested page of results

@param {number} lim - page size
@param {number} page - page number to retrieve
@return {object[]}
*/&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paginate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;page&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;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lim&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&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;// 50 * 2 gets results 51 to 100&lt;/span&gt;
    &lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lim&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;ul&gt;
&lt;li&gt;The skip and limit funcs both wrap the MongoDB $skip and $limit pipeline stage operators
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lim&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;$limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;lim&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 javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;skip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;$skip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;So paginate returns an arr of two stages because it uses two staging operators. You don't have think about that though.&lt;br&gt;
You only have to call paginate and pass in two numbers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An example of the resultset in the UI:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2Ftkck2mos5831enmwxav7.JPG" 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%2Ftkck2mos5831enmwxav7.JPG" alt="song matches"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What's Next
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If you have any questions let me know&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We'll keep moving the needle forward with more enterprise patterns in the subsequent articles in this series&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>node</category>
      <category>mongodb</category>
      <category>javascript</category>
      <category>database</category>
    </item>
  </channel>
</rss>
