$setOnInsert

Operator $setOnInsert służy do ustawiania wartości pól tylko wtedy, gdy operacja upsert powoduje wstawienie nowego dokumentu. Jeśli dokument już istnieje i jest aktualizowany, $setOnInsert operator nie ma żadnego wpływu. Ten operator jest szczególnie przydatny w przypadku ustawiania wartości domyślnych lub danych inicjowania, które powinny być stosowane tylko podczas tworzenia nowych dokumentów.

Składnia

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

Parametry

Parameter Description
field Nazwa pola do ustawienia tylko podczas wstawiania. Może być polem najwyższego poziomu lub użyć notacji kropkowej dla zagnieżdżonych pól.
value Wartość, która ma zostać przypisana do pola tylko podczas wstawiania nowego dokumentu. Może być dowolnym prawidłowym typem BSON.

Przykłady

Rozważmy ten przykładowy dokument z kolekcji sklepów.

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

Przykład 1. Podstawowe użycie $setOnInsert

Aby utworzyć lub zaktualizować rekord magazynu, ale ustawić tylko niektóre pola inicjowania podczas tworzenia nowego magazynu.

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

Ta operacja zwraca następujący wynik.

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

Ponieważ dokument z _id: "new-store-001" programem nie istnieje, ta operacja tworzy następujący nowy dokument:

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

Przykład 2: $setOnInsert z istniejącym dokumentem

Teraz spróbujmy ponownie przestawić ten sam dokument z różnymi wartościami:

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

Ponieważ dokument już istnieje, zostaną zastosowane tylko $set operacje i $setOnInsert zostaną zignorowane:

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

Przykład 3. Złożone $setOnInsert z zagnieżdżonymi obiektami

Za pomocą $setOnInsert polecenia można zainicjować złożone zagnieżdżone struktury:

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

Przykład 4. Używanie $setOnInsert z tablicami

Można zainicjować tablice i złożone struktury danych:

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

Ważne

Operator $setOnInsert działa tylko podczas operacji upsert ({ upsert: true }).

Jeśli dokument istnieje, $setOnInsert pola są całkowicie ignorowane.

$setOnInsert jest często używany do $set obsługi scenariuszy aktualizacji i wstawiania w ramach jednej operacji.

Można łączyć $setOnInsert się z innymi operatorami aktualizacji, takimi jak $inc, $pushitp.

Operator $setOnInsert jest idealny do ustawiania sygnatur czasowych tworzenia, wartości domyślnych i danych inicjowania.