user874737
user874737

Reputation: 533

MongoDB: How to $set or $inc an object item on an array in a single query?

I need an update query that triggers whenever a user posts something on a channel in Discord. I can't seem to make the $set and $inc work on a single query.

The idea is that if it's a new channelId then it should create a new object in the array. If the channel is already existing in the array of objects, then it increments the message count field of the array that holds the specific channelId. How to do that in a single query? Is it possible?

Here's the query with $set:

db.collection("users").updateOne({userId: userId}, { $set: { messages:[ {channelId: channelId} ] }});

I'm not sure where to place the $inc operator which will increment the correct object.

Here's what it should look like:

  {
    userId: "1",
    messages: [
      {
        channelId: "10000000000",
        messageCount: 10
      },
      {
        channelId: "10000000001",
        messageCount: 24
      }
    ]
  },

If a user sends a message on channel "10000000000" then the messageCount should increment by 1.

Upvotes: 1

Views: 38

Answers (1)

nimrod serok
nimrod serok

Reputation: 16033

One option is to use update with pipeline with $cond:

db.collection.updateOne(
  {userId: userId},
  [{$set: {messages: {$cond: [
          {$in: [channelId, "$messages.channelId"]},
          {$reduce: {
              input: "$messages",
              initialValue: [],
              in: {$concatArrays: [
                  "$$value",
                  {$cond: [
                      {$eq: ["$$this.channelId", channelId]},
                      [{$mergeObjects: [
                            "$$this",
                            {messageCount: {$add: ["$$this.messageCount", 1]}}
                      ]}],
                      ["$$this"]
                  ]}
              ]}
          }},
          {$concatArrays: [
              "$messages",
              [{channelId: channelId, messageCount: 1}]
          ]}
  ]}}}]
)

See how it works on the playground example

Upvotes: 0

Related Questions