выполнить общий поиск в документе mongoengine, чтобы найти экземпляр конкретного значения

Вопрос или проблема

Я создал базу данных в mongodb и настроил mongoengine в Python для взаимодействия с ней. Следующий шаг – настроить запрос, который будет проходить через документы и искать конкретные значения. У меня есть базовая настройка, но я надеялся на что-то более динамичное.

from mongoengine import Document, EmbeddedDocument, StringField, IntField, EmbeddedDocumentField, MapField, Q

class games(EmbeddedDocument):
    game_name = StringField()

class PlayersDocument(Document):
    name = StringField()
    games = MapField(EmbeddedDocumentField(games), db_field="console")

def search_document(console, game_name)
    query = Q(**{f'games__{console}__game_name': game_name})
    PlayersDocument.objects(query)

Я надеялся превратить это в общую настройку, где он будет просматривать вложенные документы, не уточняя их. Тем не менее, многие из моих попыток не сработали.

def search_document(game_name)
    query = Q(**{'games__{}__game_name': game_name})
    PlayersDocument.objects(query)

def search_document(game_name)
    query = Q(**{'games__$in__game_name': game_name})
    PlayersDocument.objects(query)

Ответ или решение

Чтобы выполнить общий поиск в документе MongoEngine и найти экземпляры конкретного значения в вложенных документах, необходимо учитывать структуру ваших документов и возможность динамического формирования запросов. Ваше текущее решение уже предлагает хороший базовый подход, но может быть улучшено для работы с любым количеством вложенных документов.

Структура данных

Вы определили класс PlayersDocument, который представляет документ в коллекции с полями name и games. Поле games представляет собой MapField, где ключи соответствуют консолям, а значения — вложенные документы типа games, содержащие название игры.

Проблема поиска

Ваша задача — сделать функцию поиска, которая может динамически обрабатывать любое название консоли, не указывая его заранее в запросе. Чтобы достичь этого, вам нужно применять следующий подход:

  1. Извлечение ключей консоли: Необходимо получить все ключи из поля games для выполнения поиска по всем играм, независимо от консоли.
  2. Формирование динамического запроса: Быть способным создавать запросы в зависимости от наличия ключей.

Пример решения

Вот обновленная версия вашей функции поиска, которая решает поставленную задачу:

from mongoengine import Document, EmbeddedDocument, StringField, MapField, EmbeddedDocumentField, Q

class Games(EmbeddedDocument):
    game_name = StringField()

class PlayersDocument(Document):
    name = StringField()
    games = MapField(EmbeddedDocumentField(Games), db_field="console")

def search_document(game_name):
    # Получаем все документы
    players = PlayersDocument.objects()
    result = []

    # Перебираем все документы
    for player in players:
        # Перебираем все консоли и их игры
        for console, games in player.games.items():
            if games.game_name == game_name:
                result.append(player)

    return result

Объяснение кода

  1. Получение всех документов: Мы извлекаем все экземпляры PlayersDocument из базы данных.
  2. Перебор документов и вложенных игр: С помощью вложенного цикла мы перебираем каждый документ, а затем — все ключи консоли и их соответствующие игры.
  3. Сравнение имен игр: Если game_name из вложенного документа совпадает с заданным значением, мы добавляем экземпляр игрока в результирующий список.

Заключение

При таком подходе вы сможете гибко и динамично находить игры в ваших документах, не ограничиваясь структурой отдельных консольных ключей. Это решение эффективно использует вложенные документы, следуя принципам MongoDB и ООП в Python. Одно из ключевых преимуществ — это гибкость, что позволяет вам добавлять новые консолей и игры без изменения основной логики поиска.

Такой метод не только отвечает вашим требованиям, но и представляет собой простое и расширяемое решение для работы с MongoDB через возможностям MongoEngine.

Оцените материал
Добавить комментарий

Капча загружается...