2

I want to increment a property value of an object if it does exist inside an array.

Mongo record:

{
    "_id" : ObjectId("5b7bdd9f0465e8345ba83aad"),
    "userID" : "400",
    "userName" : "Jon Snow",
    "pageName" : "1",
    "courseName" : "Maths",
    "socketID" : [
        "aswKWYyE1euk2GNIAAAD"
    ],
    "online" : true,
    "userHistory" : {
        "pagesVisited" : [
            {
                "page" : "1",
                "timesVisited" : 1
            }
        ],
        "coursesVisited" : [
            "Maths"
        ]
    },
    "date" : ISODate("2018-08-21T09:38:39.281Z")
}

Here on userHistory.pagesVisited on the page property if I get the value 1 again then I want to increment the timesVisited property like so:

"pagesVisited" : [
    {
       "page" : "1",
       "timesVisited" : 2
    }
],

Here's what I have tried with no luck:

let userDetails = {
   userID: queryUser.userID,
   userName: queryUser.username,
   pageName: queryUser.pageName,
   courseName: queryUser.courseName,
   socketID: [socket.id],
   online: true,
   userHistory: {
     pagesVisited: [
        {
          "page" : queryUser.pageName,
          "timesVisited" : 1
        }
     ],
     coursesVisited: [queryUser.courseName]
   },
   date: new Date()
};

onlineUsersDB.findOne({'userID': userDetails.userID}).then(async (user) => {
     if (user) {
         let page = {"page": queryUser.pageName, "timesVisited": 1};
         let course = queryUser.courseName;
         let updatedUser = await onlineUsersDB.findOneAndUpdate(
           {'userID': user.userID}, 
           {
             $set: {'online': true}, 
             $push: { 'socketID': socket.id },
           },
           { $addToSet: { 'userHistory.coursesVisited': course } },
           { returnOriginal: false }
         );
         let updatedUserPageRef = updatedUser.value.userHistory.pagesVisited;
         if (updatedUserPageRef) {
           let pageFound = await updatedUserPageRef.findIndex(item => item.page === page);
           if (pageFound >= 0) {
            let updatedUserPage = await onlineUsersDB.findOneAndUpdate(
              {'userID': updatedUser.value.userID},
             // Here I want to reference the variable pageFound
              {$inc: { 'userHistory.pagesVisited.[pageFound].timesVisited': 1 }},
              { returnOriginal: false }
            );
            console.log(JSON.stringify(updatedUserPage,null, 2));
           }
         }
         let users = await onlineUsersDB.find({'online': true}).toArray();
         io.to(room).emit('online-users', users);
         io.to(room).emit('user-back-online', updatedUser);
     } else {
         if (userDetails.userID !== '100') {
            await onlineUsersDB.insert(userDetails);
         }
         let users = await onlineUsersDB.find({'online': true}).toArray();
         io.to(room).emit('online-users', users);
     }
}).catch((e) => console.log(e));

In the above code where my comment is I want to reference the variable pageFound in my object dot notation like so:

{$inc: { 'userHistory.pagesVisited.[pageFound].timesVisited': 1 }}

It works when I give it a hardcoded value like:

{$inc: { 'userHistory.pagesVisited.0.timesVisited': 1 }}

1 Answer 1

3

After experimenting a little bit I made it to work like this:

I broke out my query string into another variable using template literals.

let pageInc = `userHistory.pagesVisited.${pageFound}.timesVisited`;

And then referenced the variable in my query like so:

{$inc: { [pageInc]: 1 }}

And it works now.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.