Невозможно вставить вложенный объект в mongodb, используя pymongo - PullRequest
0 голосов
/ 21 июня 2019

Я приду сегодня после проблемы, которая не имеет смысла для меня, используя 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)

У меня есть эти 2 класса, а также другой файл, содержащий некоторый помощник для использования 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 идентификаторов пользователя (в виде массива / списка ObjectId).

Однако, когда я пытаюсь вставить insert_one, я получаю следующее:

TypeError: документ должен быть экземпляром dict, bson.son.SON, bson.raw_bson.RawBSONDocument или типом, который наследуется от collection.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)

Исходя из вышеизложенного, я попытался преобразовать мои Деятельности через день в dic / json:

col.insert_one(activities_through_days.__dict__)

bson.errors.InvalidDocument: не может кодировать объект: модели. Ежедневные дела. Объект DailyActivity по адресу 0x10eea0320, типа: класс 'моделей. Ежедневные дела. DailyActivity '

col.insert_one(json.dumps(activities_through_days))

TypeError: Объект типа ActivitiesThroughDays не поддерживает сериализацию в формате 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: невозможно закодировать объект: объект свойства в 0x10229aa98, типа: класс 'свойство'


Для каждого шага, который я продвигаю, возникает другая проблема ... Для меня все это вообще не имеет смысла, потому что ... где-то должен быть универсальный сериализатор / десериализатор, который из 1 строки конвертировал бы любые вложенные объекты / массивы для вставки в mongodb ..

Кроме того, из одного решения, которое я пробовал, я обнаружил, что ObjectId игнорировались при отображении в json / dict (я не помню, какое)

Я вовсе не являюсь разработчиком Python , поэтому, пожалуйста, не стесняйтесь давать любые советы:)

Спасибо

1 Ответ

0 голосов
/ 24 июня 2019

интерфейс pymongo ожидает dict, а .__dict__ - атрибут очень низкого уровня.

Боюсь, вы потратите много энергии, если попытаетесь создать ORM / ODM для mongodb с нуля.

Существуют библиотеки ORM / ODM, которые существуют для mongodb в python ( mongoengine , pymodm , которые очень похожи) и которые могут помочь вам быстро что-то заработать.

Вот несколько строк, которые показывают, как модели будут выглядеть с 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()

Надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...