12/08/2018, 13:10

Non-Relational SQL ( MongoDB ) với Python và Django (Phần 2)

Tiếp chủ đề về truy vấn dữ liệu MongoDB trong Python và Django 5. Truy vấn dữ liệu Mongoengine hỗ trợ truy vẫn ORM tương đối mạnh nên chúng ta có thể hoàn toàn truy vấn dữ liệu hoàn toàn dựa trên các model dữ liệu đã định nghĩa sẵn. Nếu bạn đã quen với cách truy vấn dữ liệu trong Django thì ...

Tiếp chủ đề về truy vấn dữ liệu MongoDB trong Python và Django

5. Truy vấn dữ liệu

Mongoengine hỗ trợ truy vẫn ORM tương đối mạnh nên chúng ta có thể hoàn toàn truy vấn dữ liệu hoàn toàn dựa trên các model dữ liệu đã định nghĩa sẵn.

Nếu bạn đã quen với cách truy vấn dữ liệu trong Django thì bạn sẽ tương đối dễ dàng truy vấn với Mongoengine.

Create models :

 class TypeActivity(models.Model):
    name = models.CharField(max_length=255)

class Activity(EmbeddedDocument):
    _id = IntField()
    date_time = DateTimeField(None)
    type_activity = IntField()
    object_id = IntField()
    data = StringField()
    status = BooleanField(default=True)

    class Meta:
        app_label = 'no_sql'

class Activities(Document):
    _id = IntField()
    action = ListField(EmbeddedDocumentField(Activity))

    class Meta:
        app_label = 'no_sql'

Get về 1 đối tượng object

activities = Activities.objects.get(_id=1)

Sau khi đã get về được 1 đối tượng object thì bạn có thể thực hiện các tác vụ CRUD với đối tượng đó. (như đã gioi thiệu ở phần 1)

Tìm kiếm và lọc dữ liệu lấy về

activities  = Activities.object.filter(_id = 1)

Ngoài ra bạn cũng có thể truy vấn lồng đề tìm kiếm dữ liệu:

activities  = Activities.object.filter(action__id = 1)

Nhưng các bạn lưu ý. Ở đây các bạn là các bạn get về đối tượng Activities, nên khi bạn truyền vào tham số action__id =1 thì Mongoengine sẽ tìm kiếm trong tất cả các Activities mà thỏa mãn điều kiện có tồn tại action__id =1 và trả về toàn bộ dữ liệu của đối tượng đấy.

1 số phép toán lọc dữ liệu hỗ trợ:

lt lte  – nhỏ hơn, nhỏ hơn hoặc bằng
gt gte – lơn hơn, lớn hơn hoặc bằng
in – value is in list (a list of values should be provided)
exists – Gía trị có tồn tại hay ko
...

exact – Tìm kiếm gía trị chính xác
contains – Chuỗi gía trị có chứa tham số đầu vào
icontains – Chuỗi gía trị có chứa tham số đầu vào ( ko phân biệt chữ hoa )
startswith – Chuỗi bắt đầu bằng
...

Các bạn có thể tham khảo thêm tại

http://docs.mongoengine.org/en/latest/guide/querying.html

Vì do MongoDB lưu dữ liệu dưới dạng Bson nên chúng ta còn có thể lấy 1 đối tượng dữ liệu theo kiểu :

activity = Activities.objects.get(_id=1).action[1]

ở đây ta get về 1 đối tượng Activity thông qua đối tượng Activities

6. Sử dụng song song nhiều database

Mặc định thì Django không hỗ trợ MongoDB nên nếu chỉ sử dụng MongoDB làm database cho Project của bạn thì bạn sẽ phải hi sinh đến 95% các app authentication hỗ trợ sẵn của Django. Nhưng ở đây mình sẽ gioi thiệu cho các bạn 1 mẹo nhỏ để chúng ta có thể sử dụng 1 lúc song song nhiều Database phù hợp với nhu cầu của Project.

Trong file setting.py ta sửa lại dòng cấu hình database.

 DATABASE_ROUTERS = ['Myproject.modelrouter.DatabaseAppsRouter', ]
 DATABASE_APPS_MAPPING = {'no_sql': 'no_sql'}
 DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': ',
        'USER': ',
        'PASSWORD': ',
        'HOST': ',
        'PORT': ',

    },
    'no_sql': {
        'ENGINE': 'django.db.backends.dummy',
    }
}

Ở đây mình có sử dụng 2 database là Mysql và MongoDB.

Với dòng đầu tiên. Bạn tạo 1 file modelrouter.py cùng cấp với file setting.py

class DatabaseAppsRouter(object):
    """
    A router to control all database operations on models for different
    databases.

    In case an app is not set in settings.DATABASE_APPS_MAPPING, the router
    will fallback to the `default` database.

    Settings example:

    DATABASE_APPS_MAPPING = {'no_sql1': 'no_sql1'}
    """

    def db_for_read(self, model, **hints):
        """"Point all read operations to the specific database."""
        if model._meta.app_label in settings.DATABASE_APPS_MAPPING:
            return settings.DATABASE_APPS_MAPPING[model._meta.app_label]
        return None

    def db_for_write(self, model, **hints):
        """Point all write operations to the specific database."""
        if model._meta.app_label in settings.DATABASE_APPS_MAPPING:
            return settings.DATABASE_APPS_MAPPING[model._meta.app_label]
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """Allow any relation between apps that use the same database."""
        db_obj1 = settings.DATABASE_APPS_MAPPING.get(obj1._meta.app_label)
        db_obj2 = settings.DATABASE_APPS_MAPPING.get(obj2._meta.app_label)
        if db_obj1 and db_obj2:
            if db_obj1 == db_obj2:
                return True
            else:
                return False
        return None

    def allow_migrate(self, db, model):
        """Make sure that apps only appear in the related database."""
        """ No migrate all database no_sql and model have ap_label = no_sql"""
        if db == 'no_sql' or model._meta.app_label == "no_sql":
            return False
        else:
            return True

trong file này mình có gọi đến cấu hình DATABASE_APPS_MAPPING dc định nghĩa trong file setting.py

Trong cấu hình DATABASES mình có cấu hình 2 cơ sở dữ liệu với tên được khai baos riêng rẽ.

Và khi bạn tạo 1 model mới thì bạn sẽ thêm dòng

class Meta:
        app_label = 'no_sql'

để báo với hệ thống là model này bạn sẽ sử dụng cơ sở dữ liệu nào. Và như thế khi bạn thực hiện các thao tác CRUD trên model này thì hệ thống sẽ thực hiện các truy vấn trên DATABASE mà bạn đã định hướng. Như vậy bạn có thể sử dụng các app có sẵn cửa Django thông qua 1 database mà Django hỗ trỡ ( như ví dụ là mình sử dụng MySQL ).

Cách sử dụng song song nhiều database như trên có thể áp dụng với nhiều loại database khác nhau. ( bạn cần cấu hình khai báo trong DATABASE_APPS_MAPPING và đặt app_lable =' ở những model mà bạn muốn chỉ định rõ database sẽ ghi vào.

0