MongoDb - Как вернуть поле вложенного вложенного документа только при использовании агрегации поиска?
Я очень плохо знаком с MongoDb, поэтому я привык к SQL. Прямо сейчас у меня есть две коллекции в моей базе данных:
1) Серия (в которой есть вложенные поддокументы)
2) Рецензия (решили сослаться на поддокумент эпизода, потому что будет много рецензий)
Смотрите эту картинку для лучшего понимания.
Теперь я хочу добиться следующего. Для каждого обзора (два в данном случае) я хочу получить название эпизода.
Я попробовал следующее:
db.review.aggregate([
{
$lookup:{
from:"series",
localField:"episode",
foreignField:"seasons.episodes._id",
as:"episode_entry"
}
}
]).pretty()
Проблема в том, что это возвращает (конечно) не только название эпизода, на который есть ссылка, но и документ всего сезона.
Смотрите картинку ниже для моего текущего выхода.
Я не знаю, как этого добиться. Пожалуйста, помогите мне. Я использую Mongo 3.4.9
1 ответ
Я бы порекомендовал следующую структуру серии, которая разматывает массив сезонов на несколько документов, по одному на каждый сезон.
Это поможет вам вставить / обновить эпизоды напрямую.
Что-то вроде
db.series.insertMany([
{
"title": "Sherlock Holmes",
"nr": 1,
"episodes": [
{
"title": "A Study in Pink",
"nr": 1
},
{
"title": "The Blind Banker",
"nr": 2
}
]
},
{
"title": "Sherlock Holmes",
"nr": 2,
"episodes": [
{
"title": "A Scandal in Belgravia",
"nr": 1
},
{
"title": "The Hounds of Baskerville",
"nr": 2
}
]
}
])
Запрос поиска будет делать что-то вроде этого
episode: { $in: [ episodes._id1, episodes._id2, ... ] }
Из документов
Если поле содержит массив, то оператор $ in выбирает документы, в поле которых содержится массив, который содержит хотя бы один элемент, соответствующий значению в указанном массиве (например, и т. Д.).
Так что поиск вернет все эпизоды, когда есть совпадение. Затем вы можете отфильтровать, чтобы сохранить только тот, который соответствует эпизоду вашего обзора.
Так что запрос будет выглядеть
db.review.aggregate([
{
"$lookup": {
"from": "series",
"localField": "episode",
"foreignField": "episodes._id",
"as": "episode_entry"
}
},
{
"$addFields": {
"episode_entry": [
{
"$arrayElemAt": {
"$filter": {
"input": {
"$let": {
"vars": {
"season": {
"$arrayElemAt": [
"$episode_entry",
0
]
}
},
"in": "$$season.episodes"
}
},
"as": "result",
"cond": {
"$eq": [
"$$result._id",
"$episode"
]
}
}
}
},
0
]
}
}
])