doableware / djongo

Django and MongoDB database connector
https://www.djongomapper.com
GNU Affero General Public License v3.0
1.88k stars 353 forks source link

first impressions / questions #141

Open dblado opened 6 years ago

dblado commented 6 years ago

I'm looking to migrate from MongoEngine to Djongo. Has anyone done this and kept track of their 'gotchas'? I just like the concept of using as pure a Django as possible and removing several dependencies that using MongoEngine introduces.

I'm also interested in hearing about the future of Djongo. What companies are using it in production? Is there a corporate sponsor?

dblado commented 6 years ago

I'll use this issue for tracking my progress / thoughts instead of opening new ones.

I'm a little confused on the documentation so want to ask for clarification if I'm understanding things correctly. The docs explain EmbeddedModelField, ArrayModelField, and ArrayReferenceField but only as related to the Django quick start blog example. I looked through djongo.models.fields but the examples there are not accurate either. Examples of MongoDB documents would be great.

My understandings: EmbeddedModelField: A field whose value is a single object with fields defined from another model. For example, a users profile. Mongoengine equivalent is the EmbeddedDocumentField. Example

models.py

class Profile(models.Model):
    email = models.CharField()
    favorite_snack = models.CharField()
    class Meta:
        abstract = True

class User(models.Model)
    fname = models.CharField()
    lname = models.CharField()
    profile = models.EmbeddedModelField(model_container=Profile)

example mongodb document

{
    "fname": "Joe",
    "lname": "Shmoe",
    "profile": {
        "email": "me@me.com",
        "favorite_snack": "almonds"
    }
}

\ \ ArrayModelField: A field whose value is a list of EmbeddedModelField. For example, a list of all the places a user has lived. Mongoengine equivalent is the EmbeddedDocumentListField -- or ListField(EmbeddedDocumentField (a list of embedded documents).

class PlacesLived(models.Model):
    city = models.CharField()
    country = models.CharField()
    class Meta:
        abstract = True

class User(models.Model)
    fname = models.CharField()
    lname = models.CharField()
    places_lived = models.ArrayModelField(model_container=PlacesLived)

example mongodb document

{
    "fname": "Joe",
    "lname": "Shmoe",
    "places_lived": [
        {
            "city": "London",
            "country": "England"
        },
        {
            "city": "New York",
            "country": "USA"
        }
    ]
}

\ \ ArrayReferenceField: A field whose value is a list of MongoDB ObjectIDs (references to documents in another collection). In Django terms, a list of ForeignKeys. For example, a list of classes a user is enrolled in. Mongoengine equivalent is the ListField(ReferenceField).

class Classes(models.Model):
    name = models.CharField()
    start = models.DateTimeField()

class User(models.Model)
    fname = models.CharField()
    lname = models.CharField()
    classes_enrolled = models.ArrayReferenceField(to=Classes)

example mongodb document

{
    "fname": "Joe",
    "lname": "Shmoe",
    "classes_enrolled": [ObjectID(), ObjectID(), ObjectID()]
}

\ \ Conclusions Array is the MongoDB term for a collection of related objects like all the pets I've ever had. I prefer to use the term 'array' when talking about the actual documents in the database and the term 'list' when talking about the model because an embedded field in a queryset is a python list of dicts. Feel free to tell me I'm wrong :)

I feel that if I'm understanding this as above, ArrayModelField might inherit from EmbeddedModelField. Alternatively, I'm not convinced there is a use case for an embedded document to be a single object (compared to an array of objects). In my existing database, embedded documents are always arrays. Why not just do this instead and have the embedded fields be 'real' fields that can be queried faster:

class Profile(models.Model):
    email = models.CharField()
    favorite_snack = models.CharField()
    class Meta:
        abstract = True

class User(Profile)
    fname = models.CharField()
    lname = models.CharField()

\ \ I also think it might be nice to rename the djongo fields to be more explanatory. Maybe: ArrayModelField becomes ArrayEmbeddedModelField (or ListEmbeddedModelField since it's used in python as a list)\ \ ArrayReferenceField becomes ArrayForeignKeyField (or ListForeignKeyField since it's used in python as a list)\ \ I've always hated that Django doesn't use ForeignKeyField() when it uses Field for all other field types.

anupam858 commented 5 years ago

hello, I am very new to Django and I cannot find a single place to ask my query. I found this thread relevant so, I'm asking it here. After I declare an ArrayModelField in my model. How can I insert data into that field from my Views?