Search code examples
javascriptmongodbmongoose

If object in array is found, increment value inside, if not push to array


I'm trying to perform an updateOne() query on my db where if an object within an array in the doc, has an _id that matches some value, increment a value within that document, but if there are no matches with that _id, push a new object to the array

Reduced schema:

const userSchema = new Schema({
    _id: String
    counting: [{
        _id: String
        score: Number
    }]    
})
const UserModel = mongoose.model('User', userSchema)

And the attempted, not working, query with example _id's:

const userId:     '5'
const countingId: '2'

await UserModel.updateOne(
    { _id: userId},
    { counting: {
        $cond: { 
            if: { $in: [ countingId, '_id' ] },
            then: { $inc: { 'score': 1 } },
            else: { $push: { _id: countingId, score: 1 } }
        }
    } }
)

If the current db contains a doc of:

{
    _id: 5,
    counting: {
        _id: 2,
        score: 50
    }
}

When the query is done, the doc becomes:

{
    _id: 5,
    counting: {
        score: 0
    }
}

So when the query matches the countingId, it removes the 'counting._id' field and sets the score to 0

If there are no matches with countingId, nothing happens

Can someone please help me understand why this query doesn't work and how I might go about fixing it


Solution

  • I couldn't figure out how to put it into a single query so I've just split it into two separate queries with an if statement

    if ( await User.findOne({ _id: userId, 'counting._id': countingId }) ) {
        await User.updateOne(
            { _id: userId, 'counting._id': countingId },
            { $inc: { 'counting.$.score': 1 } }
    );} else {
        await User.updateOne(
            { _id: userId },
            { $push: { counting: { _id: countingId, score: 1 } } },
            { upsert: true }
    )};