I have an addressmodel like this:
const AddressSchema = new Schema({
address: String,
city: String,
postal_code: String,
country: String,
user_id: String,
postalCodeMeters: Number,
});
And I want to know (for a certain user at a certain postal_code):
- How many unique addresses have been visited
- How many times have the user visited this postal code
- How many meters have they traveled
This code works, but I want to do it in one query, not two:
addressrouter.get("/isexplored/:userid/:postalcode",
async (req, res) => {
console.log(req.params.userid)
try {
const addresses = await Address.aggregate(
[
{ $match:{
user_id: req.params.userid,
postal_code: req.params.postalcode
}},
{$group: {
_id: null,
meters: {$sum: "$postalCodeMeters"},
count: { $sum: 1 }
}
}]
)
console.log(addresses)
const uniqueAddresses = (await Address.find(
{
user_id: req.params.userid,
postal_code: req.params.postalcode
}
).distinct('address')).length
res.json({
time: addresses[0].count,
uniqueAddressesVisited: uniqueAddresses,
meters: addresses[0].meters
});
} catch (err) {
console.log(err)
res.json({ message: err });
}
}
)
CodePudding user response:
If I've understood correctly you can do it in a single $group operation.
Check this query where using $addToSet in the $group stage we can get the unique values. And after that use $size into project to know the length.
Address.aggregate([
{
"$match": {
"user_id": req.params.userid,
"postal_code": req.params.postalcode
}
},
{
"$group": {
"_id": null,
"meters": {
"$sum": "$postalCodeMeters"
},
"count": {
"$sum": 1
},
"address": {
"$addToSet": "$address"
}
}
},
{
"$project": {
"_id": 0,
"count": 1,
"meters": 1,
"uniqueAddressesVisited": {
"$size": "$address"
}
}
}
])
Example here
