Search code examples
mongodbmongodb-update

How to update value in array in MongoDB


For example, Documents.

[
  {
    "username": "joy",
    "size_info": [
      {
        "data1": "apple bear cat",
        "data2": 100
      },
      {
        "data1": "dog eat fog good ",
        "data2": 100
      },
      {
        "data1": "hug ill jump",
        "data2": 100
      }
    ]
  }
]

I want to update the document like below.

data3 is the value split by space after getting 2 words from data1.

When I use $substr, I get an error:

can't convert from BSON type array to String

[
  {
    "username": "joy",
    "size_info": [
      {
        "data1": "apple bear cat",
        "data2": 100,
        "data3": "apple bear"
      },
      {
        "data1": "dog eat fog good ",
        "data2": 100,
        "data3": "dog eat"
      },
      {
        "data1": "hug ill jump",
        "data2": 100,
        "data3": "hug ill"
      }
    ]
  }
]

Is it possible? Thank you for helping.


Solution

  • Pre-requisites: Have to update the records with the aggregation pipeline.

    Solution 1: With regex

    1. $set - Set size_info array.

      1.1. $map - Iterate the element in the size_info array and return a new array.

      1.1.1. $mergeObjects - Merge the current iterated document with the result from 1.1.1.1.

      1.1.1.1. A document with data3 field. Get the first capture element from the result with the regex that captures the first two words.

    db.collection.update({},
    [
      {
        $set: {
          size_info: {
            $map: {
              input: "$size_info",
              in: {
                $mergeObjects: [
                  "$$this",
                  {
                    data3: {
                      $first: {
                        $getField: {
                          field: "captures",
                          input: {
                            $regexFind: {
                              input: "$$this.data1",
                              regex: "^([^\\s]* [^\\s]*).*$"
                            }
                          }
                        }
                      }
                    }
                  }
                ]
              }
            }
          }
        }
      }
    ])
    

    Demo Solution 1 @ Mongo Playground


    Solution 2: Get the first N element with $firstN

    Pre-requisites: MongoDB version 5.2

    1. $set - Set size_info array.

      1.1. $map - Iterate the element in the size_info array and return a new array.

      1.1.1. $mergeObjects - Merge the current iterated document with the result from 1.1.1.1.

      1.1.1.1. A document with data3 field. Trim the result returned from $reduce operator which will:

      a. Split the data1 by space into an array. And take the first 2 elements.

      b. Concat the value from the array (result from a) into a string with space.

    db.collection.update({},
    [
      {
        $set: {
          size_info: {
            $map: {
              input: "$size_info",
              in: {
                $mergeObjects: [
                  "$$this",
                  {
                    data3: {
                      $trim: {
                        input: {
                          $reduce: {
                            input: {
                              $firstN: {
                                input: {
                                  $split: [
                                    "$$this.data1",
                                    " "
                                  ]
                                },
                                n: 2
                              }
                            },
                            initialValue: "",
                            in: {
                              $concat: [
                                "$$value",
                                " ",
                                "$$this"
                              ]
                            }
                          }
                        }
                      }
                    }
                  }
                ]
              }
            }
          }
        }
      }
    ])
    

    Demo Solution 2 @ Mongo Playground