Considering the following Documents in "Words":
[{
_id: 1,
usages: 2,
word: "Name"
}, {
_id: 2,
usages: 1,
word: "Street"
}, {
_id: 3,
usages: 1,
word: "House"
}, {
_id: 4,
usages: 3,
word: "Table"
}, {
_id: 5,
usages: 3,
word: "Bread"
}, {
_id: 6,
usages: 4,
word: "Door"
}]
How can i get all the records where the number of usages is the lowest or highest? Lowest should return id 2 and 3(and their word), highest should return id 6 with its word.
I need to aggregate this data into a random amount of lowest/highest records (50 to be exact) so it needs to be an aggregate.
It should be a single lookup, so the min/max cannot be found using another query with $max or $min.
The MongoDB version is 3.4.7, Mongoose version 5.0.0-rc1. Mongoose solution not requred since I can use a raw query. (It is preferred however!)
Example:
Words.aggregate([
{
$match: { _
usages: { WHAT_SHOULD_I_HAVE_HERE }
}
}, {
$sample: {
size: 50
}
}
])
Thanks!
You can try below aggregation
$facet
will give you the two lowest and highest value for the usages
and you can easily $project
through them using $filter
operator
db.collection.aggregate([
{ "$facet": {
"minUsages": [{ "$sort": { "usages": -1 } }],
"maxUsages": [{ "$sort": { "usages": 1 } }]
}},
{ "$addFields": {
"lowestUsages": {
"$arrayElemAt": ["$minUsages", 0]
},
"highestUsages": {
"$arrayElemAt": ["$maxUsages", 0]
}
}},
{ "$project": {
"minUsages": {
"$filter": {
"input": "$minUsages",
"as": "minUsage",
"cond": {
"$eq": ["$$minUsage.usages", "$lowestUsages.usages"]
}
}
},
"maxUsages": {
"$filter": {
"input": "$maxUsages",
"as": "maxUsage",
"cond": {
"$eq": ["$$maxUsage.usages", "$highestUsages.usages"]
}
}
}
}}
])
Or you can simply do this with find
query as well
const minUsage = await db.collection.find({}).sort({ "usages": -1 }).limit(1)
const maxUsage = await db.collection.find({}).sort({ "usages": 1 }).limit(1)
const minUsages = await db.collection.find({ "usages": { "$in": [minUsages[0].usages] } })
const maxUsages = await db.collection.find({ "usages": { "$in": [maxUsages[0].usages] } })
Take a look here