Mongodb aggregate $gt returns non matching records - mongodb

I would like to count the sum of a field in my database.
I have this pipeline in mongodb:
{
match: {
'user1': user.id,
'unreadMessagesCount': { $exists: true, $gt: 0 },
}
},
{
group: {
objectId: null,
total: { $sum: "$unreadMessagesCount" },
count: { $sum: 1 }
}
}
The results returned is
{total: 3, count: 30}
The total is correct because I only have 3 records with 1 unreadMessagesCount each. But the count returned is 30 which is wrong. There should only be 3 records matched. When i remove group from pipeline, I get 30 records.

Related

How to check a field is increasing continuously or not in MongoDB

I have a DB with about 500K document in MongoDB. My DB has a field number starting from 1 and increasing continuously. After I count total of the document, I realize some documents are missing (last number field is greater than total document, instead of equal). How can I check which document is missing? A document has the form:
{
"_id" : ObjectId("abc"),
"number" : 499661
}
You can try this approach. Consider you have these documents with missing numbers 1 and 4:
{ number: 0 }
{ number: 2 }
{ number: 3 }
{ number: 5 }
{ number: 6 }
To find the two missing numbers, try this aggregation:
db.test.aggregate([
{
$group: {
_id: null,
nums: { $push: "$number" }
}
},
{
$project: {
_id: 0,
missing_numbers: { $setDifference: [ { $range: [ 0, 7 ] }, "$nums" ] }
}
},
])
The output: { "missing_numbers" : [ 1, 4 ] }

Problem with an aggregated query in mongoDB

I have the following collection in mongodb:
IDcustomer. idServicerequired. ...
001. 13
002. 15
002. 19
002. 10
003. null
From this, i want to get the average number of services required by each customer (in this case, the output should be (1+3+0)/3 = 1.34)
I tried as follows, but in this way, for each customer that has required no service, it is counted 1, as if he had required one service, so the average is higher than expected (in this case it would be (1+3+1)/3=1.67)
first group, check condition if idServicerequired is null then count 0
second $group by null and average count
db.collection.aggregate([
{
$group: {
_id: "$idCustomer",
count: {
$sum: {
$cond: [{ $eq: ["$idServicerequired", null] }, 0, 1]
}
}
}
},
{
$group: {
_id: null,
count: { $avg: "$count" }
}
}
])
Playground

How to count total customers using MongoDB?

Here is the example of the JSON. I want to count the total customers by unique "email_address" and filter by "transactions_status" equal to "S".
Expected output:
{
_id: null,
count: total amount of customers with an unique email address and filtered by status equal S
}
You can try this aggregations pipeline:
Filter by "transactions_status" equal to "S".
Group distinct emails.
Project the count field with the emails's size.
db.collection.aggregate([
{
$match: {
"transaction_info.transaction_status": "S"
}
},
{
$group: {
_id: null,
emails: {
$addToSet: "$payer_info.email_address"
}
}
},
{
$project: {
count: {
$size: "$emails"
}
}
}
]);

How to get the real count of matching documents when using limit in mongodb?

I have a facet aggregation in mongodb. It works. Now, I need to limit the result in order to have an infinite scroll. How to get the total count of matching documents in the entire collection?
I can get the total count of documents in the collection, but this number is not relevant. My goal is to know if the user can fetch more data. If he has received 120 documents, but 150 matches his filter, then another query can be performed.
Here is my query:
db.collection.aggregate([
{
$facet: {
data: [
{ $match: { score: {$gt: 80 } } },
{ $skip: 0},
{ $limit: 2},
{ $project: { score: 1 } }
],
}
},
])
You can play with fake data in this sandbox: https://mongoplayground.net/p/EClbe0f_Fms
The real number of matching documents is 4. If I add a "hits" after the facet with the $count operator, I receive 7, which the the total of documents. How to get this information in an efficient way?
The most efficient way would be not to use $count at all but rather to check if the last page received was less than the limit. Ie:
const perPage = 10;
const results = await getPageOfResults();
const atEnd = results.length < perPage;
It sound like you added $count to your facet already but got an incorrect result. To get the 'real' number of matching documents you need to add the $match stage to both facets like so https://mongoplayground.net/p/liQaiyZhYER
db.collection.aggregate([
{
$facet: {
data: [
{ $match: { score: {$gt: 80 } } },
{ $skip: 0},
{ $limit: 2},
{ $project: { score: 1 } }
],
count: [
{ $match: { score: {$gt: 80 } } },
{ $count: 'total' }
]
}
},
{$unwind: "$count"},
{$addFields: {
count: "$count.total"
}}
])

How to retrieve specific keys when grouping on mongo while using $max on a field?

How can i retrieve keys beyond the grouped ones from mongodb?
Documents example:
{code: 'x-1', discount_value: 10, type: 1}
{code: 'x-2', discount_value: 8, type: 1}
{code: 'x-3', discount_value: 5, type: 2}
Query:
{
$match: {
type: 1
}
},
{
$group: {
_id: null
discount_value: {$max: '$discount_value'}
}
}
This query will retrieve the max value from discount_value (10) key and the key _id but how i can do to retrieve the code and type key as well if i don't have operation to do those keys?
The current result:
{_id: null, discount_value: 10}
Expected result:
{_id: null, discount_value: 10, type: 1, code: 'x-1'}
You can try below query :
db.collection.aggregate([
{
$match: { type: 1 }
},
{
$group: {
_id: null,
doc: {
$max: {
discount_value: "$discount_value",
type: "$type",
code: "$code"
}
}
}
}
])
I believe it would get $max on field discount_value and get respective type & code values from the doc where discount_value is max.
In another way, since you're using $match as first stage, I believe your data will be less enough to perform $sort efficiently :
db.collection.aggregate([
{
$match: { type: 1 }
},
{
$sort: { discount_value: -1 } // sort in desc order
},
{
$limit: 1
}
])
Test : mongoplayground
Note :
Test the first query on DB itself rather than in playground. In first query you can use $replaceRoot as last stage if you wanted to make doc field as root of your document.