Как изменить значение в массиве по позиции в структуре агрегации - PullRequest
1 голос
/ 13 февраля 2020

Допустим, у нас есть простой документ:

{
   array: ["a", "b", "c", "d"]
}

Как изменить значение second в агрегации ?

С update это очень просто:

db.collection.updateOne({},
   { $set: { "array.1": "B" } }
)

дает:

{
   array: ["a", "B", "c", "d"]
}

В структуре агрегации вы можете использовать это:

db.collection.aggregate([
   {
      $set: {
         "array": {
            $map: {
               input: "$array",
               in: {
                  $cond: {
                     if: { $eq: [{ $indexOfArray: ["$array", "$$this"] }, 1] },
                     then: "B",
                     else: "$$this"
                  }
               }
            }
         }
      }
   }
])

Однако это не удается, когда массив не является множеством, то есть значения не являются уникальными, как этот

{
   array: ["a", "b", "c", "b"]
}

Ответы [ 2 ]

1 голос
/ 13 февраля 2020

Другое решение состоит в том, чтобы $ разматывать ваш массив с помощью includeArrayIndex и preserveNullAndEmptyArrays, устанавливать значение с условием, а затем группировать. Но будьте осторожны, хотя это может быть полезно в некоторых ситуациях, в некоторых случаях оно может потреблять больше ресурсов сервера.

db.collection.aggregate([
  {
    $unwind: {
      path: "$array",
      includeArrayIndex: "index",
      preserveNullAndEmptyArrays: true
    }
  },
  {
    $addFields: {
      array: {
        $cond: {
          if: {
            $eq: [
              "$index",
              1
            ]
          },
          then: "B",
          else: "$array"
        }
      }
    }
  },
  {
    $group: {
      _id: "$_id",
      array: {
        $push: "$array"
      }
    }
  }
])

вы можете проверить здесь

1 голос
/ 13 февраля 2020

Вы можете l oop над $size (длиной) массива, используя $range, а затем получить индекс элемента и может изменить значение элемента индекса на любое значение.

db.collection.aggregate([
  { "$project": {
    "array": {
      "$map": {
        "input": { "$range": [0, { "$size": "$array" }] },
        "in": {
          "$cond": [
            { "$eq": ["$$this", 1] },
            "B",
            { "$arrayElemAt": ["$array", "$$this"] }
          ]
        }
      }
    }
  }}
])

MongoPlayground

...