无法使用pymongo在mongodb中插入嵌套对象

时间:2019-06-21 16:10:32

标签: python mongodb serialization

我今天要来的一个问题对于使用python和mongodb来说对我来说没有意义。我是Go / C#开发人员,所以也许我错过了一些东西,但是我遇到以下情况:

from datetime import datetime
from bson import ObjectId 

class DailyActivity:
    user_ids = []
    date = None

    def __init__(self, user_ids : [ObjectId] = [], date : datetime = None):
        self.user_ids = user_ids
        self.date = date


class ActivitiesThroughDays:
    daily_activies = []

    def add_daily_activity(self, daily_activity : DailyActivity = None):
        daily_activies.append(daily_activity)

然后我有这两个类,还有另一个包含一些使用mongodb的助手的文件:

from pymongo import MongoClient

def get_client():
    return MongoClient('localhost', 27017)


def get_database(database_name: str = None):
    if database_name is None:
        raise AttributeError("database name is None.")
    return get_client().get_database(database_name)


def get_X_database():
    return get_database("X")

这是我们要解决的问题。.我现在正在构建一个简单的ActivitiesThroughDays对象,其中只有一个DailyActivity包含X个用户ID(作为ObjectId数组/列表)。

但是,当我尝试insert_one时,我得到以下信息:

  

TypeError:文档必须是dict,bson.son.SON,bson.raw_bson.RawBSONDocument的实例,或者是从collections.MutableMapping继承的类型

这是引发异常的代码:

def insert_activities_though_days(activities_through_days: ActivitiesThroughDays = None):
    if activities_through_days is None:
        raise AttributeError("activities_through_days is None.")
    col = get_EM_column("activities_through_days")
    col.insert_one(activities_through_days)

基于上述问题,然后我尝试将我的ActivitiesThroughDays转换为dic / json:

col.insert_one(activities_through_days.__dict__)

  

bson.errors.InvalidDocument:无法编码对象:模型。 DailyActivity。 DailyActivity对象,位于0x10eea0320,类型为:“模型”。 DailyActivity。 DailyActivity”

col.insert_one(json.dumps(activities_through_days))

  

TypeError:ActivityThroughDays类型的对象不可JSON序列化

因此,基于此,我开始在Google上搜索不同的解决方案,并找到了诸如以下的解决方案:

def to_dict(obj):
    if not hasattr(obj,"__dict__"):
        return obj
    result = {}
    for key, val in obj.__dict__.items():
        if key.startswith("_"):
            continue
        element = []
        if isinstance(val, list):
            for item in val:
                element.append(to_dict(item))
        else:
            element = to_dict(val)
        result[key] = element
    return result

但是我得到了:

  

bson.errors.InvalidDocument:无法编码类型为“ property”的对象:位于0x10229aa98的属性对象


对于我迈出的每一步,都会出现另一个问题……对我来说,所有这些都根本没有意义,因为..应该在某个地方有一个通用的序列化器/反序列化器,它将从一行开始转换要在mongodb中插入的任何嵌套对象/数组。

此外,从我尝试过的一种解决方案中,我发现ObjectId在映射到json / dict时被忽略了(我不记得是哪一个了)

我根本不是Python开发人员,所以请随时提供任何提示:)

谢谢

1 个答案:

答案 0 :(得分:0)

pymongo的界面需要dict,而.__dict__是一个非常低级的属性。

如果您尝试从头开始为mongodb构建ORM / ODM,恐怕您会花费很多精力。

存在适用于python中mongodb的现有ORM / ODM库(mongoenginepymodm,它们非常相似),可以帮助您快速进行操作。

以下几行代码显示了使用mongoengine的模型的外观以及如何保存它们:

import datetime as dt
from mongoengine import *

connect(host='mongodb://localhost:27017/testdb')

class User(Document):
    email = EmailField(required=True)

class DailyActivity(Document):
    users = ListField(ReferenceField(User))
    date = DateTimeField(default=dt.datetime.utcnow)

user = User(email='test@garbage.com').save()
user2 = User(email='test2@garbage.com').save()

activity = DailyActivity(users=[user, user2]).save()

我希望这对您有帮助