Вопрос или проблема
Я создал базу данных в 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
, содержащие название игры.
Проблема поиска
Ваша задача — сделать функцию поиска, которая может динамически обрабатывать любое название консоли, не указывая его заранее в запросе. Чтобы достичь этого, вам нужно применять следующий подход:
- Извлечение ключей консоли: Необходимо получить все ключи из поля
games
для выполнения поиска по всем играм, независимо от консоли. - Формирование динамического запроса: Быть способным создавать запросы в зависимости от наличия ключей.
Пример решения
Вот обновленная версия вашей функции поиска, которая решает поставленную задачу:
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
Объяснение кода
- Получение всех документов: Мы извлекаем все экземпляры
PlayersDocument
из базы данных. - Перебор документов и вложенных игр: С помощью вложенного цикла мы перебираем каждый документ, а затем — все ключи консоли и их соответствующие игры.
- Сравнение имен игр: Если
game_name
из вложенного документа совпадает с заданным значением, мы добавляем экземпляр игрока в результирующий список.
Заключение
При таком подходе вы сможете гибко и динамично находить игры в ваших документах, не ограничиваясь структурой отдельных консольных ключей. Это решение эффективно использует вложенные документы, следуя принципам MongoDB и ООП в Python. Одно из ключевых преимуществ — это гибкость, что позволяет вам добавлять новые консолей и игры без изменения основной логики поиска.
Такой метод не только отвечает вашим требованиям, но и представляет собой простое и расширяемое решение для работы с MongoDB через возможностям MongoEngine.