0

I'm trying to build a query to fetch information from my mongoDB but I need to filter the results and only get the corresponding value.

This is the way I have tried until now. I need to match the expensesHouse._id with the id i will pass in the link.

router.get("/showExpense/:id", ensureAuthenticated, (req, res) => {
  House.aggregate([
    {
      expensesHouse: {
        $filter: {
          input: "$expensesHouse",
          as: "each",
          cond: { $eq: ["$$each._id", req.params.id] }
        }
      }
    }
  ]).then(house => {
    console.log(house);
    res.render("houses/showExpense", {
      house: house
    });
  });

The following screen is the mongodb schema. I need to get every value from expensesHouse but only with the 'id' I pass need to match with the expensesHouse.ID

MongoDB Schema

After the result I need to use them here in my handlebars

<form>
                    {{#each house}}
                    {{#each expensesHouse}}
                    <div class="form-group">
                        <label for="expenseType" class="text-dark">Expense Type</label>
                        <input type="text" class="form-control" name="expenseType" value="{{expenseType}}" disabled>
                    </div>
                    <div class="form-group">
                        <label for="description" class="text-dark">Description</label>
                        <input type="text" class="form-control" name="description" value="{{description}}" disabled>
                    </div>
                    <div class="form-group">
                        <label for="price" class="text-dark">Price</label>
                        <input type="text" class="form-control" name="price" value="{{price}}" disabled>
                    </div>

                    <div class="form-group">
                        <label for="status" class="text-dark">Price</label>
                        <input type="text" class="form-control" name="status" value="{{status}}" disabled>
                    </div>
                    {{/each}}
                    {{/each}}
                </form>
3
  • expensesHouse needs to be wrapped inside a $project stage Commented Jan 28, 2020 at 22:09
  • I get this result: [ { _id: 5e2dea5f71cbdd1a6dd1c8fc, expensesHouse: [] }, { _id: 5e2debbf30b9cd1aa5aca711, expensesHouse: [] }, { _id: 5e2f57ad63e463338bc44f9a, expensesHouse: [] }, { _id: 5e2f5b3163e463338bc44f9c, expensesHouse: [] } ] This is the all houses I have but don't get me the right expense. Commented Jan 28, 2020 at 22:18
  • I guess you should use ObjectId object instead of passing a string Commented Jan 28, 2020 at 22:22

2 Answers 2

1

Try these options :

1) Use of $filter-aggregation :

var mongoose = require('mongoose');

router.get("/showExpense/:id", ensureAuthenticated, (req, res) => {
    var id = mongoose.Types.ObjectId(req.params.id);
    House.aggregate([
        {
            $addFields:
            {
                expensesHouse: {
                    $filter: {
                        input: "$expensesHouse",
                        as: "each",
                        cond: { $eq: ["$$each._id", id] }
                    }
                }
            }
        }
    ]).lean().then(house => {
        console.log(house);
        res.render("houses/showExpense", {
            house: house
        });
    })
})

2) Use of $elemMatch-projection :

    var mongoose = require('mongoose');

router.get("/showExpense/:id", ensureAuthenticated, (req, res) => {
    var id = mongoose.Types.ObjectId(req.params.id);
    House.find({ 'expensesHouse._id': id }, {
        members: 1, name: 1, description: 1, address: 1,
        type: 1, user: 1, userID: 1, userType: 1, expensesHouse: { $elemMatch: { _id: id } }, date: 1
    }).then(house => {
        console.log(house);
        res.render("houses/showExpense", {
            house: house
        });
    })
})
Sign up to request clarification or add additional context in comments.

Comments

0

Based on what you said, you're trying to achieve what the operator $elemMatch provides for you.

Try this code and comment below if it helped:

.
. // All the other stuff
.
expensesHouse: {
    $elemMatch: {
        _id: req.params.id // or ObjectId(req.params.id)
    }
}

4 Comments

The $elemMatch get me all the values from my Array and not the specific one..
That isn't how the elemMatch actually works, the problem is that you're using objectId, isn't that so? If it is you need to use _id: ObjectId(req.params.id) . Tell if this way works
I've tested here and it works, I've even updated the answer to support this way
I've updated my query and search with the $elemMatch: _id: ObjectId(req.params.id) but it still retrieves all the expenses and not only the specific id

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.