<?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: Layers</title>
    <description>The latest articles on DEV Community by Layers (@layers).</description>
    <link>https://dev.to/layers</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%2F2036118%2F358faebb-6b44-4990-a220-d8027cc3b56e.png</url>
      <title>DEV Community: Layers</title>
      <link>https://dev.to/layers</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/layers"/>
    <language>en</language>
    <item>
      <title>Why MongoDB and GraphQL are perfect for each other.</title>
      <dc:creator>Layers</dc:creator>
      <pubDate>Fri, 06 Sep 2024 15:12:58 +0000</pubDate>
      <link>https://dev.to/layers/why-mongodb-and-graphql-are-perfect-for-each-other-2m7d</link>
      <guid>https://dev.to/layers/why-mongodb-and-graphql-are-perfect-for-each-other-2m7d</guid>
      <description>&lt;h2&gt;
  
  
  What is GraphQL?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;GraphQL is an open-source data query and manipulation language for APIs and a query runtime engine&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What is MongoDB?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;MongoDB is a source-available cross-platform document-oriented database program.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  That's cool, but why are they "perfect for each other?"
&lt;/h2&gt;

&lt;p&gt;In this article I'll assume you have an existing understanding of the way GraphQL and MongoDB work, after all this isn't a tutorial but rather an explanation of why MongoDB and GraphQL are perfect for one another.&lt;/p&gt;

&lt;p&gt;Now onto the good stuff.&lt;/p&gt;

&lt;p&gt;If you want to view a list of posts you might send a query like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see we're asking our GraphQL API for a list of posts, which will give us back the title and content fields on each respective post. The function to return this data might look something 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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resolvers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;posts&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;PostModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On its own, this isn't very notable, but cool stuff starts to happen when you leverage the Document nature of MongoDB.&lt;br&gt;
Nearly every Object in HiddenLayer's database contains a subdocument called &lt;code&gt;Insights&lt;/code&gt; which represents various forms of data. For example, the counts of a number of replies on a post. Typically if you were using an SQL style of database this would live in another table.&lt;/p&gt;
&lt;h2&gt;
  
  
  So what if it lives in another table?
&lt;/h2&gt;

&lt;p&gt;The simple answer is less time spent on doing stuff on the database.&lt;br&gt;
The query to get a post and its &lt;code&gt;insights&lt;/code&gt; would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;insights&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;totalReplies&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And its corresponding resolver code querying a MongoDB 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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resolvers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// The same resolver from before&lt;/span&gt;
        &lt;span class="nf"&gt;posts&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;PostModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&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;Insight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// A field resolver that will let us return a sub-object within each `Post` object&lt;/span&gt;
        &lt;span class="nf"&gt;insights&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// This functions first argument will always be the object returned from the parent resolver.&lt;/span&gt;
            &lt;span class="c1"&gt;// We can just grab the object and return its insights object which already exists on the document&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insights&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the &lt;code&gt;insights&lt;/code&gt; field already exists and is stored directly on the post we add no additional database overhead to fetch this data. If we were to write this resolver using an SQL database it might look something 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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resolvers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;posts&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SELECT post, title FROM posts&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="na"&gt;Insight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// A field resolver that will let us return a sub-object within each `Post` object&lt;/span&gt;
        &lt;span class="nf"&gt;insights&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// We now have to add another database query to fetch and return this data.&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SELECT totalReplies FROM insights WHERE post_id = $(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;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="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;What ends up happening is that we run the query for the &lt;code&gt;insights&lt;/code&gt; table for every single post. So if we fetch 50 posts, that means 50 additional queries to fetch the &lt;code&gt;insights&lt;/code&gt;. Initially this may not seem like much, but if there's a lot of data and depth in these relation/sub object fields you end up with enormous amounts of database queries.&lt;/p&gt;

&lt;p&gt;I think this is where MongoDB &amp;amp; GraphQL truly shine. MongoDB's data storage structure already represents data the same way as GraphQL, we can leverage the deeply nested data to return a lot of information back to the consumer with very minimal overhead.&lt;/p&gt;

&lt;p&gt;I plan on turning these articles into a series, in the upcoming articles I'll deep dive into how this impacts HiddenLayer's queries in production using more in depth code examples. If this interests you be on the lookout.&lt;/p&gt;

&lt;p&gt;If you'd like to learn more about HiddenLayer, I'd encourage you to head over to &lt;a href="https://hiddenlayer.app" rel="noopener noreferrer"&gt;https://hiddenlayer.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Original article: &lt;a href="https://programming.hiddenlayer.app/c/mongodb/post/why-mongodb-and-graphql-are-perfect-for-each-other-ee7f" rel="noopener noreferrer"&gt;https://programming.hiddenlayer.app/c/mongodb/post/why-mongodb-and-graphql-are-perfect-for-each-other-ee7f&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
