insertOne, insertMany — hujjat qo'shish

~15 daq · MongoDB · CRUD

Muammodan boshlaylik

Ma'lumotlar bazasi bor, lekin ichida hech narsa yo'q — foydasiz. Ma'lumot qo'shishdan hamma narsa boshlanadi.

MongoDB da qo'shishning ikki asosiy usuli:

  • insertOne — bitta document
  • insertMany — bir nechta document birdaniga

Farqi faqat sonda emas — natija, xato tutish va ishlash tezligida ham farq bor.


insertOne — bitta document qo'shish

db.talabalar.insertOne({ ism: "Jasur", yosh: 24, shahar: "Toshkent" })

SQL bilan solishtiring:

-- SQL
INSERT INTO talabalar (ism, yosh, shahar)
VALUES ('Jasur', 24, 'Toshkent');
// MongoDB
db.talabalar.insertOne({ ism: "Jasur", yosh: 24, shahar: "Toshkent" })

SQL da ustunlarni oldindan yozish kerak. MongoDB da — faqat document.

insertOne — qaytaradigan natija

let natija = db.talabalar.insertOne({ ism: "Jasur", yosh: 24 })
natija:
{
  acknowledged: true,                              ← yozildi tasdiqlandi
  insertedId: ObjectId("64a1f2c3b4e5f6a7b8c9d0e1") ← yangi _id
}
┌─────────────────────────────────────────────────────────┐
│  acknowledged: true                                     │
│       ↑                                                 │
│  MongoDB ma'lumotni qabul qildi va yozdi.               │
│  false bo'lsa — yozilmagan (writeConcern: 0 holatda)    │
│                                                         │
│  insertedId: ObjectId("64a1f2c3...")                    │
│       ↑                                                 │
│  Qo'shilgan documentning _id si.                        │
│  Keyinchalik bu ID bilan topish mumkin.                 │
└─────────────────────────────────────────────────────────┘

insertedId ni ishlatish

let natija = db.talabalar.insertOne({ ism: "Jasur", yosh: 24 })
let yangiId = natija.insertedId

// Shu ID bilan documentni topish
db.talabalar.findOne({ _id: yangiId })
// → { _id: ObjectId("..."), ism: "Jasur", yosh: 24 }

insertMany — bir nechta document

db.talabalar.insertMany([
  { ism: "Jasur",   yosh: 24, shahar: "Toshkent"  },
  { ism: "Malika",  yosh: 22, shahar: "Samarqand" },
  { ism: "Bobur",   yosh: 25, shahar: "Toshkent"  },
  { ism: "Zulfiya", yosh: 21, shahar: "Namangan"  }
])

SQL bilan solishtiring:

-- SQL
INSERT INTO talabalar (ism, yosh, shahar) VALUES
  ('Jasur',   24, 'Toshkent'),
  ('Malika',  22, 'Samarqand'),
  ('Bobur',   25, 'Toshkent'),
  ('Zulfiya', 21, 'Namangan');

insertMany — qaytaradigan natija

let natija = db.talabalar.insertMany([...])
natija:
{
  acknowledged: true,
  insertedIds: {
    '0': ObjectId("64a1f2c3b4e5f6a7b8c9d0e1"),  ← birinchi
    '1': ObjectId("64a1f2c3b4e5f6a7b8c9d0e2"),  ← ikkinchi
    '2': ObjectId("64a1f2c3b4e5f6a7b8c9d0e3"),  ← uchinchi
    '3': ObjectId("64a1f2c3b4e5f6a7b8c9d0e4")   ← to'rtinchi
  }
}

Kalitlar ('0', '1', ...) — massivdagi indeks. Har element uchun alohida _id yaratildi.


_id ni o'zingiz berish

MongoDB _id ni avtomatik yaratadi, lekin o'zingiz ham berishingiz mumkin:

// Raqam ID bilan
db.kategoriyalar.insertOne({ _id: 1, nom: "Elektronika" })
db.kategoriyalar.insertOne({ _id: 2, nom: "Kiyim" })

// String ID bilan
db.sozlamalar.insertOne({ _id: "mavzu", qiymat: "qorong'u" })
db.sozlamalar.insertOne({ _id: "til", qiymat: "uzbek" })

// Bir nechtasini birdaniga
db.mahsulotlar.insertMany([
  { _id: "KITOB-001", nom: "Clean Code",    narx: 85000 },
  { _id: "KITOB-002", nom: "The Pragmatic", narx: 92000 },
])

Qachon o'z ID berish kerak?

┌─────────────────────────────────────────────────────────────┐
│  ObjectId (default)         │  O'z ID (manual)              │
├─────────────────────────────┼──────────────────────────────┤
│  ✓ Oddiy foydalanuvchi,    │  ✓ Mahsulot kodi (SKU)       │
│    post, buyurtma uchun     │  ✓ Sozlamalar (kalit-qiymat) │
│  ✓ Avtomatik, qulay         │  ✓ Tashqi tizim ID si        │
│  ✓ Timestamp o'z ichida     │  ✓ Tartibli raqamlash kerak  │
└─────────────────────────────┴──────────────────────────────┘

ordered opsiyasi — muhim

insertMany bir nechta document qo'shadi. Ulardan biri xato bo'lsa nima bo'ladi? Bu ordered opsiyasi bilan boshqariladi.

ordered: true (standart)

Tartib:  [Doc1] → [Doc2] → [Doc3-XATO] → [Doc4] → [Doc5]
                                ↓
                          To'xtaydi! Doc4 va Doc5 qo'shilmaydi.
db.talabalar.insertMany([
  { _id: 1, ism: "Jasur" },
  { _id: 2, ism: "Malika" },
  { _id: 2, ism: "Bobur" },   // ← _id: 2 allaqachon bor → xato
  { _id: 3, ism: "Zulfiya" }, // ← qo'shilmaydi (to'xtagan)
  { _id: 4, ism: "Sardor" }   // ← qo'shilmaydi (to'xtagan)
], { ordered: true })

// Natija: 1 va 2 qo'shildi, 3 xato, 4 va 5 qo'shilmadi

ordered: false

Tartib:  [Doc1] → [Doc2] → [Doc3-XATO] → [Doc4] → [Doc5]
                               ↓                ↓        ↓
                          Xato yoziladi   Davom etadi  Qo'shiladi
db.talabalar.insertMany([
  { _id: 1, ism: "Jasur" },
  { _id: 2, ism: "Malika" },
  { _id: 2, ism: "Bobur" },   // ← xato — lekin davom etadi
  { _id: 3, ism: "Zulfiya" }, // ← qo'shiladi
  { _id: 4, ism: "Sardor" }   // ← qo'shiladi
], { ordered: false })

// Natija: 1, 2, 3, 4 qo'shildi; 5 (Bobur) xato

Qachon ordered: false kerak? Katta import operatsiyalarida — ba'zi duplicatlar kutilgan bo'lsa, qolganlarini qo'shishni to'xtatmaslik uchun.


Nested document va array qo'shish

insertOne va insertMany har qanday tuzilishni qabul qiladi:

db.buyurtmalar.insertOne({
  buyurtma_raqam: "ORD-001",
  mijoz: {                            // ← ichma-ich document
    ism:    "Jasur Karimov",
    telefon: "+998901234567"
  },
  mahsulotlar: [                      // ← array of objects
    { nom: "Kitob",  narx: 25000, soni: 2 },
    { nom: "Qalam",  narx: 5000,  soni: 5 },
  ],
  jami:       75000,
  yaratilgan: new Date()
})

Bir nechta insert — tezlik farqi

Nima uchun insertMany bitta insertOne ni ko'p marta chaqirishdan yaxshi?

insertOne × 1000:
┌───────┐  ┌───────┐  ┌───────┐       ┌───────┐
│ Doc 1 │→ │ Doc 2 │→ │ Doc 3 │→ ... →│Doc1000│
└───────┘  └───────┘  └───────┘       └───────┘
1000 ta alohida tarmoq so'rovi
→ ~1000 ms (har biri ~1 ms deb hisoblasak)

insertMany (1000 ta):
┌──────────────────────────────────────────────┐
│ Doc1, Doc2, Doc3, ..., Doc1000               │
└──────────────────────────────────────────────┘
Bitta tarmoq so'rovi
→ ~10-50 ms

Katta ma'lumotlar bilan ishlashda insertMany ancha tezroq. 1000 ta document qo'shish kerak bo'lsa — hammasini bitta insertMany ga bering, 1000 ta insertOne emas.


Amaliy misol — ma'lumotlarni to'ldirish

Maktab bazasini to'ldirish:

use maktab

// Fanlar
db.fanlar.insertMany([
  { _id: 1, nom: "Matematika", haftalik_soat: 5 },
  { _id: 2, nom: "Fizika",     haftalik_soat: 4 },
  { _id: 3, nom: "Kimyo",      haftalik_soat: 3 },
  { _id: 4, nom: "Biologiya",  haftalik_soat: 3 },
])

// O'qituvchilar
db.o_qituvchilar.insertMany([
  { ism: "Kamolov A.",  fan_id: 1, tajriba: 12 },
  { ism: "Yusupova B.", fan_id: 2, tajriba: 8  },
  { ism: "Rahimov C.",  fan_id: 3, tajriba: 15 },
])

// Talabalar
db.talabalar.insertMany([
  { ism: "Jasur",   yosh: 16, sinf: "10A", baholar: { mat: 90, fiz: 85 } },
  { ism: "Malika",  yosh: 17, sinf: "11B", baholar: { mat: 95, kim: 88 } },
  { ism: "Bobur",   yosh: 16, sinf: "10A", baholar: { mat: 78, fiz: 92 } },
  { ism: "Zulfiya", yosh: 15, sinf: "9C",  baholar: { bio: 96, kim: 91 } },
])

Tez-tez uchraydigan xatolar

E11000 — duplicate key

db.talabalar.insertOne({ _id: 1, ism: "Jasur" })
db.talabalar.insertOne({ _id: 1, ism: "Malika" })
// ❌ MongoServerError: E11000 duplicate key error
//    collection: maktab.talabalar index: _id_ dup key: { _id: 1 }

Sabab: _id: 1 allaqachon bor. Har document unikal _id ga ega bo'lishi shart. Siz _id bermasangiz, MongoDB ObjectId yaratadi — bu muammo bo'lmaydi. O'zingiz berayotgan bo'lsangiz, unikal ekanligiga ishonch hosil qiling.

insertMany da xato tutish

try {
  db.talabalar.insertMany([
    { ism: "Jasur" },
    { _id: "bor", ism: "Malika" },  // bu ID allaqachon bor
    { ism: "Bobur" }
  ])
} catch (e) {
  console.log("Xato:", e.message)
  // ordered: true bo'lganda — "bor" ID da to'xtaydi, Bobur qo'shilmaydi
  // ordered: false bo'lganda — Jasur va Bobur qo'shiladi, faqat Malika xato
}

Katta massiv

// ❌ — 100 000 ta bitta so'rovda
db.logs.insertMany(barcha100000ta)

// ✅ — 1000 tadan bo'lib yuborish
for (let i = 0; i < barcha.length; i += 1000) {
  db.logs.insertMany(barcha.slice(i, i + 1000))
}

JSON formatida xato

// ❌ Xato — vergul unutilgan
db.users.insertOne({
  ism: "Jasur"
  yosh: 24        // ← vergul yo'q → SyntaxError
})

// ✅ To'g'ri
db.users.insertOne({
  ism: "Jasur",   // ← vergul bor
  yosh: 24
})

Mongosh da SyntaxError darhol ko'rinadi — document bajarilmaydi.


Xulosa

┌──────────────────┬────────────────────────────────────────┐
│  insertOne({})   │  Bitta document, insertedId qaytaradi  │
│  insertMany([])  │  Ko'p document, insertedIds qaytaradi  │
├──────────────────┼────────────────────────────────────────┤
│  ordered: true   │  Xatoda to'xtaydi (standart)           │
│  ordered: false  │  Xatoni yozib, davom etadi             │
├──────────────────┼────────────────────────────────────────┤
│  _id             │  Avtomatik ObjectId yoki o'zingiz      │
│  Performance     │  insertMany >>> 1000 × insertOne       │
└──────────────────┴────────────────────────────────────────┘
  • Bitta document: insertOne — insertedId bilan qaytadi
  • Ko'p document: insertMany — insertedIds ob'ekti bilan qaytadi
  • Katta import: 500-1000 li bo'laklarga bo'ling
  • Duplicate _id → E11000 xatosi

Keyingi dars: 7-dars — find, findOne: filter, projection, sort, limit, skip