I’m trying to build a table with values from an Array of objects from mongodb, but I only can get every value and only need the specific value.
So I made a query like this
router.get("/arquiveExpense", ensureAuthenticated, (req, res) => {
House.find({
userID: req.user.id,
expensesHouse: { $elemMatch: { status: "Private" } }
}).then(house => {
console.log(house);
res.render("houses/arquiveExpense", {
house: house
});
});
});
I want to retrieve the specific value from expensesHouse with status ‘Private’.
And in handlebars I have this structure
<tbody>
<tr>
{{#each house}}
<td>{{expenseType}}</td>
<td>{{price}}€</td>
<td>{{payAt}}</td>
<td>{{formatDate date 'MMMM Do YYYY'}}</td>
<td>
<a href="/houses/showExpense/{{id}}" id="detailsExpense"
class="btn btn-outline-light mb-3"><i class="fas fa-eye mr-2"></i>Details
</a>
<td>
<a href="/houses/editExpense/{{id}}" id="editExpense" class="btn btn-outline-light mb-3"><i
class="fas fa-edit mr-2"></i>Edit
</td>
</tr>
{{else}}
<p>No expenses</p>
{{/each}}
</tbody>
And after this handlebars, this is the result
The Schema structure is the follow
So I want to show in the web page the value from expensesHouse with the Status ‘Private’.
How can I change my code to retrieve only this value ?
snigo
January 26, 2020, 9:09pm
2
Did you try like this?
expensesHouse: { $elemMatch: { status: { $eq: 'Private' } } }
1 Like
Didn’t work too… I retrieve the private match but only one and I need every register with private status…
snigo
January 26, 2020, 11:24pm
4
It’s not clear what’s your goal. Do want to show all the private expenses of all the houses with specific userID?
1 Like
But if I have two or more values with status ‘Private’ I want them too…
My goal is:
I have my array with multiple expenses, privates and public and I want to retrieve all info with specific userID and status = ‘Private’ or ‘Public’.
snigo
January 27, 2020, 5:20pm
10
So this thing will find all the houses where userID matches and expensesHouse will have at least one element with status set to 'Private':
House.find({
userID: req.user.id,
expensesHouse: { $elemMatch: { status: { $eq: 'Private' } }
})
Then in then():
.then((houses) => {
res.render('houses/arquiveExpense', { house: filterByExpenses(houses, 'Private') });
});
function filterByExpenses(houses, expenseStatus) {
return houses
.map((house) => ({
...house,
expensesHouse: house.expensesHouse
.filter(({ status }) => status === expenseStatus)
}));
}
I guess this will get you the right result, however your handlebars code is hugely unprepared - for starters, you have nested array in each house, therefore you need two #each loops, one for each house and one for each expense. Secondly they both need to be outside <tr> tag.
Good luck!
2 Likes
I just figured out after the ‘RandellDawson’ answer if I use the $elemMatch I never see all the results.
So i change my router to something like this:
outer.get("/dashboard", ensureAuthenticated, (req, res) => {
House.aggregate([
{
$match: { members: req.user.id }
},
{
$unwind: "$expensesHouse"
},
{
$match: { "expensesHouse.status": "Public" }
}
]).then(house => {
console.log(house);
res.render("houses/dashboard", {
house: house
});
});
});
And in my
inside handlebars I have something like this:
<tbody>
{{#each house}}
<tr>
{{!-- {{#each expensesHouse}} --}}
<td>{{expensesHouse.expenseType}}</td>
<td>{{expensesHouse.price}}€</td>
<td>{{expensesHouse.payAt}}</td>
<td>{{formatDate date 'MMMM Do YYYY'}}</td>
<td>
<a href="/houses/showExpense/{{id}}" id="detailsExpense"
class="btn btn-outline-light mb-3"><i class="fas fa-eye mr-2"></i>Details
</a>
<td>
<a href="/houses/editExpense/{{id}}" id="editExpense"
class="btn btn-outline-light mb-3"><i class="fas fa-edit mr-2"></i>Edit
</td>
</tr>
{{!-- {{/each}} --}}
{{else}}
<p>No expenses</p>
{{/each}}
</tbody>
So the problem is solved !