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)

Только кажется красиво, но с большими структурами документа, при таком раскладе, можно просто помереть.
  • Вопрос задан
  • 104 просмотра
Решения вопроса 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
наверное будет неатомарным и все может пойти по *изде (хотя, неизвестно, как ваша обертка для моно работает на этот счет.)
Ответ написан
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы
23 марта 2019, в 16:34
700 руб./за проект
23 марта 2019, в 15:42
400 руб./в час