$setOnInsert

L'operatore $setOnInsert viene utilizzato per impostare i valori di campo solo quando un'operazione upsert comporta l'inserimento di un nuovo documento. Se il documento esiste già e viene aggiornato, l'operatore $setOnInsert non ha alcun effetto. Questo operatore è particolarmente utile per impostare i valori predefiniti o i dati di inizializzazione che devono essere applicati solo durante la creazione di nuovi documenti.

Sintassi

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

Parametri

Parametro Description
field Nome del campo da impostare solo in caso di inserimento. Può essere un campo di primo livello o usare la notazione punto per i campi annidati.
value Valore da assegnare al campo solo quando si inserisce un nuovo documento. Può essere qualsiasi tipo BSON valido.

Esempi

Si consideri questo documento di esempio dalla raccolta negozi.

{
    "_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
                }
            ]
        }
    ]
}

Esempio 1: Utilizzo $setOnInsert di base

Per creare o aggiornare un record dell'archivio, ma impostare solo determinati campi di inizializzazione durante la creazione di un nuovo archivio.

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 }
)

Questa operazione restituisce il risultato seguente.

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

Poiché il documento con _id: "new-store-001" non esiste, questa operazione crea il nuovo documento seguente:

{
  "_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
}

Esempio 2: $setOnInsert con il documento esistente

A questo punto, provare a eseguire di nuovo l'upsert dello stesso documento con valori diversi:

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 }
)

Poiché il documento esiste già, verranno applicate solo le $set operazioni e $setOnInsert verranno ignorate:

{
  "_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
}

Esempio 3: $setOnInsert complessi con oggetti annidati

È possibile usare $setOnInsert per inizializzare strutture annidate complesse:

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 }
)

Esempio 4: Uso di $setOnInsert con matrici

È possibile inizializzare matrici e strutture di dati complesse:

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 }
)

Importante

L'operatore $setOnInsert diventa effettivo solo durante le operazioni upsert ({ upsert: true }).

Se il documento esiste, $setOnInsert i campi vengono completamente ignorati.

$setOnInsert viene comunemente usato con $set per gestire sia gli scenari di aggiornamento che di inserimento in una singola operazione.

È possibile combinare $setOnInsert con altri operatori di aggiornamento, ad $incesempio , e $pushcosì via.

L'operatore $setOnInsert è ideale per impostare timestamp di creazione, valori predefiniti e dati di inizializzazione.