Q:

Express MongoDB - insert a document but before customize data through another query

My requirement is pretty straightforward -
I want to insert a document in MongoDB database. But before I have to check if the slug already exists in database. Then perform an operation to rename the slug if the slug is already exists.
What I have been trying is to perform an async await callback to check the slug is already exists then insert the document.
mongoClient.connect(function (err, mongoClient) {
    let db = mongoClient.db("articles");

    let category_information = async (db, category_info) => {
        let slug_information = await db.collection('categories').find({slug: category_info.slug});

        slug_information.count((err, count) => {
            if (count > 0) {
                let new_slug = `${category_info.slug}_${new Date().getTime()}`;
                console.log(new_slug);
                return new_slug;
            }
            else
                return category_info.slug;
        })
    };

    let category_promise = category_information(db, category_info);

    category_promise.then(value => {
        console.log(value);
        category_info.slug = value;
    });

    db.collection('categories')
        .insertOne(category_info, (err, data) => {
            assert.equal(null, err);
            res.status(200);
            res.json('success');
        });

    mongoClient.close();
});

In console I get undefined value from Promise. Can you please figure out my code? 
I am new in MongoDB. So also, do you have the solution of the problem in MongoDB way? I mean, can I perform these two queries within a single query?
Thanks! 

A:

You don't need to await find() since it's actually the command coming after, in this case count() that is executing the query.
Next I wonder where and how category_info is defined. It's missing in the code above. But I'll assume you have set it properly in your code.
You must return something from your async function (a promise preferably). Right now you only return from the count-callback. 

With async/await you should be able to:    
const count = await slug_information.count();
if (count > 0) {
    let new_slug = `${category_info.slug}_${new Date().getTime()}`;
    console.log(new_slug);
    return new_slug;
} else {
    return category_info.slug;
}

Basically, if you use a callback like (err, count)=>{..} then you say "I won't be using promises here!", no promise will come and you have nothing to wait for.

Next: category_promise.then(... this bit is async, so you cannot know that it'll resolve before you start your insertOne( query. Actually you can be almost sure it hasn't. 

So you either chain another then: 
category_promise.then(value => {
    console.log(value);
    return category_info.slug = value;
}).then( ()=>{ 
    db.collection('categories')
        .insertOne( ...
});

or just async the whole thing:
const MongoClient = require("mongodb").MongoClient;
const category_info = { slug: "abc" };

async function run(req, res, next) {
  const mongoClient = await MongoClient.connect("mongodb://localhost:27017");
  let db = mongoClient.db("categories");

  // With async/await this is almost superfluous, but lets roll with it.
  let category_information = async (db, category_info) => {
    const count = await db.collection("articles")
      .find({ slug: category_info.slug })
      .count();

    if (count > 0) {
      let new_slug = `${category_info.slug}_${new Date().getTime()}`;
      console.log(new_slug);
      return new_slug;
    } else {
      return category_info.slug;
    }
  };

  category_info.slug = await category_information(db, category_info);
  // note that insertOne() does not return the inserted document.
  let data = await db.collection("categories").insertOne(category_info);

  res.status(200).json(data);

  mongoClient.close();
}

run(); // or app.get("/some-route", run);

This code runs, but I haven' tested every case (count and so on), so grain of salt and all that.

