Pipelines de agregação do MongoDB com objeto vinculado
Estou ligando dois objetos em uma consulta e uso a função de agregação para isso. Alguns dados estão localizados e estou usando uma solução daqui para obter dados para o local especificado.
Estou lutando para fazer o mesmo com os dados do objeto vinculado (quartos). Especificamente, liste os dados para a localidade fornecida em roomDetails.
Por favor, dê uma olhada no playground Mongo
Respostas
Você só precisa adicionar o filtro em seu segundo $addFieldsestágio que você está filtrando roomTypese o resto dos estágios seria o mesmo, apenas destaque o novo código abaixo do comentário inicial e final,
Estou sugerindo esta solução em sua consulta implementada, não tenho certeza se esta é a abordagem certa para fazer isso, pode ser mais causará o desempenho da consulta.
$reducepara iterar o loop doroomDetails.descriptionarray $ cond para corresponder ao local e retornar o resultado da correspondência para o valor, mesmo processo para oroomDetails.titlearray, e mesclar estes 2 campos atualizados com o objeto atual usando$mergeObjects
{
$addFields: { roomTypes: { $map: {
input: "$roomTypes", in: { $mergeObjects: [
"$$this",
{
Começar:
roomDetails: {
$mergeObjects: [
"$$this.roomDetails", { description: { $reduce: {
input: "$$this.roomDetails.description", initialValue: "", in: { $cond: [
{ $eq: ["$$this.locale", "pl"] },
"$$this.value", "$$value"
]
}
}
},
title: {
$reduce: { input: "$$this.roomDetails.title",
initialValue: "",
in: {
$cond: [ { $eq: ["$$this.locale", "pl"] }, "$$this.value",
"$$value"
]
}
}
}
}
]
},
~ Fim ~
available: {
$reduce: {
input: "$$this.capacity", initialValue: 0, in: { $cond: [
{ $eq: ["$$this.cruiseID", "$cruiseID"] }, "$$this.available",
"$$value"
]
}
}
}
}
]
}
}
}
}
}
Parque infantil
Na opção genérica que respondi em sua pergunta de referência, você pode usar a mesma função como,
function languageFilter(inputField, locale) {
return {
$reduce: {
input: inputField,
initialValue: "",
in: {
$cond: [{ $eq: ["$$this.locale", locale] }, "$$this.value", "$$value"]
}
}
};
}
Sua consulta final seria:
let locale = "pl";
db.cs.aggregate([
{ $match: { cID: "00001" } },
{
$lookup: { from: "rooms", localField: "roomTypes.roomID", foreignField: "roomID", as: "roomTypes" } }, { $addFields: {
title: languageFilter("$title", locale), description: languageFilter("$description", locale),
roomTypes: {
$map: { input: "$roomTypes",
in: {
$mergeObjects: [ "$$this",
{
roomDetails: {
$mergeObjects: [ "$$this.roomDetails",
{
description: languageFilter("$$this.roomDetails.description", locale), title: languageFilter("$$this.roomDetails.title", locale)
}
]
},
available: {
$reduce: { input: "$$this.capacity",
initialValue: 0,
in: {
$cond: [ { $eq: ["$$this.cruiseID", "$cruiseID"] },
"$$this.available", "$$value"
]
}
}
}
}
]
}
}
}
}
},
{
$project: {
_id: 0,
"roomTypes": { _id: 0 },
"roomTypes.capacity": 0
}
}
]);