skip to Main Content

I have this document and i need remove only 3 items with name "Test" using only 1 request.
{ "_id" : 1, "items" : ["Test, "Test", "Test", "Test", "Test", "Sword", "Sword]}

It must become { "_id" : 1, "items" : ["Test", "Test", "Sword", "Sword]} after request.

2

Answers


  1. Maybe something like this:

    db.collection.aggregate([
    {
      "$unwind": "$items"
    },
    {
     $group: {
      _id: "$items",
      cnt: {
        $sum: 1
      },
      it: {
        $push: "$items"
      },
      origid: {
        "$first": "$_id"
        }
      }
     },
     {
      $project: {
      _id: "$origid",
      items: {
        $slice: [
          "$it",
          0,
          2
         ]
       }
      }
     },
     {
      $group: {
      _id: "$_id",
      items: {
         $push: "$items"
        }
      }
    },
    {
    $addFields: {
      items: {
        "$reduce": {
          "input": "$items",
          "initialValue": [],
          "in": {
            "$concatArrays": [
              "$$this",
              "$$value"
              ]
            }
          }
        }
       }
      }
    ])
    

    Explained:

    1. unwind the items array so you can group after
    2. group by item so you get the repeating values
    3. project with slice to remove more then 2x items in array
    4. group to form back the document but without the >2 repeating values
    5. project with concatArrays to concat arrays of items.

    Playground

    Login or Signup to reply.
  2. You can use this aggregation to get the desired result. The query uses the $reduce Aggregate Array Operator to iterate over the items array, and discards the first 3 matching "Test" items.

    db.collection.aggregate([
    { 
        $set: {
            items: {
                $reduce: { 
                    input: "$items", 
                    initialValue: { result: [], count: 0 }, 
                    in: {
                        $cond: [ { $and: [ { $eq: [ "$$this", "Test" ] }, { $lt: [ "$$value.count", 3 ] } ] },
                            { result: "$$value.result", count: { $add: [ "$$value.count", 1 ] } },
                            { result: { $concatArrays: [ "$$value.result", [ "$$this" ] ] }, count: "$$value.count" }
                        ]
                    }
                }
            }
        }
    },
    {
        $set: {
            items: "$items.result"
        }
    }
    ])
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search