YardalGedal
@YardalGedal
yeah boy

Как логично совместить документы mongodb с объектами проекта?

У меня в проекте есть некоторые сущности, объекты, например класс User, класс Chat и есть документы к которым они привязаны. Могу ли я, каким-либо образом, расширить объект документа? То есть сейчас чтобы обходится только классом Chat мне приходится использовать такую лапшу, а ведь мне всего навсего нужно только создавать чат в базе данных, если его нет и добавить один проперти-метод.

class Chat(Document):
    bot = ObjectIdField(required=True)
    i = LongField(required=True)
    greeting = BooleanField(default=True, required=True)
    rules = StringField(min_length=2)
    silence_ts = LongField(required=True)
    games = EmbeddedDocumentListField(Game)

    meta = {
        'indexes': [
            {"fields": ["bot", "i"], "unique": True}
        ]
    }

class Chat:
    def __init__(self, bot, i=0):
        self.bot = bot
        self.i = i

    def __getattr__(self, item):
        data = modules.Chat.objects(bot=self.bot.id, i=self.i)

        if not data:
            data = modules.Chat(bot=self.bot.id, i=self.i).save()
        else:
            data = data[0]

        return getattr(data, item)

    @property
    def is_silence(self):
        return self.silence_ts >= tools.ts()


И за это я плачу невозможностью обновлять многие значения "на лету". Приходится вместо
user = modules.User.objects.first()
# ...
user.balance += 1000

Делать
user = User(bot, 1)
# ...
user.update(inc__balance=1000)

Только кажется красиво, но с большими структурами документа, при таком раскладе, можно просто помереть.
  • Вопрос задан
  • 114 просмотров
Решения вопроса 1
YardalGedal
@YardalGedal Автор вопроса
yeah boy
Нашёл для себя такое решение.
class Chat:
    def __init__(self, bot, i=0):
        self._bot = bot

        data = modules.Chat.objects(bot=bot.id, i=i)

        if not data:
            self._data = modules.Chat(bot=bot.id, i=i).save()
        else:
            self._data = data[0]

    def __getattr__(self, item):
        self._data.reload()
        return getattr(self._data, item)

    def __setattr__(self, key, value):
        if key not in ('_data', '_bot'):
            data = self._data.__setattr__(key, value)
            self._data.save()
            return data
        else:
            return super().__setattr__(key, value)


Но осталась проблемка: когда поле является EmbeddedDocumentListField - в него нельзя сделать append / extend / pop и тд.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
alternativshik
@alternativshik
user.balance += 1000
наверное будет неатомарным и все может пойти по *изде (хотя, неизвестно, как ваша обертка для моно работает на этот счет.)
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы