This question already has answers here:
MongoDB SELECT COUNT GROUP BY
(9 answers)
Closed 3 years ago.
I am performing an aggregation query.My requirement is that I have docs in following format:
{
"name":"a","age":20},
{
"name":"b","age":23},
{
"name":"a","age":26}
I need to sum the ages of all names who have "a" in their name field.
I am doing the following but it gives me an error that "The field 'name' must be an accumulator object":
db.collection('students').aggregate({
$group: {"name": "a", "sum": {$sum: '$age'}}
}, {
$project: {sum: '$sum'}
}, (e, d) => {
if (!e) {
var e = d.stream({transform: JSON.stringify});
console.log("answer")
console.log(e);
deferred.resolve(e);
} else {
console.log(e)
}
})
I altered your aggregation query.Try as below:
db.collection('students').aggregate(
[
{
$match: {
name: "a"
}
},
{
$group: {_id: "$name",
"sum": {
$sum: '$age'
}
}
},
{
$project: {
sum: 1
}
], (e, d) => {
if (!e) {
var e = d.stream({transform: JSON.stringify});
console.log("answer")
console.log(e);
deferred.resolve(e);
} else {
console.log(e)
}
})
Here, you are missing match filter properly. We should use $match filter to find out specific results and "_id" for attribute on which we are performing operation in $group.
Structure of your query would be -
db.students.aggregate(
[
{
$match: {
"name": "a"
}
},
{
$group: {
"_id": "$name",
totalTte: {
$sum: "$age"
}
}
},
{
$project: {
sum: 1
}
}
])
Related
I'm working with a MongoDB collection that has a lot of duplicate keys. I regularly do aggregation queries to find out what those duplicates are, so that I can dig in and find out what is and isn't different about them.
Unfortunately the database is huge and duplicates are often intentional. What I'd like to do is to find the count of keys that have duplicates, instead of printing a result with thousands of lines of output. Is this possible?
(Side Note: I do all of my querying through the shell, so solutions that don't require external tools or a lot of code would be preferred, but I understand that's not always possible.)
Example Records:
[
ObjectId("622f2d94ecf6a5076c2e230b"),
ObjectId("622f329c6f10fe0490252611"),
ObjectId("623026366f10fe0490254341"),
ObjectId("623026de6f10fe0490254583"),
ObjectId("6234346adec0b842dcceb790"),
ObjectId("623434a86f10fe0490260db6"),
ObjectId("62382f91dab1e245d4e152f4"),
ObjectId("6238303b6f10fe0490265acf"),
ObjectId("623bf2af700224301c756394"),
ObjectId("623bf2f76f10fe04902729a4"),
ObjectId("623c5a1f282a052c3c0bbdfd"),
ObjectId("624bf013383df47699e6b141")
]
Here is the query that I've been using to find duplicates based on key:
db.getCollection('weldtestings').aggregate([
{
$match: {
weldId: {
$in: [
ObjectId("622f2d94ecf6a5076c2e230b"),
ObjectId("622f329c6f10fe0490252611"),
ObjectId("623026366f10fe0490254341"),
ObjectId("623026de6f10fe0490254583"),
ObjectId("6234346adec0b842dcceb790"),
ObjectId("623434a86f10fe0490260db6"),
ObjectId("62382f91dab1e245d4e152f4"),
ObjectId("6238303b6f10fe0490265acf"),
ObjectId("623bf2af700224301c756394"),
ObjectId("623bf2f76f10fe04902729a4"),
ObjectId("623c5a1f282a052c3c0bbdfd"),
ObjectId("624bf013383df47699e6b141")]
}
}
},
{
$facet: {
"NDEfailedDate": [
{
$match: { testResult: 'Failed' }
},
{
$group: {
_id: { $dateToString: { format: "%Y-%m-%d", date: "$testDate" } },
count: { $sum : 1 }
}
},
{ $sort: { _id: 1 } }
],
"NDEfailedCount": [
{
$match: { testResult: 'Failed' }
},
{
$group: {
_id: "$weldId",
data: { "$addToSet": "$testDate" }
}
},
{ $count: "totalCount" }
],
}
}
])
Which gives me an output of:
{
"NDEfailedDate" : [
{
"_id" : "2022-04-08",
"count" : 6.0
}
],
"NDEfailedCount" : [
{
"totalCount" : 5
}
]
}
The result I want to get instead:
"_id" : "2022-04-08",
"count" : 5
db.collection.aggregate([
{
$project: {
_id: {
$first: "$NDEfailedDate._id"
},
count: {
$first: "$NDEfailedCount.totalCount"
}
}
}
])
mongoplayground
Orders.aggregate([{$match: { shippingType: "standardShipping" }},
{ $project: { standardShippingCount: { $size: "$products" } } },
])
Orders.aggregate([{$match: { shippingType: "expressShipping" } },
{ $project: { expressShippingCount: { $size: "$products" } } },
])
I need help to find out if it's possible to write these 2 queries in 1. Any help is appericated.
If you only need the number of total products ordered with each shippingType from the whole collection, then you can use this aggregate query
[
{
$unwind: {
path: "$products"
},
},
{
$group: {
_id: "$shippingType",
count: {
$count: {}
}
}
},
]
It will give you a response in this format
[
{
"_id": "expressShipping",
"count": 14
},
{
"_id": "standardShipping",
"count": 6
}
]
Now to convert it into a format that suits your use-case
queryResponse.reduce((acc, curr) => {
acc[`${curr._id}Count`] = curr.count;
return acc;
}, {})
Finally, you'll have this
{
expressShippingCount: 14,
standardShippingCount: 6
}
This question already has answers here:
Find in Double Nested Array MongoDB
(2 answers)
Closed 3 years ago.
My model called Residence
{
"_id": { "$oid": "5d88dfe45feb4c06a5cfb762" },
"spaces": [{
"_id": { "$oid": "5d88dfe45feb4c06a5cfb76f" },
"name": "Building 2",
"subSpace": [
{
"_id": { "$oid": "5d88dfe45feb4c06a5cfb771" },
"name": "Basement"
},
{
"_id": { "$oid": "5d88dfe45feb4c06a5cfb770" },
"name": "Floors" // Get only the name by Id
}
]
}
}
To find a spaceName by Id (OK)
exports.getSpaceNameById = (spaceId) => {
return Residence.find({ 'spaces._id': spaceId }, { _id: 0, spaces: { $elemMatch: { _id: spaceId } } })
}
Now I want to have the subSpace name requested by Id.
But my dream would be to have both (query by subSpace Id, for this example : 5d88dfe45feb4c06a5cfb770) : spaceName / subSpaceName only with 1 request.
Thanks for your help.
UPDATE 1
I try this method but the response is an empty array
exports.getSubSpaceNameById = (spaceId) => {
return Residence.aggregate([
{ $match: {'spaces.subSpace._id': spaceId}},
{ $project: {
'spaces.subSpace': { $filter: {
input: '$spaces.subSpace',
as: 'mySubSpace',
cond: { $eq: ['$$mySubSpace._id', spaceId]}
}},
_id: 0
}}
])
}
The following should work for you. This query would return the whole document.
By name:
db.collection.find({"spaces.subSpace.name": "Basement"})
By _id: db.collection.find({"spaces.subSpace._id": "YOUR_ID"})
Try this query
db.testers.aggregate([
{
$addFields:{
"spaces":{
$map:{
"input":"$spaces",
"as":"doc",
"in":{
$mergeObjects:[
"$$doc",
{
"subSpace":{
$filter:{
"input":"$$doc.subSpace",
"as":"sn",
"cond": {
"$and": [
{ "$eq": [ "$$sn._id", "5d88dfe45feb4c06a5cfb770" ] },
]
}
}
}
}
]
}
}
}
}
}
]).pretty()
Try something like this:
find({spaces._id:id})
This question already has answers here:
Getting a list of unique embedded/nested objects in a MongoDB document
(4 answers)
Closed 5 years ago.
I have a document, Model like this:
{
name: String,
user: String,
components: [{
alias: String,
name: String,
...etc...
}]
}
I'd like to formulate a reponse that just returns an array of component.alias for a given document.
E.g, if I have:
{
name: "doc1",
components: [{alias: "alias1", ...}, {alias: "alias2", ...}]
}
I'd like to just end up with ["alias1", "alias2"]
So far I have:
Model.findById(
modelId,
{ "components.alias": 1, _id: 0 },
(err, docs) => {
console.log(docs)
}
);
But this gives me:
{
"components": [
{
"alias": "alias1"
}
]
}
Any ideas?
Use aggregate for that, MongoDB query for that.
db.getCollection('Model').aggregate([
{ "$unwind": "$components" },
{ "$group": { "_id": "$components.alias" }}
]).map(function(el) { return el._id })
Node.js code
Model.aggregate([
{ "$match": { "name": "doc1" } }, // any condition
{ "$unwind": "$components" },
{ "$group": { "_id": "$name", components: { $push: "$components.alias" } } }
]).then((data)=>console.log(data))
Output:
{
"_id": "doc1",
"emails": [
"alias1",
"alias2"
]
}
I am new to nodejs, I am trying to get the all duplicate documents in a collection in mongoDB for that I have tried the following query in mongo shell
db.collection.aggregate([
{
$group: {
_id: {
ProductName: "$ProductName"
},
uniqueIds: {
$addToSet: "$_id"
},
count: {
$sum: 1
}
}
},
{
$match: {
count: {
$gte: 2
}
}
},
{
$sort: {
count: -1
}
}
])
In mongo shell result:
{
"_id" : {
"ProductName" : "Sony Mobile"
},
"uniqueIds" : [
ObjectId("5728ce42a069270e00e59910"),
ObjectId("5728cde6a069270e00e5990e")
],
"count" : 2
},
{
"_id" : {
"ProductName" : "Nokia Mobile"
},
"uniqueIds" : [
ObjectId("5728ce42a069270e00e59920"),
ObjectId("5728cde6a069270e00e5990f")
],
"count" : 2
}
In mongo shell it gaves the result what i want correctly, but i tried the same query in nodejs server side function like below
Company.aggregate([
{
$group: {
_id: {
Proname: "$Proname"
},
uniqueIds: {
$addToSet: "$_id"
},
count: {
$sum: 1
}
}
},
{
$match: {
count: {
$gte: 2
}
}
},
{
$sort: {
count: -1
}
}
]).then(function (dupProds) {
console.log("ALL DUPLICATE PRDCTS : " + JSON.stringify(dupProds));
})
};
It shows me an error that Compnay.aggregate(...).then is not a function, I tried in different ways but no use, now how can get the result same as like I got in mongoshell.
Use exec instead of then for mongoose and in callback function parameters error then result.
Company.aggregate([
{
$group: {
_id: {
Proname: "$Proname"
},
uniqueIds: {
$addToSet: "$_id"
},
count: {
$sum: 1
}
}
},
{
$match: {
count: {
$gte: 2
}
}
},
{
$sort: {
count: -1
}
}
]).exec(function (err,dupProds) {
if(err) {
// return err;
}
console.log("ALL DUPLICATE PRDCTS : ", dupProds);
// return dupProds
})
};
Actually then worked on promise so if you want to use then you need to promising. so can use like
aggregate([{..}]).exec().then(function(result){..})
where aggregate([{..}]).exec() return promise
You need call exec before then:
Company.aggregate(params).exec().then(function (dupProds) {
console.log("ALL DUPLICATE PRDCTS : " + JSON.stringify(dupProds));
})
};
[ http://mongoosejs.com/docs/api.html#aggregate_Aggregate-exec ]