Query nel documento nidificato in mongodb

Sep 08 2020

Ecco il mio schema di mangusta:

const chapterSchema = mongoose.Schema({
title: {
    type: String
},
number: {
    type: Number
}
})

const bookSchema = mongoose.Schema({
    title: {
        type: String
    },
    author: {
        type: String
    },
    chapters: [chapterSchema]
})

const Book = mongoose.model('Book', bookSchema)
module.exports = Book

Ecco il mio database:

{
"_id": "5f56f8e66a7eee227c1acc0a",
"title": "Book1",
"author": "Author1",
"chapters": [{
    "_id": "5f56fa47a78fbf03cc32d16d",
    "title": "Chapter1",
    "number": 1
}, {
    "_id": "5f56fad10820300de031317f",
    "title": "Chapter2",
    "number": 2,
}]
}

Voglio trovare un capitolo specifico dall'array dei capitoli in base al suo ID. Quindi, ho scritto questo codice:

router.get('/:id', async function (req, res) {
try {
    const id = req.params.id
    await Book.findById(id, function (err, chapter) {
        res.render('chapter.hbs', {
            chapter: chapter
        })
    })
} catch (error) {
    res.redirect('/')
}
})

Secondo l'id del capitolo, voglio questo risultato:

{
    "_id": "5f56fa47a78fbf03cc32d16d",
    "title": "Chapter1",
    "number": 1
}

o

{
    "_id": "5f56fad10820300de031317f",
    "title": "Chapter2",
    "number": 2,
}

Cosa devo fare per trovare un capitolo specifico utilizzando il suo ID?

Risposte

r7r Sep 08 2020 at 06:05

Stai cercando su Book usando findById dei capitoli Id, non darà risultati poiché non è Book Id,

Dovrai usare $elemMatchper questo

controllare questo Interrogazione per oggetto in Mongoose Sub Array per riferimento

ProsenGhosh Sep 08 2020 at 08:37

Puoi farlo utilizzando la funzione di aggregazione .

router.get('/:id', async function (req, res) {
  try {
    const id = req.params.id
    await Books.aggregate([
      {
        $project: { title: 1, author: 1, chapters: { $filter: {
              input: "$chapters", as: "chapter", cond: { $eq: [
                  "$$chapter.id", id
                ]
              }
            }
          }
        }
      }
    ])
  } catch (error) {
    res.redirect('/')
  }
})
turivishal Sep 09 2020 at 12:10

Puoi usare la aggregate()funzione,

  • $match la tua condizione
  • $filter per ottenere l'ID del capitolo specifico
  • $replaceWith per sostituire il capitolo nella radice
const id = mongoose.Types.ObjectId(req.params.id);

let chapter = await Book.aggregate([
  { $match: { "chapters._id": id } },
  {
    $replaceWith: { $arrayElemAt: [
        {
          $filter: { input: "$chapters",
            cond: { $eq: ["$$this._id", id] }
          }
        },
        0
      ]
    }
  }
]);

console.log(chapter);

Terreno di gioco