Mongodb Veritabanınızı Google Cloud Storage'a Aktarın
Tags: mongodb, cloud, googlecloud, python
Published: 2022-01-22 16:11:10

erhaba arkadaşlar, bu yazımda [heybooster](https://app.heybooster.ai)'ın
veritabanı yedeği için yazdığımız bir koddan bahsedeceğim. Bu kod veritabanımızı
[Google Cloud Storageda](https://cloud.google.com/storage/)
açtığımız bir bucketa yolluyor. Detayları aşağıda konuşalım :)

---

### Neden Mongodb?


![MongoDB](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n091yewdsivphd9yulvn.png)

Bu yazı tek tek neyin ne olduğunu açıklayan bir yazı olmayacak ancak kısaca yazıda
geçen teknolojilerden bahsetmek istiyorum. [Mongodb](https://www.mongodb.com/)
birçok programlama diline destek veren, ölçeklenebilir açık kaynak kodlu bir
NoSQL veritabanıdır. Verileri SQL veritabanlarından farklı olarak JSON formatta
tutmaktadır. Bu da bizim istediğimiz bir özellik. Mongodb NoSQL yapısıyla
Heybooster'ın tüm ihtiyaçlarına çözüm sunuyordu. Bu yüzden veritabanı olarak
Mongodb'yi tercih ettik.   

---

### Neden Google Cloud Storage?

![Google Cloud Storage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h3l1mx1hsoiofvb07jab.png)

Yazının kalanında "Google Cloud Storage" yerine "GCS" yazacağım. Öncelikle ne olduğundan
bahsedelim. Wikipedia'a göre aşağıdaki gibi bir tanımı var. Bu tanım ne olduğunu
anlamaya yetecektir diye düşünüyorum.

> Google Cloud Storage, Google Cloud Platform altyapısındaki verileri depolamak ve
bunlara erişmek için RESTful bir çevrimiçi dosya depolama web hizmetidir. Hizmet,
Google'ın bulutunun performansını ve ölçeklenebilirliğini gelişmiş güvenlik ve
paylaşım yetenekleriyle birleştirir

---

### Peki Biz Ne İstiyorduk?


![Who we are meme](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sv4p6bw1mp437yo571jv.jpg)

Gelelim asıl konuya, biz ne istiyorduk? Bizim isteğimiz gün içinde oluşan veritabanındaki
bazı verileri yedeklemek. Yani günlük veritabanı yedeği diyebiliriz. Peki bunu nasıl yapacağız?
Mongodb database tool içinde bulunan mongodump programını kullanarak veritabanını export
edebileceğiz. Sonra? Sonrası için ilk planımız [Digital Ocean](https://www.digitalocean.com/)'dan
bir ubuntu makine açıp orda yedeklemekti ancak GCS'a göre çok daha pahalıya geliyordu.
Bizim kararımız bu noktada netleşti.

---

### Operasyon Başlasın &#128074;


![Maskeli Beşler Irak](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ncxyctq4f9hyrtyuwi76.jpg)

Kararlarımızı verdikten sonra gereklilikleri sağlayıp kod yazmaya başladık. Kodu
yazı sonunda paylaşacağım ama önce gerekliliklerden kısaca bahsedeyim. Verilerini
elde edeceğimiz veritabanının username, password gibi bilgilerine ihtiyacımız var.
Sonrasında GCS için credential işlemleri ve gerekli GCS kütüphanesini yüklememiz
gerekiyor. Bunları yaptıktan sonra kodumuzu yazabiliriz.

Gelelim koda.

```Python
import os
from dotenv import load_dotenv
from google.cloud import storage
from bson.objectid import ObjectId
from datetime import datetime
import time
from os import listdir
from os.path import isfile, join

load_dotenv()

DB_USER = os.environ['DB_USER']
DB_PASSWORD = os.environ['DB_PASSWORD']
DB_NAME = os.environ['DB_NAME']
BUCKET_NAME = os.environ['BUCKET_NAME']


def mongodump_reports(archive_file):
    today = datetime.today()
    date = datetime(today.year, today.month, today.day, 0, 0, 0)
    # Required for ignoring the documents older than 1 day
    idMin = ObjectId(format(int(date.timestamp()), 'x') + "0000000000000000")

    # Using --out options to fix the file name
    DB_DUMP_COMMAND = """
    mongodump --uri "mongodb://{}:{}@heybooster-shard-00-00-yue91.mongodb.net:27017,heybooster-shard-00-01-yue91.mongodb.net:27017,heybooster-shard-00-02-yue91.mongodb.net:27017/{}?authSource=admin&replicaSet=heybooster-shard-0&retryWrites=true&ssl=true&w=majority" --collection reports --out {} --query""".format(
        DB_USER, DB_PASSWORD, DB_NAME, archive_file) + """ '{"_id": {"$gte": ObjectId("'""" + str(idMin) + """'")}}'"""
    os.system(DB_DUMP_COMMAND)


def list_blobs(bucket_name):
    """Lists all the blobs in the bucket."""

    storage_client = storage.Client.from_service_account_json(
        'credentials.json')

    # Note: Client.list_blobs requires at least package version 1.17.0.
    return storage_client.list_blobs(bucket_name)


def upload_backup_file(bucket_name, archive_file, destination_blob):
    """Uploads a file to the bucket."""

    storage_client = storage.Client.from_service_account_json(
        'credentials.json')
    bucket = storage_client.bucket(bucket_name)

    current = os.getcwd()
    a = listdir(archive_file)[0]
    path = current + "/" + archive_file + "/" + a
    files = [f for f in listdir(path) if isfile(join(path, f))]
    for file in files:
        archive_file = path + '/' + file
        destination_blob = destination_blob + '_' + file
        blob = bucket.blob(destination_blob)
        blob.upload_from_filename(archive_file)

    print("File {} uploaded to {}.".format(archive_file, destination_blob))


def remove_old_reports(bucket_name, archive_file):
    """Deletes a blob from the bucket."""

    storage_client = storage.Client.from_service_account_json(
        'credentials.json')

    bucket = storage_client.bucket(bucket_name)
    blob = bucket.blob(archive_file)
    blob.delete()

    print("Blob {} deleted.".format(archive_file))


def start():
    archive_file_name = "mongo_backup_" + time.strftime('%x').replace('/', '_')
    destination_blob_name = archive_file_name
    mongodump_reports(archive_file_name)
    upload_backup_file(BUCKET_NAME, archive_file_name, destination_blob_name)


if __name__ == '__main__':
    start()
```

Kod karmaşık olmadığı için anlaşılır diye düşünüyorum. Kısaca bahsedeyim, veritabanımızı
export eden fonksiyon "mongodump_export"un yaptığı şey mongodump komutunu çalıştırmak. Başka
bir görevi yok. "list_blobs" isimli fonksiyon ise bucket içindeki dosyaları listelememizi
sağlıyor. "upload_backup_file" ise istediğimiz dosyanın bucketa yüklenmesini sağlıyor.
"remove_old_file" isminden anlaşıldığı gibi eski dosyaları silmemizi sağlıyor. Tabi bunu
dosya ismini parametre olarak alarak yapıyor.

Kodumuz bundan ibaret. Serverda bu kodun günlük olarak çalışmasını sağlamamız yeterli.
Anlamadığınız bir yer varsa sorabilirsiniz. Umarım işinize yaramıştır. İyi pazarlar dilerim :)

* Typo düzeltmesi için teşekkürler [@Yaşar](https://twitter.com/yasarcelepp)

* [https://ilteriskeskin.github.io/posts/google-cloud-storage-mongodb-data-transfer/](https://ilteriskeskin.github.io/posts/google-cloud-storage-mongodb-data-transfer/)