Bu makalemizde, Node.JS ile Mongoose modülünü kullanarak bir önceki makalemizde kurduğumuz popüler NoSQL veritabanı sistemlerinden biri olan MongoDB'ye bağlanıp, veritabanı işlemlerini nasıl gerçekleştirebileceğimizi inceleyeceğiz.

Biraz uzun bir makale olacak ama sonuna kadar sabredebilirsen, buna değmesi için elimden geleni yaptım inşallah. Makaleye başlamadan önce, MongoDB ve NoSQL kavramlarına henüz aşina olmayanlar için "ufak" bir ön bilgilendirme kutucuğuyla işe başlayalım.














MongoDB ve NoSQL Hakkında

Yukarıdaki iki kelimeyi zaten biliyor ve hakimsen, bu kutuyu atla, boşuna vakit kaybetme. Ama eğer ki ilk defa duyuyor veya henüz denemediysen, muhtemelen programcılık anlayışında köklü değişikliklere sebep olacak bir dönüm noktasında duruyorsun. Bu anı bir yere not et, çünkü bir daha asla eskisi gibi olamayacaksın.

Çok mu abarttım? Sanmıyorum. Dinle.

Normalde MSSQL, MySQL, Oracle ve Postgresql gibi veritabanları, RDBMS (Relational database management system) olarak geçer. Bu tarz sistemler, birbiri ile ilişkili tablolardan oluşur. Örneğin bir cari hesaplar tablosu ve her cari hesabın cari işlemlerinin tutulduğu bir detay tablosu gibi. Bu iki tablo birbirine CariHesapKodu sütunu üzerinden PrimaryKey - ForeignKey eşleşmesi ile bağlanır. Detayını anlatmıyorum, zaten biliyorsundur.

Bu tarz sistemlerde tablolarımız sütunlardan oluşur ve her tablonun belirli bir yapısı vardır. Sütunlara Nullable özelliği ekleyebiliriz ve böylece bazı sütunlara değer atamak zorunda kalmayız ama tabloların yapıları yine de bellidir.

Gelelim NoSQL'lere. Aslında bunlar kendi aralarında kategorilere ayrılırlar ve her kategorinin kendine has bir kullanım alanı vardır. Bizim bu makaleye konu olan MongoDB, Document Database olarak geçer.

Bu veritabanlarında tablo yok, sütun yok, foreign key yok. Aslında bunlar tam bir emanet kasasına benzer. Elimizde alt alta geçmiş pek çok alt nesnesi olan kompleks bir nesnemizin olduğunu düşünelim. Biz bu nesneyi MongoDB'ye veririz, al bunu kaydet deriz, o da kaydeder. Daha sonradan geri ver deriz, aynen aldığı gibi nesne şeklinde geri verir. Çünkü verdiğimiz nesneleri, RDBMS'deki ORM'lerin yaptığı gibi tablolarla eşleştirmeye çalışmaz. Verilen nesneyi JSON Serialize eder ve BSON (Binary JSON) formatında kayıt altında tutar.

Hatta diyelim ki yukarıdaki örnekteki gibi CariHesaplar isimli bir nesnemiz olsun. Bu nesnenin AdiSoyadi gibi değişkenleri, hatta CariIslemler gibi bir de alt nesnel dizisi de olsun. Bu tarz nesnelerden, cari hesap adedince farklı nesneyi MongoDB'ye veririz, hepsini ayrı ayrı kaydeder. Sonra gideriz, bambaşka yapıdaki, örneğin Banka ve BankaIslemleri nesnelerini de kaydet deriz, bunları da kaydeder. Son olarak deriz ki, bize tipi CariHesaplar olup, AdiSoyadi değişkeninin değeri "Ali" olan veya içindeki CariIslemler dizisinin tutar alanının toplamı 100'den büyük olan nesneleri getir deriz, MongoDB bu nesneleri sanki Select çekiyormuş gibi bulur ve getirir. Üstelik RDBMS'lerin ulaşamayacağı kadar yüksek bir süratte getirir.

Yani özetle şunu düşün; Öyle bir dünyada yaşıyorsun ki, bellekteki nesnelerin program, hatta bilgisayar kapansa bile yok olmuyor. Bu veritabanları, nesneleri kalıcı hale getirmemizi sağlıyor. Böyle bir durumda programın mimari tasarımı ne kadar değişirdi?

Evet, baştan aşağı değişirdi. Artık CariHesaplar adında bir nesnemiz, bu cari hesaba ait tüm çekler, senetler ve cari işlemler de bu nesnenin alt nesneleri olurdu. Bana şu cari hesabı getir derdik, bunlar komple gelirdi. 1-1, 1-n veya n-n relation diye bir derdimiz olmazdı. Hatta veritabanı diye bir derdimiz de olmazdı. Bu aletler bizim için sadece nesneleri kalıcı hale getiren birer emanet kasası olurdu.

Aslında tüm bu anlattıklarım, DDD (Domain Driven Design)'daki  Aggregate yapısına çok uyuyor. Burada tek seferde tüm bir Aggregate'i kaydetme ve geri getirme imkanına kavuşuyoruz ve bu, modern programlama mantığına kesinlikle çok yakışıyor.

Bu arada tüm bu yazdıklarımdan sonra, MongoDB'nin Open Source ve Cross platform olduğunu söylememe gerek yoktur sanırım.

İnşallah NoSQL veritabanı sistemleri hakkında ilgini çekmeyi başarabilmişimdir. Şahsen ben bunlarla tanıştıktan sonra, yaptığım mimari tasarımlar da ciddi anlamda değişti. Piyasada farklı amaçlara hizmet eden pek çok NoSQL veritabanı sistemi olmasının yanında, bunlardan en popüler olanı MongoDB'dir ve genel olarak hemen her ihtiyacımıza karşılık verebilir.


Node.JS ile MongoDB'ye ulaşmak için birden fazla modül ve yöntem var. Ancak aralarında en çok popüler olan modül Mongoose modülüdür ki, makalemiz de bu modül hakkında olacak inşallah.



Bu modülü kullanmak için, ilk olarak masaüstüne "MongoDBTest" isimli bir klasör açıp içerisine "package.json" dosyasını aşağıdaki gibi hazırlayalım.
{
    "name": "MongoDBTest",
    "version": "1.0.0",
    "dependencies": {
        "mongoose": "3.8.0"
    }
}


Ardından, asıl kodumuzu içeren "program.js" dosyamızı aşağıdaki gibi hazırlayalım.
"use strict";

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/testdb');


var Schema = mongoose.Schema;

var currentAccountSchema = new Schema({
    currentAccountId: Number,
    nameSurname: String,
    contactInfo: {
        phoneNumber: Number,
        faxNumber: Number,
        emailAddress: String
    },
    operations: [{
            operationId: Number,
            operationType: String,
            date: {
                type: Date
            },
            amount: Number
    }]
});


var CurrentAccount = mongoose.model('CurrentAccount', currentAccountSchema);


var currentAccount1 = new CurrentAccount();

currentAccount1.currentAccountId = 1234;
currentAccount1.nameSurname = "Ali";

currentAccount1.contactInfo.phoneNumber = 1234;
currentAccount1.contactInfo.faxNumber = 5678;
currentAccount1.contactInfo.emailAddress = "aa@bb.net";

currentAccount1.operations.push({
    operationId: 1,
    operationType: "Para Girişi",
    date: new Date(),
    amount: 250
});

currentAccount1.operations.push({
    operationId: 2,
    operationType: "Para Çıkışı",
    date: new Date(),
    amount: 100
});


currentAccount1.save(function (ex) {
    if (ex) {
        console.log(ex);
    } else {
        console.log("Tamam");
    }
});

Kodu çalıştırmaya geçmeden önce biraz inceleyelim. İlk baştaki "require" satırını anlatmıyorum zaten, modülleri kullanmak için sürekli kullanıyoruz.


mongoose.connect('mongodb://localhost/testdb');

Bu satır ise, localhost üzerinde kurulu olan MongoDB veritabanı sunucusuna ve bunun üzerinde bulunan "testdb" isimli bir veritabanına bağlanıyor.

Not : Şu anda "testdb" isimli bir veritabanının olmadığına dikkatini çekerim.


var Schema = mongoose.Schema;
var currentAccountSchema = new Schema({
    currentAccountId: Number,
    nameSurname: String,
    contactInfo: {
        phoneNumber: Number,
        faxNumber: Number,
        emailAddress: String
    },
    operations: [{
            operationId: Number,
            operationType: String,
            date: {
                type: Date
            },
            amount: Number
    }]
});

Burada, kayıt altında tutmak istediğimiz nesnenin yapısını belirtiyoruz. Tanımlama JSON'a çok benziyor. Sütun isimleri ve tiplerini belirtiyoruz. Burada asıl nesnemizin altında "contactInfo" isimli bir alt nesnenin, yine "operations" isimli bir nesne dizisinin olduğuna dikkatini çekmek istiyorum.

Yani diyoruz ki, bizim bir nesnemiz var. Bunun "currentAccountId" ve "nameSurname" diye iki alt değişkeni var. Ayrıca "contactInfo" adında bir alt nesnesi var ki, bu da kendi altında "phoneNumber", "faxNumber" ve "emailAddress" adında üç değişken barındıracak. Bir de asıl nesnemiz altında "operations" isminde bir dizi olacak. Bu dizinin her bir elemanı da bir nesne olacak ve bu nesne kendi altında, "operationId", "operationType", "date" ve "amount" isimli değişkenler barındıracak (Bunun dizi olduğunu [] işaretleri ile anlatıyoruz).

Not : Normalde böyle bir nesneyi RDBMS bir sistemde tutmak isteseydik, "CariHesaplar" isimli bir tablomuz, buna 1-1 bağlı "IletisimBilgileri" isimli bir tablomuz, "CariHesaplar" tablosuna 1-n bağlı "CariIslemler" isimli bir tablomuz olmak üzere, toplamda 3 tabloya ihtiyacımız olurdu.

Mongoose ile birlikte kullanabileceğimiz veri tiplerini şu şekilde sıralayabiliriz.
  • String
  • Number
  • Date
  • Buffer
  • Boolean
  • Mixed
  • Objectid
  • Array

var CurrentAccount = mongoose.model('CurrentAccount', currentAccountSchema);

Burada, tanımladığımız şemadan bir model oluşturuyoruz. Artık bu modelden nesneler türeterek kullanabiliriz. Ki nitekim, aşağıda da bunu yapıyoruz.


var currentAccount1 = new CurrentAccount();
currentAccount1.currentAccountId = 1234;
currentAccount1.nameSurname = "Ali";
currentAccount1.contactInfo.phoneNumber = 1234;
currentAccount1.contactInfo.faxNumber = 5678;
currentAccount1.contactInfo.emailAddress = "aa@bb.net";
currentAccount1.operations.push({
    operationId: 1,
    operationType: "Para Girişi",
    date: new Date(),
    amount: 250
});
currentAccount1.operations.push({
    operationId: 2,
    operationType: "Para Çıkışı",
    date: new Date(),
    amount: 100
});

Burada, modelimizden türettiğimiz nesnemizi dolduruyoruz. Nesnemizdeki cari işlemler dizisine de iki adet cari işlem ekliyoruz.


currentAccount1.save(function (ex) {
    if (ex) {
        console.log(ex);
    }
    else {
        console.log("Tamam");
    }
});

Son olarak, nesnemizin "save" fonksiyonunu çağırarak MongoDB'ye kaydedilmesini sağlıyoruz. İşlem tamamlandığında callback fonksiyonumuz çağırılacak ve eğer hata oluşursa "ex" nesnemiz null olmayıp içeriği ekrana yazılacak. Aksi takdirde ekrana "Tamam" yazılacak.


Haydi bakalım, bir de şu arkadaşı iş başında görelim. İlk olarak gerekli modülü indirmek için terminal (Linux veya Mac OS) veya command prompt (Windows) penceresinden "MongoDBTest" isimli klasöre girip aşağıdaki komutu çalıştıralım.

npm install

Böylece Mongoose için gerekli olan dosyalar inmiş olacak. Ardından aşağıdaki komutla uygulamamızı ayağa kaldıralım.

node program.js

Eğer her şey yolunda gittiyse, ekranda "Tamam" yazıyor olması lazım. Ama nasıl tamam? Şunu bir de gözle görelim bakalım. Geçen makalemizde kurduğumuz "Robomongo" isimli uygulamamızı açıp MongoDB'ye bağlanalım. Aşağıdaki gibi bir görüntü ile karşılaşmış olman lazım.


MongoDB bizim için "testdb" adında bir veritabanı oluşturmuş. Ardından "Collections" altında "currentaccounts" adında da bir koleksiyon oluşturmuş. Bu iyi haber. Şimdi bu "currentaccounts" koleksiyonuna çift tıklayalım. Bu durumda sağ tarafta koleksiyonun içeriği aşağıdaki gibi gözükecektir.


Görünüşe göre kaydı yapmış. Bir miktar veri okunuyor ama özellikle alt nesneler pek gözükmüyor. Bu pencerenin en sağında, üç adet düğme göreceksin. Varsayılan olarak birinci düğme seçilidir ve veriyi ağaç şeklinde gösterir. İkinci düğme, tablo yapısına alışkın olanlar için grid şeklinde gösterim yapar. Son düğme ise, ki aralarında en kullanışlı olanıdır, veriyi JSON formatında gösterir. Bu düğmeye tıklarsan, verinin tamamını aşağıdaki gibi görebiliyor olman lazım.



Harika, değil mi? Bütün nesneyi JSON Serialize edip tek seferde kaydetmiş.

Haydi, bu veriyi yalnız bırakmayalım ve yanına bir arkadaş gönderelim. "program.js" dosyamızı aşağıdaki gibi değiştirip uygulamamızı tekrar çalıştıralım.
"use strict";

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/testdb');


var Schema = mongoose.Schema;

var currentAccountSchema = new Schema({
    currentAccountId: Number,
    nameSurname: String,
    contactInfo: {
        phoneNumber: Number,
        faxNumber: Number,
        emailAddress: String
    },
    operations: [{
            operationId: Number,
            operationType: String,
            date: {
                type: Date
            },
            amount: Number
    }]
});


var CurrentAccount = mongoose.model('CurrentAccount', currentAccountSchema);


var currentAccount1 = new CurrentAccount();

currentAccount1.currentAccountId = 5678;
currentAccount1.nameSurname = "Veli";

currentAccount1.contactInfo.phoneNumber = 5555;
currentAccount1.contactInfo.faxNumber = 6666;
currentAccount1.contactInfo.emailAddress = "cc@dd.net";

currentAccount1.operations.push({
    operationId: 1,
    operationType: "Para Girişi",
    date: new Date(),
    amount: 500
});

currentAccount1.save(function (ex) {
    if (ex) {
        console.log(ex);
    } else {
        console.log("Tamam");
    }
});

Yine "Tamam" yazısını gördüysek, hemen Robomongo'yu refresh edip (Yukarıdaki yeşil Play butonu) teyit edelim. Bu sefer aşağıdaki gibi bir ekranla karşılaşmış olman gerekiyor.


Gördüğün üzere ikinci nesne de kaydedilmiş. Yani aynı koleksiyondaki iki nesneyi, birbirine karıştırmadan tutabiliyor.

Peki, şimdi de farklı bir yapıdaki nesneyi kaydetmeye çalışalım. Örneğin banka ve alt nesnesi olarak banka işlemleri. "program.js" dosyamızı aşağıdaki gibi değiştirip uygulamamızı tekrar çalıştıralım.
"use strict";

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/testdb');


var Schema = mongoose.Schema;

var bankSchema = new Schema({
    bankId: Number,
    description: String,
    operations: [{
            operationId: Number,
            operationType: String,
            date: {
                type: Date
            },
            amount: Number,
            receiptNo: Number
    }]
});


var Bank = mongoose.model('Bank', bankSchema);


var bank1 = new Bank();

bank1.bankId = 123;
bank1.description = "X Bankası";

bank1.operations.push({
    operationId: 1,
    operationType: "Para Girişi",
    date: new Date(),
    amount: 1500,
    receiptNo: 1234
});

bank1.save(function (ex) {
    if (ex) {
        console.log(ex);
    } else {
        console.log("Tamam");
    }
});

"Tamam" yazısını gördüysek, hemen Robomongo'nun sol tarafındaki ağacı refresh edip teyit edelim. Bu sefer aşağıdaki gibi bir ekranla karşılaşmış olman gerekiyor.


Gördüğün üzere, farklı yapıdaki bir nesne geldiğinde, onun için ayrı bir koleksiyon oluşturdu ve koleksiyonları birbirine karıştırmadı. Yani diyebiliriz ki, RDBMS'de tablo neyse, burada da koleksiyonlar odur. Ama elbette çok daha fazla esneklikle birlikte.

Böylece "currentaccounts" koleksiyonunda 2, "banks" koleksiyonunda da kayıtlı 1 nesnemiz oldu. Kaydetmeye alışmışızdır herhalde. Haydi, şimdi de bunları geri isteyelim. "program.js" dosyamızı aşağıdaki gibi değiştirelim.
"use strict";

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/testdb');


var Schema = mongoose.Schema;

var currentAccountSchema = new Schema({
    currentAccountId: Number,
    nameSurname: String,
    contactInfo: {
        phoneNumber: Number,
        faxNumber: Number,
        emailAddress: String
    },
    operations: [{
            operationId: Number,
            operationType: String,
            date: {
                type: Date
            },
            amount: Number
    }]
});


var CurrentAccount = mongoose.model('CurrentAccount', currentAccountSchema);


CurrentAccount.find(function (ex, currentAccounts) {

    if (ex) {
        console.log(ex);
    } else {

        for (var i = 0; i < currentAccounts.length; i++) {
            console.log(currentAccounts[i].nameSurname);
            console.log(currentAccounts[i].contactInfo.emailAddress);
            console.log(currentAccounts[i].operations[0].amount);
            console.log("------------------------------------------");
        }
    }
});

Çalıştırmadan önce değişikliklere bir göz atalım. Yine şema ve model tanımlarımız duruyor (Zaten bu tanımlamalar, yazdığımız programda daha merkezi bir yerde duruyor olmalı). Ancak bu sefer modelden bir nesne türetmiyoruz. Çünkü ihtiyacımız olan nesne veritabanında duruyor ve bizim isteğimiz de onu geri almak. bunun için aşağıdaki kod bloğundan faydalanıyoruz.


CurrentAccount.find(function (ex, currentAccounts) {
    if (ex) {
        console.log(ex);
    } else {
        for (var i = 0; i < currentAccounts.length; i++) {
            console.log(currentAccounts[i].nameSurname);
            console.log(currentAccounts[i].contactInfo.emailAddress);
            console.log(currentAccounts[i].operations[0].amount);
            console.log("------------------------------------------");
        }
    }
});

Burada "CurrentAccount" modelimizin "find" fonksiyonunu çağırıyoruz. Bu fonksiyon, belirtilen modele ait veritabanındaki koleksiyonda bulunan tüm nesneleri çekiyor ve callback fonksiyonunun ikinci parametresi olan "currentAccounts" parametresine geçiyor. Eğer işlem sırasında bir hata olursa da, ilk parametre olan "ex" parametresini dolduruyor.

Örneği çok uzatmamak adına, gelen "currentAccounts" dizisinde dönerek nesnelerin sadece "nameSurname", "contactInfo" alt nesnesindeki "emailAddress" ve "operations" dizisinin ilk elemanının "amount" değerini ekrana yazdırdım. Uygulamayı çalıştırdığında aşağıdaki gibi bir ekranla karşılaşmış olman gerekiyor.



Gördüğün gibi verdiğimiz nesneler aynen geri geldi. Demek ki tam bir emanet ehliymiş. MongoDB müslüman olmalı.

Ehh, verilen tüm nesneleri herkes getirir. Bir de spesifik bir nesneyi isteyelim bakalım. "program.js" dosyamızı aşağıdaki gibi değiştirelim.
"use strict";

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/testdb');


var Schema = mongoose.Schema;

var currentAccountSchema = new Schema({
    currentAccountId: Number,
    nameSurname: String,
    contactInfo: {
        phoneNumber: Number,
        faxNumber: Number,
        emailAddress: String
    },
    operations: [{
            operationId: Number,
            operationType: String,
            date: {
                type: Date
            },
            amount: Number
    }]
});


var CurrentAccount = mongoose.model('CurrentAccount', currentAccountSchema);


CurrentAccount.find({ nameSurname: "Ali" },
                    function (ex, currentAccounts) {
    if (ex) {
        console.log(ex);
    } else {

        for (var i = 0; i < currentAccounts.length; i++) {
            console.log(currentAccounts[i].nameSurname);
            console.log(currentAccounts[i].contactInfo.emailAddress);
            console.log(currentAccounts[i].operations[0].amount);
            console.log("------------------------------------------");
        }
    }
});

Dikkat edersen, burada tek değişen, "find" fonksiyonuna opsiyonel olan ilk parametreyi geçmemiz oldu. Opsiyonel olan bu ilk parametre, SQL'deki Where yerine geçiyor. Ancak yazımı biraz daha farklı. İnşallah birkaç örnek sonra alışmaya başlarsın. Buradaki örnekte, "nameSurname" değeri "Ali" olan nesneleri getir dedik. Uygulamayı çalıştırdığında aşağıdaki gibi bir ekranla karşılaşmış olman gerekiyor.


Gördüğün gibi diziye tek bir eleman doldurdu. Yani aletin Where çekme yeteneği de var. "Böyle Where'i ninem de çeker" diyenler için iki örnek daha yapalım. Öncelikle "program.js" dosyamızı aşağıdaki gibi değiştirelim.
"use strict";

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/testdb');


var Schema = mongoose.Schema;

var currentAccountSchema = new Schema({
    currentAccountId: Number,
    nameSurname: String,
    contactInfo: {
        phoneNumber: Number,
        faxNumber: Number,
        emailAddress: String
    },
    operations: [{
            operationId: Number,
            operationType: String,
            date: {
                type: Date
            },
            amount: Number
    }]
});


var CurrentAccount = mongoose.model('CurrentAccount', currentAccountSchema);


CurrentAccount.find({ nameSurname: /li/, currentAccountId: { $gte: 2000 } },
                    function (ex, currentAccounts) {
    if (ex) {
        console.log(ex);
    } else {

        for (var i = 0; i < currentAccounts.length; i++) {
            console.log(currentAccounts[i].nameSurname);
            console.log(currentAccounts[i].contactInfo.emailAddress);
            console.log(currentAccounts[i].operations[0].amount);
            console.log("------------------------------------------");
        }
    }
});

Burada sorgu kriterini biraz değiştirdik. Öncelikle "nameSurname: /li/" ifadesi SQL'deki "Like '%li%' ifadesine karşılık gelir ve "nameSurname" değişkeni içerisinde "li" geçen tüm kayıtlar anlamındadır. Ardından bir virgül koyuyoruz ki, bu da "and" anlamına geliyor. Son olarak da "currentAccountId: { $gte: 2000 } }" ifadesini görüyoruz. "gte" "Greater or Equal", yani büyük veya eşit anlamına geliyor. Diğer ihtimaller, "gt", "lte" (Less or Equal) ve "lt" şeklinde sıralanıyor. Özetle burada, "currentAccountId" değişkeni 2000'den büyük veya eşit olanlar demiş oluyoruz. Uygulama da her iki kritere de uyan kayıtları listeliyor ki, bu sefer aşağıdaki gibi sadece Veli dönmüş oluyor.


Biliyorum, sorgulama kriterinin yazımı biraz farklı ama alıştıktan sonra o kadar da sorun olmuyor. Yalnız arkadaşlar bu konuda o kadar aşmışlar ki, tüm kriter yazımlarını burada verme imkanım yok. İsteyenler, tam listeye buradan ulaşabilir. Ben, yukarıdaki iddiada bulunan arkadaşların ninesine son bir uğraş daha verip konuyu geçeceğim. "program.js" dosyamızı aşağıdaki gibi değiştirelim.
"use strict";

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/testdb');


var Schema = mongoose.Schema;

var currentAccountSchema = new Schema({
    currentAccountId: Number,
    nameSurname: String,
    contactInfo: {
        phoneNumber: Number,
        faxNumber: Number,
        emailAddress: String
    },
    operations: [{
            operationId: Number,
            operationType: String,
            date: {
                type: Date
            },
            amount: Number
    }]
});


var CurrentAccount = mongoose.model('CurrentAccount', currentAccountSchema);


CurrentAccount.find(
  {
    $and: [
            {
                nameSurname: /li/
            },
            {
                $or: [{ "currentAccountId.operations": { $gt: { $size: 0 } } },
                      { currentAccountId: { $not: { $gte: 10000 } } }]
                },
            {
                $or: [{ "contactInfo.emailAddress": "aa@bb.net" },
                      { "contactInfo.emailAddress": "cc@dd.net" }]
            }
          ]
  },

function (ex, currentAccounts) {

    if (ex) {
        console.log(ex);
    } else {

        for (var i = 0; i < currentAccounts.length; i++) {
            console.log(currentAccounts[i].nameSurname);
            console.log(currentAccounts[i].contactInfo.emailAddress);
            console.log(currentAccounts[i].operations[0].amount);
            console.log("------------------------------------------");
        }
    }
});

Burada mümkün mertebe, normalde kullandığımız pek çok sorgu ifadesini kullanmaya çalıştım.
  • "$and" ve "$or" ifadeleri, kendinden sonra gelen dizi içerisindeki ifadelerin ve/veya işlemlerinin hangisine tabii tutulacağını söylüyor. Bu ifadeleri istediğimiz kadar iç içe kullanabiliyoruz.
  • Eğer ki "currentAccountId.operations" gibi alt nesnelerin birinin üzerinden sorgu çekmek istersek, bunu tırnak içerisinde yazmak zorundayız. 
  • Eğer bir dizinin boyutu ile ilgileniyorsak, "$size" ifadesini kullanabiliyoruz (Örneğin burada "operations" dizisinin eleman sayısı 0'dan büyük olanlar dedik).
  • Eğer söylediğimizin tam tersini istiyorsak, "$not" ifadesini kullanıyoruz.


Sonuç olarak uygulamayı çalıştırdığında aşağıdaki gibi bir ekranla karşılaşmış olman gerekiyor.



Nasıl? Biraz biraz etkilenmeye başladık mı? Kafamıza göre kompleks nesneleri MongoDB'ye veriyoruz ve bunlar içerisinden istediğimiz gibi sorgu çekiyoruz. İşin ilginci, bu sorguların cevapları, RDBMS sistemlerden de hızlı bir şekilde geliyor. Ama milyonlarca kaydımız varsa, sorguların hızlanması için aynı RDBMS sistemlerdeki gibi Index kullanmamız da mümkün.

Bu konu makalenin dışında, direk MongoDB ile ilgili ama özet olarak şöyle söyleyeyim. Robomongo'da ilgili koleksiyonun altında "indexes" adında bir alt klasör bulunuyor. Buraya sağ tuşla basıp "Add Index" dediğimizde karşımıza bir ekran çıkıyor. Burada Index'e bir isim verdikten sonra, Keys kısmında nesnenin altındaki şu değişkenlere Index koy gibi ifadeler yazabiliyoruz. Buradaki yazım standardı "{ "currentAccountId" : 1, "nameSurname" : -1 }" şeklinde oluyor. Örneğin burada "currentAccountId" değişkenine artan sırada, ardından "nameSurname" değişkenine azalan sırada Index koydurmuş olduk. Burası fanteziye oldukça açık ve en iyi öğrenme yolu deneme yanılma şeklinde. Ancak şunu söyleyeyim. Eğer ki kayıt sayısı onbinler seviyesinde ve aşırı kompleks sorgu kriterlerimiz yoksa, RDBMS'lerden farklı olarak Index'lere hiçbir zaman ihtiyacımız olmayabilir. Çünkü bu sistemler, Sharding ile birlikte, milyarlarca kayıtla başa çıkmak üzere tasarlanmıştır ve onbin kayıt bunlara ancak kürdan vazifesi görür.



Pekala, konumuza geri dönelim. Şimdiye kadar sürekli sorgu çekip bir dizi aldık. Peki ya tek bir nesneye ihtiyacımız varsa? Örneğin sorgudan tek bir nesne geleceğini biliyorsak ya da dönen nesnelerden ilki bizim için önemliyse? "program.js" dosyamızı aşağıdaki gibi değiştirelim.
"use strict";

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/testdb');


var Schema = mongoose.Schema;

var currentAccountSchema = new Schema({
    currentAccountId: Number,
    nameSurname: String,
    contactInfo: {
        phoneNumber: Number,
        faxNumber: Number,
        emailAddress: String
    },
    operations: [{
            operationId: Number,
            operationType: String,
            date: {
                type: Date
            },
            amount: Number
    }]
});


var CurrentAccount = mongoose.model('CurrentAccount', currentAccountSchema);


CurrentAccount.findOne({ nameSurname: /li/},
                       function (ex, currentAccount) {
    if (ex) {
        console.log(ex);
    } else {

        console.log(currentAccount.nameSurname);
        console.log(currentAccount.contactInfo.emailAddress);
        console.log(currentAccount.operations[0].amount);
        console.log("------------------------------------------");
    }
});

Burada sadece "find" yerine "fineOne" fonksiyonunu kullandık. Bu fonksiyon, sorgudan dönen nesnelerden ilkini alır ve callback fonksiyonunun ikinci parametresine geçer. Böylece dizilerle uğraşmadan direk nesne ile çalışabiliriz. Uygulamayı çalıştırdığında ekran çıktısı aşağıdaki gibi olmalı.



Şimdi de farklı bir detaya odaklanalım. Robomongo ile kayıtları JSON formatında incelersen, "_id" adında bizim vermediğimiz bir değişkenin de nesnenin içerisinde bulunduğunu fark edeceksin. Bu aslında, RDBMS sistemlerden alışık olduğumuz Primary Key alanı, yani nesnenin Unique ifadesi. Biz vermediğimiz için mongoose bunu otomatik olarak oluşturuyor.




Güzel, ama bu ne işimize yarayacak? RDBMS sistemlerde olduğu gibi, bir kayda ulaşmanın en hızlı yolu, Primary Key üzerinden sorgu çekmektir. Bunun şimdilik bir anlamı olmayabilir, çünkü bu değeri sorgu öncesinde bilmiyoruz. Ancak ekranda gösterdiğimiz nesneyi birazdan güncelleyecek ve sileceğiz. İşte bu durumlarda, bu "_id" üzerinden sorguyu çalıştırdığımızda, sorgular, dolayısıyla güncelleme ve silme işlemlerimiz çok daha hızlı tamamlanacaktır.

Öncelikle bu "_id" alanını ekrana bir yazdıralım bakalım. "program.js" dosyamızı aşağıdaki gibi değiştirelim.
"use strict";

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/testdb');


var Schema = mongoose.Schema;

var currentAccountSchema = new Schema({
    currentAccountId: Number,
    nameSurname: String,
    contactInfo: {
        phoneNumber: Number,
        faxNumber: Number,
        emailAddress: String
    },
    operations: [{
            operationId: Number,
            operationType: String,
            date: {
                type: Date
            },
            amount: Number
    }]
});


var CurrentAccount = mongoose.model('CurrentAccount', currentAccountSchema);


CurrentAccount.findOne({ nameSurname: /li/ },
                       function (ex, currentAccount) {
    if (ex) {
        console.log(ex);
    } else {

        console.log(currentAccount._id);
    }
});

Uygulamayı çalıştırdığında ekran çıktısı aşağıdaki gibi olmalı.


Elbette akılda tutulacak gibi değil. Ama güncelleme ve silme öncesi bir değişkende saklanabilir. Sırada, bu alana göre nesneyi getirme işlemi var. "program.js" dosyamızı aşağıdaki gibi değiştirelim.

Dikkat : Burada bendeki "_id" değerini yazıyorum. Kendi bilgisayarında yaptığın örneklerde, bir önceki sorguda hangi "_id" değeri karşına çıktıysa, buradaki "_id" değerlerini onunla değiştirmeyi unutma.
"use strict";

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/testdb');


var Schema = mongoose.Schema;

var currentAccountSchema = new Schema({
    currentAccountId: Number,
    nameSurname: String,
    contactInfo: {
        phoneNumber: Number,
        faxNumber: Number,
        emailAddress: String
    },
    operations: [{
            operationId: Number,
            operationType: String,
            date: {
                type: Date
            },
            amount: Number
    }]
});


var CurrentAccount = mongoose.model('CurrentAccount', currentAccountSchema);


CurrentAccount.findById("5286502d1404139a0c000002", function (ex, currentAccount) {

    if (ex) {
        console.log(ex);
    } else {

        console.log(currentAccount.nameSurname);
        console.log(currentAccount.contactInfo.emailAddress);
        console.log(currentAccount.operations[0].amount);
        console.log("------------------------------------------");
    }
});

Gördüğün gibi, burada tek değişen "findOne" yerine "findById" fonksiyonunu kullanmamız ve sorgu parametresi olarak da "_id" değerini geçmemiz oldu. Uygulamayı çalıştırdığında ekran çıktısı aşağıdaki gibi olmalı.



Bu sorgu, her ne kadar biz şu anda fark edemesek de, milyonlarca kayıt arasında daha hızlı çalışacaktır. Şimdi gelelim bu "_id" değerinin asıl kullanım alanına. "program.js" dosyamızı aşağıdaki gibi değiştirelim.
"use strict";

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/testdb');


var Schema = mongoose.Schema;

var currentAccountSchema = new Schema({
    currentAccountId: Number,
    nameSurname: String,
    contactInfo: {
        phoneNumber: Number,
        faxNumber: Number,
        emailAddress: String
    },
    operations: [{
            operationId: Number,
            operationType: String,
            date: {
                type: Date
            },
            amount: Number
    }]
});


var CurrentAccount = mongoose.model('CurrentAccount', currentAccountSchema);


CurrentAccount.findByIdAndUpdate("5286502d1404139a0c000002",
                                 { nameSurname: "Ahmet"},
                                 function (ex) {
    if (ex) {
        console.log(ex);
    } else {
        console.log("Tamam");
    }
});

Dikkat edersen, burada "findByIdAndUpdate" fonksiyonunu kullandık. Bu fonksiyonun ilk parametresine az önce gördüğümüz "_id" alanını geçiyoruz. İkinci parametresine de değişiklik yapmak istediğimiz alanları geçiyoruz ki, bu örneğimizde, ilgili nesnenin "nameSurname" değişkeninin değerini "Ahmet" yapmak istediğimizi söyledik. Uygulamayı çalıştırdığında ekran çıktısı aşağıdaki gibi olmalı.



Tamam da, hakikatten de tamam mı acaba? Bir de Robomongo'dan kontrol edelim bakalım.


Günahını almışız. Gerçekten de, "nameSurname" alanı "Ahmet" olmuş. Helal olsun.

Gel gelelim, nesneler üzerinde yapacağımız güncellemeler her zaman bu kadar basit olmayabilir. Birkaç adımdan oluşan işlemlere tabii tutmamız gerekebilir. Hatta belki de nesneyi başka servislere göndermeli ve oradan geri gelecek nesneyi kaydetmemiz gerekebilir. Böyle durumlarda iki fazlı bir çalışma yaparız. İlk olarak "findById" ile nesneyi çekeriz. Akabinde nesne üzerinde gerekli çalışmaları yaparız (Ki bu örneğimizde "operations" dizisine yeni bir cari işlem ekleyeceğiz). Son olarak "save" fonksiyonu ile nesneyi kaydederiz.

"save" fonksiyonu normalde nesneyi sıfırdan kaydetmek için kullanılır ancak nesnenin "_id" alanı koleksiyonda zaten mevcutsa, bu durumda update işlemini gerçekleştirir. Tüm bunlar için "program.js" dosyamızı aşağıdaki gibi değiştirelim.
"use strict";

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/testdb');


var Schema = mongoose.Schema;

var currentAccountSchema = new Schema({
    currentAccountId: Number,
    nameSurname: String,
    contactInfo: {
        phoneNumber: Number,
        faxNumber: Number,
        emailAddress: String
    },
    operations: [{
            operationId: Number,
            operationType: String,
            date: {
                type: Date
            },
            amount: Number
    }]
});


var CurrentAccount = mongoose.model('CurrentAccount', currentAccountSchema);


CurrentAccount.findById("5286502d1404139a0c000002",
                        function (ex, currentAccount) {
    if (ex) {
        console.log(ex);
    } else {

        currentAccount.operations.push({
            operationId: 3,
            operationType: "Para Girişi",
            date: new Date(),
            amount: 100
        });

        currentAccount.save(function (err) {

            if (err) {
                console.log(err);
            } else {
                console.log("Tamam");
            }
        });
    }
});

Uygulamayı çalıştırdığında ekran çıktısı aşağıdaki gibi olmalı.



Bir de Robomongo'dan kontrol edelim.



Gayet güzel, sistem çalışıyor. Gel gelelim, bazen veritabanında toplu değişiklikler yapmak isteriz (Ki bu işlemler ORM'lerin en büyük sıkıntısıdır). Örneğin "nameSurname" değişkeninde "e" geçen herkesin "contactInfo" alt nesnesindeki "faxNumber" değişkeninin değerinin "777" yapılması gibi. Bunun için "program.js" dosyamızı aşağıdaki gibi değiştirelim.
"use strict";

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/testdb');


var Schema = mongoose.Schema;

var currentAccountSchema = new Schema({
    currentAccountId: Number,
    nameSurname: String,
    contactInfo: {
        phoneNumber: Number,
        faxNumber: Number,
        emailAddress: String
    },
    operations: [{
            operationId: Number,
            operationType: String,
            date: {
                type: Date
            },
            amount: Number
    }]
});


var CurrentAccount = mongoose.model('CurrentAccount', currentAccountSchema);


CurrentAccount.update({ nameSurname: /e/ },
                      { "contactInfo.faxNumber": "777" },
                      { multi: true },
                      function (ex, numberAffectedRow) {
    if (ex) {
        console.log(ex);
    } else {
        console.log(numberAffectedRow);
    }
});

Burada, herhangi bir "find" fonksiyonu kullanmak yerine, "update" fonksiyonunu kullanıyoruz. Bu fonksiyonun da ilk parametresi yine sorgulama kriterini belirtiyor. İkinci parametre ise, yapılacak güncellemeyi anlatıyor. Üçüncü parametre olarak geçtiğimiz "{ multi: true }" değeri, bir seferde birden fazla güncelleme yapılmasına izin veriyor. Eğer bunu belirtmezsek, sadece bulunan ilk kaydı güncelleyip geri kalanına dokunmayacaktır. Son parametre olan callback fonksiyonunda, şimdiye kadarkilerden farklı olarak "numberAffectedRow" parametresi mevcut. Buraya da, güncellemeye maruz kalan nesne sayısı geçiliyor. Uygulamayı çalıştırdığında, 2 adet nesne güncellendiği için, aşağıdaki gibi bir ekran çıktısı ile karşılaşıyor olman lazım.



Ben MongoDB'ye güveniyorum ve Robomongo'dan tekrar kontrol etmiyorum. İsteyen edebilir.

Gelelim bir de silme işlemine. En hızlı silme işlemi şüphesiz "_id" alanına göre olacaktır. Bunun için "program.js" dosyamızı aşağıdaki gibi değiştirelim.
"use strict";

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/testdb');


var Schema = mongoose.Schema;

var currentAccountSchema = new Schema({
    currentAccountId: Number,
    nameSurname: String,
    contactInfo: {
        phoneNumber: Number,
        faxNumber: Number,
        emailAddress: String
    },
    operations: [{
            operationId: Number,
            operationType: String,
            date: {
                type: Date
            },
            amount: Number
    }]
});


var CurrentAccount = mongoose.model('CurrentAccount', currentAccountSchema);


CurrentAccount.findByIdAndRemove("5286502d1404139a0c000002",
                                 function (ex) {
    if (ex) {
        console.log(ex);
    } else {
        console.log("Tamam");
    }
});

"findByIdAndRemove" fonksiyonu sayesinde verilen "_id" değerini barındıran nesneyi koleksiyondan uçurmuş oluyoruz. Uygulamayı çalıştırdığında ekran çıktısı aşağıdaki gibi olmalı.


Yine isteyen Robomongo'dan kontrol edebilir. Artık tek bir kaydımız kalmış olmalı.

Aynı güncelleme işleminde yaptığımız gibi, silme işleminde de zaman zaman toplu işlemler yapmamız gerekebilir. Örneğin "nameSurname" değişkeninde "e" geçen herkesin silinmesi gibi. Bunun için de "program.js" dosyamızı aşağıdaki gibi değiştirelim.
"use strict";

var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/testdb');


var Schema = mongoose.Schema;

var currentAccountSchema = new Schema({
    currentAccountId: Number,
    nameSurname: String,
    contactInfo: {
        phoneNumber: Number,
        faxNumber: Number,
        emailAddress: String
    },
    operations: [{
            operationId: Number,
            operationType: String,
            date: {
                type: Date
            },
            amount: Number
    }]
});


var CurrentAccount = mongoose.model('CurrentAccount', currentAccountSchema);


CurrentAccount.remove({ nameSurname: /e/ },
                      function (ex, numberAffectedRow) {
    if (ex) {
        console.log(ex);
    } else {
        console.log(numberAffectedRow);
    }
});

Burada da, "findByIdAndRemove" fonksiyonu yerine "remove" fonksiyonundan faydalandık. Muhtemelen artık anlatmaya gerek yoktur ama ilk parametre yine sorgulama kriterini belirtiyor. Aynı "update" fonksiyonunda olduğu gibi callback fonksiyonundaki "numberAffectedRow" parametresi silinen nesne sayısını gösteriyor. Uygulamayı çalıştırdığında, 1 adet nesne silindiği için (çünkü iki nesneden ilkini bir önceki örnekte silmiştik), aşağıdaki gibi bir ekran çıktısı ile karşılaşıyor olman lazım.



Çok şükür, nihayeti makalenin sonuna geldik sayılır. Makale boyunca Mongoose üzerinden MongoDB ile CRUD (Create, read, update, delete) işlemlerini nasıl yapabileceğimizi görmüş olduk. Elbette Mongoose oldukça geniş bir kütüphane ve MongoDB başlı başına bir derya. Tüm yeteneklerini burada saymama imkan yok. Mongoose hakkında daha detaylı bilgiye sahip olmak isteyenler, resmi sitesindeki dokümantasyondan faydalanabilirler. MongoDB hakkında ise MongoDB: The Definitive Guide kitabını tavsiye ediyorum.

MongoDB ve NoSQL anlatmakla bitmez ama makaleyi tamamlamadan önce ilgi çekmek için son bir bilgi daha vereyim. MongoDB'nin Sharding diye bir özelliği var (Ki bu diğer NoSQL veritabanlarının bir kısmında da mevcut). Bu özellik sayesinde, örneğin adı "A" ile başlayanlar şu sunucuya, "B" ile başlayanlar şu sunucuya diye bir tanımlama yapıyorsun. Böylece tek bir koleksiyonu 29 farklı sunucuya dağıtmış oluyorsun. Ardından örneğin doğum tarihi 1961-1970 olanlar şu sunucuya, 1971-1980 olanlar şu sunucuya diye de tanımlama yapıyorsun. Sonuç olarak, senin tek bir veritabanını, verinin karakteristiğine göre yüzlerce sunucuya bölmüş oluyorsun. Peki ne işe yarıyor? Eğer kayıtları yüz sunucuya böldüysen, örneğin toplamda 10 milyar kaydın varsa, her bir sunucu yaklaşık 100 milyon kayıtla çalışmak zorunda kalıyor. Böylece sunucuları paralelize ederek RDBMS'lerin sözünü bile edemeyeceği büyüklükteki verilerle başa çıkma imkanına sahip oluyorsun. Üstelik bunların tamamı da otomatik oluyor. Sen uygulamandan sadece sorgu çekiyorsun, MongoDB gidip ilgili sunucuyu bulup, sorguyu orada işletiyor.

Bu özelliği de, sırf MongoDB hakkında bir kitap alıp okumanı teşvik etmek amacıyla vermiş olayım. Daha neler var neler.

Geldik makalenin sonuna. Artık nasıl yapacaksak, öğrendiklerimizi bir özetleyelim bakalım.
  • MongoDB güzel bir şey :)
  • Node.JS üzerinden MongoDB'ye bağlanmak için Mongoose modülünü kullanabiliriz.
  • MongoDB verileri BSON (Binary JSON) formatında tutar.
  • Nesneleri Mongoose ile MongoDB'ye kaydetmeye başlamadan önce yapısını tanımlamamız gerekir. Bunun için de "mongoose.Schema" sınıfından faydalanırız.
  • Herhangi bir modelden türettiğimiz nesneyi veritabanına kaydetmek için, nesnenin "save" fonksiyonunu kullanabiliriz.
  • Kaydetme sırasında veritabanı veya koleksiyon yoksa, bizim için oluşturulur. RDBMS'de olduğu gibi bunları önceden ayarlamaya gerek yoktur.
  • Aynı yapıda kaydedilen tüm nesneler, MongoDB'de birer koleksiyon olarak tutulur.
  • Modelin "find" fonksiyonu sayesinde, veritabanındaki bir koleksiyonda bulunan tüm nesnelere ulaşabiliriz.
  • "find" fonksiyonunun opsiyonel ilk parametresinde sorgu kriterleri gönderebiliriz ve koleksiyonda bulunan nesnelerin filtrelenmiş bir kısmına ulaşabiliriz.
  • İhtiyaç durumunda, nesnelerin değişkenlerine MongoDB üzerinde index koyabiliriz ve bu alanlar üzerinden daha hızlı sorgulama imkanına kavuşabiliriz.
  • Modelin "findOne" fonksiyonu ile, nesne dizisi yerine, kriterlere uyan ilk nesneye ulaşmamız mümkündür.
  • MongoDB'ye atılan her bir kaydın "_id" isminde, RDBMS'deki Primary Key yerine geçen Uniqıe bir değeri vardır. Biz bu değeri elle vermesek bile, kendiliğinden üretilir.
  • Bu "_id" değeri üzerinden yapılan sorgular, diğer sorgulara göre daha hızlı çalışır.
  • Modelin "findById" fonksiyonu vasıtasıyla, "_id" değeri üzerinden nesnelere erişebiliriz.
  • Aynı şekilde, modelin "findByIdAndUpdate" fonksiyonu vasıtasıyla, "_id" değeri üzerinden nesneleri güncelleyebiliriz.
  • Daha kapsamlı güncellemeler için, "findById" fonksiyonu ile nesneye alıp, üzerinde istediğimiz değişiklikleri yapıp, nesnenin "save" fonksiyonu sayesinde veritabanındaki kaydını güncelleyebiliriz. Eğer elimizdeki nesnenin "_id" değeri MongoDB'deki koleksiyonda zaten varsa, "save" fonksiyonu yeni bir kayıt açmak yerine var olan kaydı güncelleyecektir.
  • Koleksiyondaki birden fazla kayıt üzerinde toplu olarak güncelleme işlemi yapmak istersek, modelin "update" fonksiyonunu kullanabiliriz.
  • Modelin "findByIdAndRemove" fonksiyonu vasıtasıyla, "_id" değeri üzerinden nesneleri silebiliriz.
  • Koleksiyondaki birden fazla kaydı toplu olarak silmek istersek, modelin "remove" fonksiyonunu kullanabiliriz.
  • Sharding denen bir teknik sayesinde, milyarlarca kayıttan oluşan bir koleksiyonu, çeşitli özelliklerine göre yüzlerce farklı sunucuya yayabilir, böylece RDBMS sistemlerin sözünü bile edemeyeceği büyüklükteki verilerle başa çıkma imkanına sahip olabiliriz.


Yorum Gönder

  1. modeldenTuretilenObject.save() şeklinde kullandığımda ilk çalıştırmada yeni veri oluşturuyor ancak daha sonra her kullanımda eklediği veriye replace yapıyor, id değeri sabit kalıp diğer değerler güncelleniyor.
    nedeni nedir?

    YanıtlaSil
  2. ORM'in çalışma mantığı bu aslında. Nesneyi id değeri üzerinden tanıyor. Eğer id değeri boş ise, nesne ilk defa oluşturuluyor kabul ediyor ve veritabanına insert ediyor. Eğer id varsa, bu durumda nesne veritabanından çekilmiştir diye kabul ediyor ve "save" komutu sonucunda güncelleme işlemini yapıyor.

    YanıtlaSil
  3. modeli urlyi yakaladığım fonksiyon içinde dinamik olarak oluşturduğumda sorunu çözdüm, diğer türlü statik olduğundan sürekli aynı model güncellenip duruyor yeni veri eklemeden güncelleme işlemi gerçekleşiyordu.

    YanıtlaSil
  4. Levent hocam,
    bende aynı durumda aşağıdaki hatayı veriyor halbuki ben değerlerin güncellenmesini istiyorum bunu nasıl gerçekletirebilirim.

    "MongoError: insertDocument :: caused by :: 11000 E11000 duplicate key error index"

    YanıtlaSil
  5. problemi aşağıdaki şekilde çözdüm update fonksiyonuna opsiyon olarak upsert:true gönderdim iyi çalışmalar.
    var q={_id:"1"};
    var update = {$set : .... };
    var options = {upsert:true};
    modalobj.update(conditions, update, options,function(){});

    mongodb version 2.6.4
    mongoose version 3.8.0
    node js version v0.13.0-pre

    YanıtlaSil
  6. Çok güzel yazı günde 10 kez bakıyorum =))

    YanıtlaSil
  7. Çok başarılı bir anlatım olmuş Levent hocam emeğinize sağlık

    YanıtlaSil

 
Top