$setOnInsert

只有當 $setOnInsert upsert 作業導致插入新檔時,運算子才會用來設定域值。 如果文件已經存在且正在更新中,運算符 $setOnInsert 就不會有任何作用。 這個運算子特別適用於設定只有在建立新檔時才應套用的預設值或初始化數據。

語法

{
  $setOnInsert: {
    <field1>: <value1>,
    <field2>: <value2>,
    ...
  }
}

參數

參數 Description
field 只在插入時設定的功能變數名稱。 可以是最上層欄位,或使用巢狀欄位的點表示法。
value 只有在插入新檔時,才會指派給欄位的值。 可以是任何有效的 BSON 類型。

範例

請參考商店集合中的此範例檔。

{
    "_id": "0fcc0bf0-ed18-4ab8-b558-9848e18058f4",
    "name": "First Up Consultants | Beverage Shop - Satterfieldmouth",
    "location": {
        "lat": -89.2384,
        "lon": -46.4012
    },
    "staff": {
        "totalStaff": {
            "fullTime": 8,
            "partTime": 20
        }
    },
    "sales": {
        "totalSales": 75670,
        "salesByCategory": [
            {
                "categoryName": "Wine Accessories",
                "totalSales": 34440
            },
            {
                "categoryName": "Bitters",
                "totalSales": 39496
            },
            {
                "categoryName": "Rum",
                "totalSales": 1734
            }
        ]
    },
    "promotionEvents": [
        {
            "eventName": "Unbeatable Bargain Bash",
            "promotionalDates": {
                "startDate": {
                    "Year": 2024,
                    "Month": 6,
                    "Day": 23
                },
                "endDate": {
                    "Year": 2024,
                    "Month": 7,
                    "Day": 2
                }
            },
            "discounts": [
                {
                    "categoryName": "Whiskey",
                    "discountPercentage": 7
                },
                {
                    "categoryName": "Bitters",
                    "discountPercentage": 15
                },
                {
                    "categoryName": "Brandy",
                    "discountPercentage": 8
                },
                {
                    "categoryName": "Sports Drinks",
                    "discountPercentage": 22
                },
                {
                    "categoryName": "Vodka",
                    "discountPercentage": 19
                }
            ]
        },
        {
            "eventName": "Steal of a Deal Days",
            "promotionalDates": {
                "startDate": {
                    "Year": 2024,
                    "Month": 9,
                    "Day": 21
                },
                "endDate": {
                    "Year": 2024,
                    "Month": 9,
                    "Day": 29
                }
            },
            "discounts": [
                {
                    "categoryName": "Organic Wine",
                    "discountPercentage": 19
                },
                {
                    "categoryName": "White Wine",
                    "discountPercentage": 20
                },
                {
                    "categoryName": "Sparkling Wine",
                    "discountPercentage": 19
                },
                {
                    "categoryName": "Whiskey",
                    "discountPercentage": 17
                },
                {
                    "categoryName": "Vodka",
                    "discountPercentage": 23
                }
            ]
        }
    ]
}

範例 1:基本$setOnInsert使用方式

若要建立或更新商店記錄,但僅在建立新商店時設定特定初始化欄位。

db.stores.updateOne(
  { "_id": "new-store-001" },
  {
    $set: {
      "name": "Trey Research Electronics - Downtown",
      "sales.totalSales": 0
    },
    $setOnInsert: {
      "createdDate": new Date(),
      "status": "new",
      "staff.totalStaff.fullTime": 0,
      "staff.totalStaff.partTime": 0,
      "version": 1
    }
  },
  { upsert: true }
)

此作業會傳回下列結果。

{
  acknowledged: true,
  insertedId: 'new-store-001',
  matchedCount: 0,
  modifiedCount: Long("0"),
  upsertedCount: 1
}

由於文件不 _id: "new-store-001" 存在,因此此作業會建立下列新文件:

{
  "_id": "new-store-001",
  "name": "Trey Research Electronics - Downtown",
  "sales": {
    "totalSales": 0
  },
  "createdDate": ISODate("2025-06-05T10:30:00.000Z"),
  "status": "new",
  "staff": {
    "totalStaff": {
      "fullTime": 0,
      "partTime": 0
    }
  },
  "version": 1
}

範例 2:使用現有文件$setOnInsert

現在,讓我們嘗試以不同的值再次插入相同的檔:

db.stores.updateOne(
  { "_id": "new-store-001" },
  {
    $set: {
      "name": "Trey Research Electronics - Downtown Branch",
      "sales.totalSales": 5000
    },
    $setOnInsert: {
      "createdDate": new Date(),
      "status": "updated",
      "staff.totalStaff.fullTime": 10,
      "staff.totalStaff.partTime": 5,
      "version": 2
    }
  },
  { upsert: true }
)

由於文件已經存在,因此只會 $set 套用作業,而且 $setOnInsert 會被忽略:

{
  "_id": "new-store-001",
  "name": "Trey Research Electronics - Downtown Branch",
  "sales": {
    "totalSales": 5000
  },
  "createdDate": ISODate("2025-06-05T10:30:00.000Z"),
  "status": "new",
  "staff": {
    "totalStaff": {
      "fullTime": 0,
      "partTime": 0
    }
  },
  "version": 1
}

範例 3:具有巢狀對象的複雜$setOnInsert

您可以使用 $setOnInsert 來初始化複雜的巢狀結構:

db.stores.updateOne(
  { "name": "Adatum Gaming Paradise - Mall Location" },
  {
    $set: {
      "location.lat": 35.6762,
      "location.lon": 139.6503
    },
    $setOnInsert: {
      "_id": "gaming-store-mall-001",
      "createdDate": new Date(),
      "status": "active",
      "staff": {
        "totalStaff": {
          "fullTime": 8,
          "partTime": 12
        },
        "manager": "Alex Johnson",
        "departments": ["gaming", "accessories", "repairs"]
      },
      "sales": {
        "totalSales": 0,
        "salesByCategory": []
      },
      "operatingHours": {
        "weekdays": "10:00-22:00",
        "weekends": "09:00-23:00"
      },
      "metadata": {
        "version": 1,
        "source": "store-management-system"
      }
    }
  },
  { upsert: true }
)

範例 4:搭配陣列使用$setOnInsert

您可以初始化陣列和複雜的資料結構:

db.stores.updateOne(
  { "address.city": "New Tech City" },
  {
    $set: {
      "name": "Future Electronics Hub",
      "sales.totalSales": 25000
    },
    $setOnInsert: {
      "_id": "future-electronics-001",
      "establishedDate": new Date(),
      "categories": ["electronics", "gadgets", "smart-home"],
      "promotionEvents": [],
      "ratings": {
        average: 0,
        count: 0,
        reviews: []
      },
      "inventory": {
        lastUpdated: new Date(),
        totalItems: 0,
        lowStockAlerts: []
      }
    }
  },
  { upsert: true }
)

這很重要

運算子 $setOnInsert 只會在 upsert 作業 ({ upsert: true }) 期間生效。

如果檔存在, $setOnInsert 則會完全忽略欄位。

$setOnInsert 通常用來 $set 處理單一作業中的更新和插入案例。

您可以與其他更新運算符合並 $setOnInsert ,例如 $inc$push等。

運算子 $setOnInsert 很適合用來設定建立時間戳、預設值和初始化數據。