Home > Software engineering >  How do I query an array within a schema in mongoose?
How do I query an array within a schema in mongoose?

Time:10-26

Really stuck on querying an array nested within a schema.

The list schema looks likes this:

const listSchema = new mongoose.Schema({
  name: String,
  items: [cardSchema]
});

I want to be able to query a particular list for a particular item, and figured this would work:

const listId = req.body.listId;
const itemId = req.body.itemId;

List.updateOne({
    "_id": listId
}, {
    $pull: {
        items: {
            "_id": itemId
        }
    }
});

As I understand, I'm updating a list by the id of "listId", and then removing something from it. The thing I'm removing is within the "items" array and has the id "itemId". However, this doesn't do anything.

I have a much clumsier, heavy-handed way of getting round this problem, shown here:

List.findOne({
    _id: listId
}, function (err, list) {
    if (err) {
        console.log(err)
    } else {
        const listItems = list.items
        listItems.forEach(function (item) {
            if (item._id == itemId) {
                const index = listItems.findIndex(function (i) {
                    return i.id === itemId
                })
                if (index !== -1) listItems.splice(index, 1);
                list.save();
            }
        })
    }

But I'd much rather something like the former. The latter just seems ridiculous when nesting arrays within arrays within arrays etc so I know this can't be the sensible way.

CodePudding user response:

I found the solution eventually:

List.findOne({listId}, function (err, list) {
    list.items.id(itemId).remove();
    list.save();            
});

CodePudding user response:

Given the following Schema:

const listSchema = new mongoose.Schema({
  name: String,
  items: [cardSchema]
});

and the following ids:

const listId = req.body.listId;
const itemId = req.body.itemId;

If your final goal is to remove item with itemId, I believe the code below should do the trick:

List.findOneAndUpdate(
    { "_id": listId },
    { $pull: { items: { _id: itemId} } },
    { 'new': true }
);

The core idea is this:

Collection.findOneAndUpdate(
    { _id: yourCollectionId },
    { $pull: { subdocumentsArray: { _id: subdocumentId} } },
    { new: true }
)
  • Related