<?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: Ahmed Magdy</title>
    <description>The latest articles on DEV Community by Ahmed Magdy (@ahmedmagdy11).</description>
    <link>https://dev.to/ahmedmagdy11</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%2F399936%2Fe5b785f2-68dd-4fa0-9c45-14ffb3b8e7b2.jpeg</url>
      <title>DEV Community: Ahmed Magdy</title>
      <link>https://dev.to/ahmedmagdy11</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ahmedmagdy11"/>
    <language>en</language>
    <item>
      <title>Become a Better programmer by Detaching Your Emotions from work</title>
      <dc:creator>Ahmed Magdy</dc:creator>
      <pubDate>Sun, 11 Dec 2022 14:44:09 +0000</pubDate>
      <link>https://dev.to/ahmedmagdy11/become-a-better-programmer-by-detaching-your-emotions-from-work-3m08</link>
      <guid>https://dev.to/ahmedmagdy11/become-a-better-programmer-by-detaching-your-emotions-from-work-3m08</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;I wanna share and discuss something with all my Dev colleagues. In the Last few months about I felt like I have lost most interest for programming in general and this has lead to me becoming Lazy even though I am not a lazy person at all. I tried multiple stuff. but nothing worked. In my mind I knew that I was good programmer. I can't simply leave something I am good at and make good money from It to go work at something I am not good at and pays less money.&lt;/p&gt;

&lt;p&gt;Me saying this doesn't mean to just drop your dreams and stick to becoming programmer ..etc. Fast forward to the future I am trying something new which is working for me perfectly which is &lt;strong&gt;Detaching my emotions away from programming&lt;/strong&gt;. meaning I don't have to like it to do it and let me tell you this is the most correct way to get things done. &lt;/p&gt;

&lt;h2&gt;
  
  
  But what leads to losing interest in the first place?
&lt;/h2&gt;

&lt;p&gt;In some experiment some scientist gathered around bunch of kids who &lt;br&gt;
liked to draw with out giving them any rewards then they started giving them rewards for painting and drawing as soon as they stopped giving them these rewards all of the kids have lost interest in drawing. &lt;/p&gt;

&lt;p&gt;So if you apply this scenario on fresh grads who are very passionate about programming.. You will find that the reward mentioned here is &lt;strong&gt;The Salary&lt;/strong&gt; and after sometime the salary just doesn't feel the same anymore because baseline of dopamine is elevated. You can check &lt;em&gt;&lt;strong&gt;Dr. Andrew Huberman&lt;/strong&gt;&lt;/em&gt; on Youtube he has some great videos on how dopamine affect you. &lt;/p&gt;

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

&lt;p&gt;If you have lost some interest like me in programming try not doing it for fun for a while and just do it regradless of how you feel and this can just work around for anything in life.&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>How to Make a major change to all your foreign keys (Mysql, Laravel)</title>
      <dc:creator>Ahmed Magdy</dc:creator>
      <pubDate>Thu, 28 Oct 2021 21:03:37 +0000</pubDate>
      <link>https://dev.to/ahmedmagdy11/how-to-make-a-change-to-all-your-foreign-keys-mysql-laravel-5e5n</link>
      <guid>https://dev.to/ahmedmagdy11/how-to-make-a-change-to-all-your-foreign-keys-mysql-laravel-5e5n</guid>
      <description>&lt;p&gt;I've recently stumbled upon this issue where I wanted to add &lt;code&gt;ON DELETE CASCADE&lt;/code&gt; to every foreign key i had on my tables. &lt;/p&gt;

&lt;p&gt;I couldn't afford to do this manually because the project I am working on had over &lt;em&gt;106 tables&lt;/em&gt; and it's still expanding, so the main idea here is to write a general script that can be applied to any project. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;1- You need to fetch every foreign key for you DATABASE&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SELECT TABLE_NAME,&lt;br&gt;
       COLUMN_NAME,&lt;br&gt;
       CONSTRAINT_NAME,&lt;br&gt;
       REFERENCED_TABLE_NAME,&lt;br&gt;
       REFERENCED_COLUMN_NAME&lt;br&gt;
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE&lt;br&gt;
WHERE TABLE_SCHEMA = "&amp;lt;DATABASE_NAME&amp;gt;" &lt;br&gt;
      AND REFERENCED_COLUMN_NAME IS NOT NULL &lt;br&gt;
      AND CONSTRAINT_NAME LIKE "%_foreign"&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note&lt;/em&gt; I added &lt;code&gt;CONSTRAINT_NAME LIKE "%_foreign"&lt;/code&gt; because when Laravel creates a foreign key it follows this convention below &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;CONVENTION:&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Schema::table('student_grades', function(Blueprint $table){
  // adding a foreign key 
   $table-&amp;gt;foreign("student_id")-&amp;gt;references("id")-&amp;gt;on("students");
});

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

&lt;/div&gt;



&lt;p&gt;The created foreign key will be named &lt;code&gt;student_grades_student_id_foreign&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;hence the condition  &lt;code&gt;CONSTRAINT_NAME LIKE "%_foreign"&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;If you apply the previous SQL Query you will get data like this&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LCmsWU6K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qwvib1opil4z60lpatj8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LCmsWU6K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qwvib1opil4z60lpatj8.png" alt="Data" width="790" height="88"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;2- Re-create your foreign key&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;make a migration file &lt;code&gt;php artisan make:migration alter_foreign_keys_on_tables&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Now let's get to the code&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  public function up() {

       // The SQL Query
        $data = DB::table("INFORMATION_SCHEMA.KEY_COLUMN_USAGE")
            -&amp;gt;select([
                "TABLE_NAME",
                "COLUMN_NAME",
                "CONSTRAINT_NAME",
                "REFERENCED_TABLE_NAME",
                "REFERENCED_COLUMN_NAME"
            ])
            -&amp;gt;whereRaw("TABLE_SCHEMA =  '&amp;lt;DATABASE_NAME&amp;gt;' 
                AND REFERENCED_COLUMN_NAME IS NOT NULL 
                AND CONSTRAINT_NAME LIKE '%_foreign'")
            -&amp;gt;get();
        // you need to write the next line to get back to your ..
        // Original Database 

        DB::statement("USE &amp;lt;DATABASE_NAME&amp;gt;");
        foreach ($data as $single) {
           // Don't forget to add protected $single = null; in migration class
            $this-&amp;gt;single = $single;
            Schema::table($single-&amp;gt;TABLE_NAME, function (Blueprint $table) {
               // drop the previous foreign key 
                $table-&amp;gt;dropForeign($this-&amp;gt;single-&amp;gt;CONSTRAINT_NAME);
                // New Foreign key 
$table-&amp;gt;foreign($this-&amp;gt;single-&amp;gt;COLUMN_NAME)-&amp;gt;references($this-&amp;gt;single-&amp;gt;REFERENCED_COLUMN_NAME)
                    -&amp;gt;onDelete("cascade")-&amp;gt;on($this-&amp;gt;single-&amp;gt;REFERENCED_TABLE_NAME);
            });
        }
    }

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Final Note:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The purpose of this article was to show you how to make a major change to all your foreign keys. &lt;/p&gt;

&lt;p&gt;feel free to contact me on my email &lt;a href="//ahmed.magdy.9611@gmail.com"&gt;ahmed.magdy.9611@gmail.com&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Thanks for coming to my Ted Talk. &lt;/p&gt;

</description>
      <category>laravel</category>
      <category>mysql</category>
      <category>backend</category>
    </item>
    <item>
      <title>Building Cache Layer Using Redis and Mongoose</title>
      <dc:creator>Ahmed Magdy</dc:creator>
      <pubDate>Wed, 17 Feb 2021 01:58:52 +0000</pubDate>
      <link>https://dev.to/ahmedmagdy11/building-cache-layer-using-redis-and-mongoose-11kb</link>
      <guid>https://dev.to/ahmedmagdy11/building-cache-layer-using-redis-and-mongoose-11kb</guid>
      <description>&lt;h2&gt;
  
  
  Introduction.
&lt;/h2&gt;

&lt;p&gt;If you ever built an api you will find that you will be needing to cache some GET requests that repeat alot and a find (if you are using mongoose) or select (sql) queries can be expensive over time. We are going to introduce a solution to this problem in this article. &lt;/p&gt;

&lt;h2&gt;
  
  
  Solution.
&lt;/h2&gt;

&lt;p&gt;We will be following a very simple strategy here, But before we start you need to be familiar with mongoose and node.js&lt;/p&gt;

&lt;h3&gt;
  
  
  Strategy
&lt;/h3&gt;

&lt;p&gt;Imagine we are working with a Query to fetch all &lt;a href="https://dev.to"&gt;dev.to&lt;/a&gt; blogs and The model will be called &lt;em&gt;Blogs&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Blogs Model
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const blogSchema = new mongoose.Schema({
    owner : {
        // user in the database 
        type: mongoose.Types.ObjectId,
        required: true,
        ref: "User"
    },
    title: {
        type : String,
        required: true
    },
    tags: {
        type : [mongoose.Types.ObjectId],
    },
    blog: {
        type : String
    }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now the request to fetch all the blog&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.use("/api/blogs",(req,res,next)=&amp;gt;{
         const blogs = await Blogs.find({}); 
          res.send(blogs);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now after we get the image of what we are working with lets get back to the strategy &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;send a query to the database to ask for a certain thing &lt;/li&gt;
&lt;li&gt;if this query has been fetched before aka exists in cache (redis)? &lt;/li&gt;
&lt;li&gt;if yes, Then return the cached result &lt;/li&gt;
&lt;li&gt;if no, Cache it in redis and return the result&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The trick here is that there is a function in mongoose that is automatically executed after every operation&lt;br&gt;
The function is called exec. &lt;/p&gt;

&lt;p&gt;so we need to overwrite this &lt;code&gt;exec&lt;/code&gt; function to do the caching logic. &lt;/p&gt;
&lt;h5&gt;
  
  
  first step to overwrite
&lt;/h5&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const exec = mongoose.Query.prototype.exec;
mongoose.Query.prototype.exec = async function (){
    // our caching logic
    return await exec.apply(this, arguments);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;now we need to make a something that tells us what gets cached and what doesn't. Which is a chainable function. &lt;/p&gt;
&lt;h5&gt;
  
  
  making the chainable function
&lt;/h5&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mongoose.Query.prototype.cache = function(time = 60 * 60){
    this.cacheMe = true; 
    // we will talk about cacheTime later;
    this.cacheTime = time;
    return this;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So Now if i wrote&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Blogs.find({}).cache(); // this is a valid code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if you are not familiar with Redis GO GET FAMILIAR WITH IT. there are thousands of videos and tutorials and it won't take that much time. &lt;/p&gt;

&lt;p&gt;We need some data structure or types for the cached results. After some thinking, I've found out this is the best structure and I will explain why.&lt;/p&gt;

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

&lt;p&gt;Blogs is the collection name; &lt;/p&gt;

&lt;p&gt;let's say you are doing &lt;code&gt;Blogs.find({"title" : "cache" , user : "some id that points to user" })&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;then Query will be { "title" : "cache" , "user" : "some id ... " , op : "find"  // the method of the query } ;&lt;/p&gt;

&lt;p&gt;result is the result we got from database; &lt;/p&gt;

&lt;p&gt;This structure is called NestedHashes. &lt;/p&gt;

&lt;p&gt;Why we are doing Nested Hashes like this &lt;/p&gt;

&lt;p&gt;we need to say if Blogs got a new Update or Insert or Delete operation delete the cached result. Because the cached result is old and not updated by any of the new operations. &lt;/p&gt;

&lt;h3&gt;
  
  
  NOW back to code.
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mongoose.Query.prototype.exec = async function(){
    const collectionName = this.mongooseCollection.name;

    if(this.cacheMe){   
      // You can't insert json straight to redis needs to be a string 

        const key = JSON.stringify({...this.getOptions(),
             collectionName : collectionName, op : this.op});
        const cachedResults = await redis.HGET(collectionName,key);

      // getOptions() returns the query and this.op is the method which in our case is "find" 

        if (cachedResults){
          // if you found cached results return it; 
            const result = JSON.parse(cachedResults);
            return result;
        }
     //else 
    // get results from Database then cache it
        const result = await exec.apply(this,arguments); 

        redis.HSET(collectionName, key, JSON.stringify(result) , "EX",this.cacheTime);
       //Blogs - &amp;gt; {op: "find" , ... the original query} -&amp;gt; result we got from database
        return result;
    }

    clearCachedData(collectionName, this.op);
    return exec.apply(this,arguments);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember the part where I said we need to clear cached data in case of Update, Insert or Delete. &lt;/p&gt;

&lt;h3&gt;
  
  
  clear the cached data
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function clearCachedData(collectionName, op){
    const allowedCacheOps = ["find","findById","findOne"];
    // if operation is insert or delete or update for any collection that exists and has cached values 
    // delete its childern
    if (!allowedCacheOps.includes(op) &amp;amp;&amp;amp; await redis.EXISTS(collectionName)){
        redis.DEL(collectionName);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Expected Results
&lt;/h2&gt;

&lt;p&gt;Much faster find queries.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Cache
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Don't Cache large data 
Imagine if you have a find query that return 20 MB or even 100 MB worth of data you will be slowing down your whole application. &lt;/li&gt;
&lt;li&gt;Don't Cache Requests that don't get a lot of traffic and that is highly dependent on your application.&lt;/li&gt;
&lt;li&gt;Don't Cache Important Data like users or transactions.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://pastebin.com/Y0k2Rzwq" rel="noopener noreferrer"&gt;My redis setup&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;cacheTime paramter is option I put a default of 1 hour but you can edit it as you wish, i suggest 1 or 2 days. &lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>node</category>
      <category>redis</category>
      <category>database</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>Handling Mongoose Dublication Errors</title>
      <dc:creator>Ahmed Magdy</dc:creator>
      <pubDate>Mon, 08 Feb 2021 16:19:20 +0000</pubDate>
      <link>https://dev.to/ahmedmagdy11/handling-mongoose-dublication-errors-3f6n</link>
      <guid>https://dev.to/ahmedmagdy11/handling-mongoose-dublication-errors-3f6n</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;If you ever wrote Node.js code and decided to have a document based DB, your main goto will be MongoDB ofc and you will be using mongoose as your ODM then you have met this error before.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;MongoError: E11000 duplicate key error collection: testDB.users index: name_1 dup key: { : "some random name" }&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;the problem is there are multiple ways to handle it. one of them is using a library called &lt;a href="https://www.npmjs.com/package/mongoose-unique-validator"&gt;mongoose-unique-validator&lt;/a&gt;. but we are not going to use an external library which I don't know how it works under the hood.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Before we keep going
&lt;/h2&gt;

&lt;p&gt;there is some stuff that needs to be clarified &lt;br&gt;
1- &lt;code&gt;name { type :string , unqiue: true}&lt;/code&gt; unique param in mongoose is not a validator meaning doing &lt;code&gt;const myUser = new User(data)&lt;/code&gt; will not throw an error in case of duplication.&lt;br&gt;
it will only throw and error when doing  &lt;code&gt;myUser.save()&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;2- when trying to add a user I suggest using either &lt;code&gt;insertOne&lt;/code&gt; or &lt;code&gt;create&lt;/code&gt; function. and keep using it through your whole application because We are about to overwrite one of them. &lt;/p&gt;
&lt;h3&gt;
  
  
  Note: I will be using &lt;code&gt;create&lt;/code&gt; here.
&lt;/h3&gt;
&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;why we wanna handle duplication error globally anyway? &lt;br&gt;
because you might have 10 or 20 collections where each one has 2 or 3 unique keys and you are not going to check for every one manually. &lt;/p&gt;
&lt;h2&gt;
  
  
  Implmentation
&lt;/h2&gt;

&lt;p&gt;you can easily overwrite mongoose function by doing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mongoose = require("mongoose");
// old create function 
const create = mongoose.Model.create;
// overwriting
// it takes this arguments according to mongoose documentation
mongoose.Model.create = async function (doc, options, callback){
     // your logic here;
     // return original function 
    return create.apply(this, arguments);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;my logic here is when I am using &lt;code&gt;create&lt;/code&gt; function I will insert a new option which is some keys to check if they are duplicated or no.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const data = { name : "ahmed"} 

User.create(data, {checkForDublication : ["name"] }).then(console.log).catch(err=&amp;gt; console.error(err)); 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I am going for this format where checkForDublication is a new option I created and will be sending the keys as array format.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Logic
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;check if &lt;code&gt;options&lt;/code&gt; has a &lt;code&gt;checkForDublication&lt;/code&gt; param.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;check if its values exist in the schema and are unique.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;the last step (checking if the key is unique) is very important, Because we are going to use &lt;code&gt;findOne({$or: searchQuery})&lt;/code&gt; ... and as you know searchQuery is going to be an array, If one Element in this array is not unique or index it's going to perform collectionScan instead of indexScan which is very slow. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;filter the checkForDublication array meaning remove every key that doesn't exist in the schema or is not unique.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;generating the search query &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;checking if the result of the search query exist. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mongoose.Model.create = async function (doc, options, callback){
    if (options &amp;amp;&amp;amp; options.checkKeysForDublication){
        const searchQuery = getSearchQuery(doc,this.schema.obj, options.checkKeysForDublication);
        await checkForDublication(this, searchQuery);
    }


    return create.apply(this, arguments);
}

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  getSearchQuery function
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function getSearchQuery(doc,schema, keys){
    if (!Array.isArray(keys)||keys.length === 0){
        return;
    }
    const filteredKeys = filterKeys(doc,schema,keys);
    return  makeSearchQuery(doc,filteredKeys);

};
function filterKeys (doc,schema,keys){
    const filteredKeys = keys.filter(key=&amp;gt;{
        if (!schema[key] || !schema[key].unique || !doc[key]){
            console.warn(`${key} key either doesn't exist in this schema or not unique so it will filtered`);
        }
        return schema[key] &amp;amp;&amp;amp; schema[key].unique &amp;amp;&amp;amp; doc[key];
    });
    return filteredKeys;
}
function makeSearchQuery(doc,keys){
    const query = [];
    keys.forEach(key=&amp;gt;{
        const obj = {};
        obj[key] = doc[key];
        query.push(obj);
    });
    return query;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  output of getSearchQuery
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;[{"name" : "ahmed"} // and every key that was common between insterted document and checkForDublication arr]&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;another example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User.create({name: "ahmed ,
 email :"anymail@gmail.com" , password : "123" }, {checkForDublication : ["name" , "email"] }.then(console.log);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  output of getSearchQuery
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;[{ "name" : "ahmed" , {"email": "anymain@gmail.com"}]&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  checkForDublication function
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function checkForDublication (Model, searchQuery){
    const result = await Model.findOne({$or: searchQuery});
    if (!result){
        return;
    }
    searchQuery.forEach(singleObject=&amp;gt;{
        //every singleObject has only one keyl
        const key = Object.keys(singleObject)[0];
        if (result[key] === singleObject[key]){
            throw new Error(`${key} already exists`);
        }
    });

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  output &lt;code&gt;Error: name already exists&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;important note:&lt;/em&gt;&lt;/strong&gt;  don't forget to put this line of code &lt;code&gt;require("./fileThatHasOverWrittenCreateFunction.js")&lt;/code&gt; at the very start of your project so changes can take effect. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE:&lt;/em&gt;&lt;/strong&gt; you can throw your custom error as well... but this one is for another article. &lt;/p&gt;

&lt;h2&gt;
  
  
  Finally
&lt;/h2&gt;

&lt;p&gt;The main goal in this article was to make a global way to handle duplication errors. &lt;br&gt;
if You have any feedback feel free to send me on this email &lt;a href="//ahmedmagdy@creteagency.com"&gt;ahmedmagdy@creteagency.com&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Enjoy~ &lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>node</category>
      <category>mongoose</category>
      <category>backend</category>
    </item>
    <item>
      <title>In case You didn't know, you don't need to install any npm package more than once.</title>
      <dc:creator>Ahmed Magdy</dc:creator>
      <pubDate>Tue, 02 Feb 2021 14:51:37 +0000</pubDate>
      <link>https://dev.to/ahmedmagdy11/in-case-you-didn-t-know-you-don-t-need-to-install-any-npm-package-more-than-once-1cd6</link>
      <guid>https://dev.to/ahmedmagdy11/in-case-you-didn-t-know-you-don-t-need-to-install-any-npm-package-more-than-once-1cd6</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Many of us have faced the problem of having to install the same package a lot of times because we are working on multiple projects locally, And as we all know your &lt;strong&gt;node_modules&lt;/strong&gt; can get pretty out of hands in terms of size on disk. &lt;/p&gt;

&lt;h2&gt;
  
  
  PNPM
&lt;/h2&gt;

&lt;p&gt;I've stumbled upon this &lt;a href="https://pnpm.js.org"&gt;project&lt;/a&gt; recently which helps you manage and solve that problem of having to install the same package more than one time. It's using &lt;a href="https://en.wikipedia.org/wiki/Content-addressable_storage"&gt;CAS&lt;/a&gt; to store &lt;strong&gt;node_modules&lt;/strong&gt; and later refer to them on your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;you will find a lot of commands in their &lt;a href="https://pnpm.js.org"&gt;Documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;here are the ones I am using for now &lt;/p&gt;

&lt;p&gt;-&lt;code&gt;pnpm install&lt;/code&gt; instead of &lt;code&gt;npm install&lt;/code&gt;, What will this do is install the packages in your &lt;code&gt;package.json&lt;/code&gt;; if they were already installed before it will just link them to your project directory. &lt;br&gt;
also, pnpm install will generate a file called &lt;code&gt;pnpm-lock.yaml&lt;/code&gt; which contains information about the installed packages. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pnpm add &amp;lt;package name&amp;gt;&lt;/code&gt; instead of &lt;code&gt;npm install &amp;lt;package name&amp;gt;&lt;/code&gt; 
also works that same as &lt;code&gt;pnpm install&lt;/code&gt; if the package doesn't exist it will download it and link it to your &lt;strong&gt;&lt;em&gt;node_modules&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;NOTE:&lt;/em&gt;&lt;/strong&gt; you can use the same flags of npm.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;example:&lt;/em&gt; &lt;code&gt;pnpm add &amp;lt;package name&amp;gt; --save-dev&lt;/code&gt; and it will it add to your dev dependencies.&lt;/p&gt;

&lt;p&gt;I recommend that you read their Documentation as it contains a lot more details on how to use and the behavior of each command. &lt;/p&gt;

&lt;p&gt;Good luck and Enjoy.&lt;/p&gt;

</description>
      <category>npm</category>
      <category>nodemodules</category>
      <category>pnpm</category>
    </item>
    <item>
      <title>Building a cronjobs server with NodeJs</title>
      <dc:creator>Ahmed Magdy</dc:creator>
      <pubDate>Sat, 24 Oct 2020 16:27:16 +0000</pubDate>
      <link>https://dev.to/ahmedmagdy11/building-a-cronjob-server-with-nodejs-1dgi</link>
      <guid>https://dev.to/ahmedmagdy11/building-a-cronjob-server-with-nodejs-1dgi</guid>
      <description>&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: This article is made for people who are familiar with Nodejs, if you are coming from another language this can be beneficial as well. &lt;/p&gt;

&lt;p&gt;What is a cronjob, It's basically a job or a function that will be executed after a certain amount of time aka scheduled. &lt;/p&gt;

&lt;p&gt;In the project we are building right now we needed to have scheduled jobs to update certain parameters into our Database. so this is easy, Right? you can just use this npm package &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fnode-schedule" 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%2Fwww.npmjs.com%2Fpackage%2Fnode-schedule" alt="node-schedule"&gt;&lt;/a&gt;, so where is the problem?&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The problem&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;While developing the project we found that some of the jobs are being scheduled but not Executed, why? because when we push new code into our server we have to restart. and every scheduled job into the memory is deleted forever. so what is the solution? &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The solution&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We have two options here but the core idea is still the same. &lt;br&gt;
The cronjob should run as a stand-alone instance meaning it's independent of our main application. &lt;/p&gt;

&lt;p&gt;1- to schedule jobs based on the OS that our server running on which is a Linux distribution. While this solution might work, for now, the problem is we don't have full control over our server and we might remove the whole project into another server in the future.&lt;br&gt;
2- to make a cronjob server and have a record of these jobs in our database &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Important Note&lt;/em&gt;: I am not going to share the full code in this article, I am just sharing the core idea.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Making the Server&lt;/strong&gt;.
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;first, we need to make a jobs model &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;a more simplified version of this model will be &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   ` time:{
        type: Date,
        required: true
    },
    done:{
        type: Boolean,
        default: false
    },
    type:{
     type: "Whatever you want it to be"
    }
    canceled:{
        type: Boolean,
        default:false
    }`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Ofc you can add or customize that model as you want but keep in mind that &lt;code&gt;time, done, canceled&lt;/code&gt; are the most important parameters in this model. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;second install express and mongodb and node-schedule. &lt;/li&gt;
&lt;li&gt;third make a simple server that starts after connecting to The DB.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;here is a simple configuration for this &lt;/p&gt;

&lt;p&gt;DB.js Config&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mongodb= require('mongodb');
const dbService = {

    db:null,
    connect: async function connection (){
        return new Promise ((resolve,reject)=&amp;gt;{

            mongodb.MongoClient.connect(process.env.MONGODB_URL,{
                useUnifiedTopology:true
            },(err,client)=&amp;gt;{
                if (err){
                    return reject(err);
                }
                this.db = client.db(process.env.DB);
                resolve(true);
            })
        });
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now make a server and end-point to receive job requests, And another one to cancel jobs if you want to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const dbConfig = require('./DB');

dbConfig.connect().then(()=&amp;gt;{
    app.listen(5000,()=&amp;gt;{
        console.log("server is listening on port 5000");
    });
   // re-schedule jobs (that are not Done yet) if the server restarts 
   onServerRestart();

}).catch((e)=&amp;gt;{
    console.log("couldn't connect to database Restart the server");
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;end-point to schedule a job and another to cancel.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;router.post('/',(req,res)=&amp;gt;{

    const job = req.body.job;
    // job is a Document that is created in the main application  
   // and sent to this server to be scheduled 

    scheduleJob(job);
    return res.sendStatus(200);
});

router.get('/cancel',(req,res)=&amp;gt;{
  // job id is sent from the main application
   const jobID = req.query.id;

  // this will be explained later
   Emitter.emit(jobID);
   return res.sendStatus(200);
}


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

&lt;/div&gt;



&lt;p&gt;inside job schedule function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const sched = require("node-schedule");
// this will also be explained later 
const Emitter = require("../Emitter/cutomEmitter");

async function scheduleJob(job){
   const newJob = sched.scheduleJob(job.time,()=&amp;gt;{
      // do the job after a certain amount of time 
      and now this job is in memory 
   });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now, what if you want to cancel the job? &lt;a href="https://www.npmjs.com/package/node-schedule" rel="noopener noreferrer"&gt;node-schedule&lt;/a&gt; gives you a way to do that by calling &lt;code&gt;newJob.cancel()&lt;/code&gt;. But how will you do that from another server? remember this server is just made to schedule jobs. here comes the &lt;a href="https://nodejs.org/api/events.html" rel="noopener noreferrer"&gt;Event Emitter API&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;refactoring the function to cancel jobs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function scheduleJob(job){
   const newJob = sched.scheduleJob(job.time,()=&amp;gt;{
      // do the job after a certain amount of time 
      and now this job is in memory 
   });
   function cancelJob(j){
      j.cancel();
     //access the DB and find Job by ID and cancel it 
        db.db.collection("jobs").updateOne(
            {
                _id: ObjectID(_id),
            },
            {
                $set: {
                    cancelled: true,
                },
            }
    );
   }
// now how the hell are we going to access this function? 
//using emitter -&amp;gt; don't worry i will show u how to configure one 
    Emitter.once(_id, cancelJob);
 // using Emitter.once cause this removes the whole Event which is "_id" -&amp;gt; referring to the job u want to cancel. 
// If the job is executed after a certain amount of "time" then you don't need that event, time to remove it. 
    sched.scheduleJob(job.time,()=&amp;gt;{
         Emitter.removeListener(_id,cancelJob);
   });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;here is the Emitter.js config&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const EventEmitter = require('events');

class jobEmitter extends EventEmitter{}
const Emitter = new jobEmitter();

module.exports = Emitter;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;yes, it is that easy. &lt;/p&gt;

&lt;p&gt;now let's use our CronServer &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Usage&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The scenario is in server 1 you need to schedule a job &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;first, if you are using mongoose just export the Jobs model and &lt;code&gt;jobs.Create({&lt;br&gt;
time: new Date(anytime that you want)&lt;br&gt;
note you might want to add certain parameters here to specify the job &lt;br&gt;
// which I suggest you do&lt;br&gt;
});&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;send a post request to CronServer with the job to be scheduled. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;axios.post("http://localhost:5000/,job,{&lt;br&gt;
 //might want to config that request &lt;br&gt;
});&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;look into your Database to see if the job is scheduled or no. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;time to test the cancellation request.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;axios.get(http://localhost:5000/cancel?id=&amp;lt;jobID&amp;gt;);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Check if the job is canceled or no you should see in the terminal the &lt;code&gt;console.log(job with ${_id} is canceled);&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;try hitting the same request again you won't get anything because the emitter has been removed and the job has been canceled.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Final Notes&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;onServerRestart&lt;/code&gt; function is made to reschedule jobs if anything happened and you need to restart the CronServer just search for the jobs that have (done: false, canceled: false) if the time is less than now Date execute them &lt;strong&gt;IMMEDIATELY&lt;/strong&gt; without re-scheduling, else just re-schedule.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;if you have any questions you can contact me via &lt;a href="//ahmed.magdy.9611@gmail.com"&gt;ahmed.magdy.9611@gmail.com&lt;/a&gt;. Thanks for coming to my TED talk.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>node</category>
      <category>cronjob</category>
    </item>
  </channel>
</rss>
