DevWannabe
DevWannabe

Reputation: 117

NodeJS create a function that returns document from MongoDB

I'm not sure if this is possible but I am using NodeJS and I'm trying to create a function that would return a document from MongoDB. My code currently looks like this but returns undefined:

const GetUser = (userId) => {
    let userData
    
    User.aggregate([
        { $match: {_id: mongoose.Types.ObjectId(userId)} },
        { 
             $project: {
                  "_id": 0,
                  "originId": 1,
                  "type": 1,
                  "poster": 1,
                  "content": 1,
                  "createdAt": 1,
                  "updatedAt" : 1
             }
        }
    ]).exec((err, res) => {
        if(err) {
            return err
        }
        else {
            userData = res
        }
    })

    return userData
}

Upvotes: 0

Views: 234

Answers (3)

ippi
ippi

Reputation: 10167

@Ifaruki's solution is correct. But just to visualize your problem:

const GetUser = (userId) => {
  let userData 
  
  // This will start the aggregation, but...
  User.aggregate( ... ).exec((err, res) => {
      // The callback will run sometime in the future.
      userData = res

      // Even if you could return something here, it's too late,
      // the parent function's return has already happened
  })
  
  // here "userData = res"  has not happened yet. It's still undefined.
  return userData
}

The best you can get is to return a promise.

Upvotes: 1

Ilijanovic
Ilijanovic

Reputation: 14904

You could do it like this. You just return your aggregation query it returns an promise.

const GetUser = userId => {
  let userData;
  return User.aggregate([
    { $match: { _id: mongoose.Types.ObjectId(userId) } },
    {
      $project: {
        _id: 0,
        originId: 1,
        type: 1,
        poster: 1,
        content: 1,
        createdAt: 1,
        updatedAt: 1
      }
    }
  ]);
};

I am not sure if you need the .exec() here but however you can try it with and without.

Later you can use your function like this:

Because its an promise, you can use .then() on it:

GetUser(id).then(response => {
   console.log(response)
})

or if you use it in an async function :

let user = await GetUser(id);
console.log(user);

Upvotes: 1

r7r
r7r

Reputation: 1525

You must have return userData inside else below userData = res,

exec is asynchronous so before it gets executed your function returns.

    const GetUser = (userId) => {
    let userData
    
    User.aggregate([
        { $match: {_id: mongoose.Types.ObjectId(userId)} },
        { 
             $project: {
                  "_id": 0,
                  "originId": 1,
                  "type": 1,
                  "poster": 1,
                  "content": 1,
                  "createdAt": 1,
                  "updatedAt" : 1
             }
        }
    ]).exec((err, res) => {
        if(err) {
            return err
        }
        else {
            userData = res
            return userData
        }
    })
}

caveat:- I am believing your database has a value that your query returns data for.

Upvotes: 0

Related Questions