mongoTemplate convert $dateTrunc? - mongodb

Currently, Mongo queries have been written, but conversion cases have not been found using the mongoTemplate.
db.a.aggregate([
{ $unwind : "$objects"},
{ $match : { "projectId" : "1234",
"objects.objectType" : "test",
"logDate" : { $gte : ISODate('2023-02-11'), "$lte" : ISODate('2023-02-12')}}},
{ $group : { _id : {"zones": "$objects.zones", "timezones":{"$dateTrunc" : {date : "$logDate", unit : "minute", binSize : 1}}, "name": "$objects.objectId" },
number : {$count: {} } }},
{ $group : { _id : {"zone": "$_id.zones", "timezone": "$_id.timezones"}, number: { $count : {} }}},
{$sort : {_id:1}}
])

Related

Get the last element for a specific field in mongo [duplicate]

I have collection in which documents are like:
{
_id: ObjectId(),
user: ObjectId(),
studentName: String,
createdAt: Date,
isAbondoned: boolean
}
example of documents are:
1-
{
"_id" : ObjectId("56cd2d36a489a5b875902f0e"),
"user" : ObjectId("56c4cafabd5f92cd78ae49d4"),
"studentName" : "Aman",
"createdAt" : ISODate("2016-02-24T04:10:30.486+0000"),
"isAbandoned" : true
}
2-
{
"_id" : ObjectId("56cd2dcda489a5b875902fcd"),
"user" : ObjectId("56c4cafabd5f92cd78ae49d4"),
"studentName" : "Aman",
"createdAt" : ISODate("2016-02-24T04:13:01.932+0000"),
"isAbandoned" : false
}
3-
{
"_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev",
"createdAt" : ISODate("2016-02-25T11:27:17.281+0000"),
"isAbandoned" : true,
}
Now I want to find the list of students for which their 'isAbandoned' is true for their last 'createdAt' document.
Required output for above example is:
{
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev"
}
because for studentName "Aman" max(createdAt) is 2nd document and 'isAbandoned' is false for that.
The best way to do this is using the aggregation framework. You need to $group your documents by "user" and return the last document for each user using the $last accumulator operator but for this to work, you need a preliminary sorting stage using the $sort aggregation pipeline operator. To sort your documents, you need to consider both the "createdAt" field and the "user" field.
The last stage in the pipeline is the $match stage where you select only those last documents where "isAbandoned" equals true.
db.students.aggregate([
{ "$sort": { "user": 1, "createdAt": 1 } },
{ "$group": {
"_id": "$user",
"last": { "$last": "$$ROOT" }
}},
{ "$match": { "last.isAbandoned": true } }
])
which returns something like this:
{
"_id" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"last" : {
"_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev",
"createdAt" : ISODate("2016-02-25T11:27:17.281Z"),
"isAbandoned" : true
}
}
To get the expected result, we need to use the $replaceRoot pipeline operator starting from verion 3.4 to promote the embedded document to the top level
{
$replaceRoot: { newRoot: "$last" }
}
In older version, you need to use the $project aggregation pipeline operation to reshape our documents. So if we extend our pipeline with the following stage:
{
"$project": {
"_id": "$last._id",
"user": "$last.user",
"studentName": "$last.studentName",
"createdAt": "$last.createdAt",
"isAbandoned": "$last.isAbandoned"
}}
it produces the expected output:
{
"_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev",
"createdAt" : ISODate("2016-02-25T11:27:17.281Z"),
"isAbandoned" : true
}
This is a good example of need to group data by specific filed (createdAt) and then compare result set match criteria.
find max by student id,
match only entries by max entry = createdAt
check if they are passing criteria
reshape document
Code:
db.student.aggregate([{
$group : {
_id : "$user",
created : {
$max : "$createdAt"
},
documents : {
$push : "$$ROOT"
}
}
}, {
$project : {
_id : 0,
documents : {
$filter : {
input : "$documents",
as : "item",
cond : {
$eq : ["$$item.createdAt", "$created"]
}
}
}}
}, {
$match : {
"documents.isAbandoned" : true
}},
{ $unwind : "$documents" },
{
$project : {
_id : "$documents._id",
user : "$documents.user",
studentName : "$documents.studentName",
createdAt : "$documents.createdAt",
isAbandoned : "$documents.isAbandoned",
}}
])

Return the last 'true' value for each group at a given time [duplicate]

I have collection in which documents are like:
{
_id: ObjectId(),
user: ObjectId(),
studentName: String,
createdAt: Date,
isAbondoned: boolean
}
example of documents are:
1-
{
"_id" : ObjectId("56cd2d36a489a5b875902f0e"),
"user" : ObjectId("56c4cafabd5f92cd78ae49d4"),
"studentName" : "Aman",
"createdAt" : ISODate("2016-02-24T04:10:30.486+0000"),
"isAbandoned" : true
}
2-
{
"_id" : ObjectId("56cd2dcda489a5b875902fcd"),
"user" : ObjectId("56c4cafabd5f92cd78ae49d4"),
"studentName" : "Aman",
"createdAt" : ISODate("2016-02-24T04:13:01.932+0000"),
"isAbandoned" : false
}
3-
{
"_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev",
"createdAt" : ISODate("2016-02-25T11:27:17.281+0000"),
"isAbandoned" : true,
}
Now I want to find the list of students for which their 'isAbandoned' is true for their last 'createdAt' document.
Required output for above example is:
{
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev"
}
because for studentName "Aman" max(createdAt) is 2nd document and 'isAbandoned' is false for that.
The best way to do this is using the aggregation framework. You need to $group your documents by "user" and return the last document for each user using the $last accumulator operator but for this to work, you need a preliminary sorting stage using the $sort aggregation pipeline operator. To sort your documents, you need to consider both the "createdAt" field and the "user" field.
The last stage in the pipeline is the $match stage where you select only those last documents where "isAbandoned" equals true.
db.students.aggregate([
{ "$sort": { "user": 1, "createdAt": 1 } },
{ "$group": {
"_id": "$user",
"last": { "$last": "$$ROOT" }
}},
{ "$match": { "last.isAbandoned": true } }
])
which returns something like this:
{
"_id" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"last" : {
"_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev",
"createdAt" : ISODate("2016-02-25T11:27:17.281Z"),
"isAbandoned" : true
}
}
To get the expected result, we need to use the $replaceRoot pipeline operator starting from verion 3.4 to promote the embedded document to the top level
{
$replaceRoot: { newRoot: "$last" }
}
In older version, you need to use the $project aggregation pipeline operation to reshape our documents. So if we extend our pipeline with the following stage:
{
"$project": {
"_id": "$last._id",
"user": "$last.user",
"studentName": "$last.studentName",
"createdAt": "$last.createdAt",
"isAbandoned": "$last.isAbandoned"
}}
it produces the expected output:
{
"_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev",
"createdAt" : ISODate("2016-02-25T11:27:17.281Z"),
"isAbandoned" : true
}
This is a good example of need to group data by specific filed (createdAt) and then compare result set match criteria.
find max by student id,
match only entries by max entry = createdAt
check if they are passing criteria
reshape document
Code:
db.student.aggregate([{
$group : {
_id : "$user",
created : {
$max : "$createdAt"
},
documents : {
$push : "$$ROOT"
}
}
}, {
$project : {
_id : 0,
documents : {
$filter : {
input : "$documents",
as : "item",
cond : {
$eq : ["$$item.createdAt", "$created"]
}
}
}}
}, {
$match : {
"documents.isAbandoned" : true
}},
{ $unwind : "$documents" },
{
$project : {
_id : "$documents._id",
user : "$documents.user",
studentName : "$documents.studentName",
createdAt : "$documents.createdAt",
isAbandoned : "$documents.isAbandoned",
}}
])

Sort a match group by id in aggregate

(Mongo newbie here, sorry) I have a mongodb collection, result of a mapreduce with this schema :
{
"_id" : "John Snow",
"value" : {
"countTot" : 500,
"countCall" : 30,
"comment" : [
{
"text" : "this is a text",
"date" : 2016-11-17 00:00:00.000Z,
"type" : "call"
},
{
"text" : "this is a text",
"date" : 2016-11-12 00:00:00.000Z,
"type" : "visit"
},
...
]
}
}
My goal is to have a document containing all the comments of a certain type. For example, a document John snow with all the calls.
I manage to have all the comments for a certain type using this :
db.general_stats.aggregate(
{ $unwind: '$value.comment' },
{ $match: {
'value.comment.type': 'call'
}}
)
However, I can't find a way to group the data received by the ID (for example john snow) even using the $group property. Any idea ?
Thanks for reading.
Here is the solution for your query.
db.getCollection('calls').aggregate([
{ $unwind: '$value.comment' },
{ $match: {
'value.comment.type': 'call'
}},
{
$group : {
_id : "$_id",
comment : { $push : "$value.comment"},
countTot : {$first : "$value.countTot"},
countCall : {$first : "$value.countCall"},
}
},
{
$project : {
_id : 1,
value : {"countTot":"$countTot","countCall":"$countCall","comment":"$comment"}
}
}
])
or either you can go with $project with $filter option
db.getCollection('calls').aggregate([
{
$project: {
"value.comment": {
$filter: {
input: "$value.comment",
as: "comment",
cond: { $eq: [ "$$comment.type", 'call' ] }
}
},
"value.countTot":"$value.countTot",
"value.countCall":"$value.countCall",
}
}
])
In both case below is my output.
{
"_id" : "John Snow",
"value" : {
"countTot" : 500,
"countCall" : 30,
"comment" : [
{
"text" : "this is a text",
"date" : "2016-11-17 00:00:00.000Z",
"type" : "call"
},
{
"text" : "this is a text 2",
"date" : "2016-11-17 00:00:00.000Z",
"type" : "call"
}
]
}
}
Here is the query which is the extension of the one present in OP.
db.general_stats.aggregate(
{ $unwind: '$value.comment' },
{ $match: {
'value.comment.type': 'call'
}},
{$group : {_id : "$_id", allValues : {"$push" : "$$ROOT"}}},
{$project : {"allValues" : 1, _id : 0} },
{$unwind : "$allValues" }
);
Output:-
{
"allValues" : {
"_id" : "John Snow",
"value" : {
"countTot" : 500,
"countCall" : 30,
"comment" : {
"text" : "this is a text",
"date" : ISODate("2016-11-25T10:46:49.258Z"),
"type" : "call"
}
}
}
}
Got my answer looking at this :
How to retrieve all matching elements present inside array in Mongo DB?
using the $addToSet property in the $group one.

Mongodb find data and groupby for another column

{
"_id" : ObjectId("5763e4d6c0140edcb8731485"),
"_class" : "net.microservice.product.domain.Product",,
"createdAt" : ISODate("2016-06-17T11:53:58.228Z"),
"createdBy" : "user-0",
"modifiedAt" : ISODate("2016-06-21T06:21:47.524Z"),
"modifiedBy" : "user-0",
"merchant" : "a746f24safa5-e96f-4281-9759-a4a02b306d77",
"type" : DBRef("productTypes", ObjectId("575fd99236623f70c959247f")),
"fields" : {
"Image4" : {
"value" : "http://i.hizliresim.com/ZdELXa.jpg",
"detail" : {
"revisedBy" : "CTA",
"revisionDate" : ISODate("2016-06-21T06:21:47.204Z")
}
},
"Image3" : {
"value" : "http://i.hizliresim.com/l1WkqX.jpg",
"detail" : {
"revisedBy" : "CTA",
"revisionDate" : ISODate("2016-06-21T06:21:47.204Z")
}
},
"Image2" : {
"value" : "http://i.hizliresim.com/VYMl9n.jpg",
"detail" : {
"revisedBy" : "CTA",
"revisionDate" : ISODate("2016-06-21T06:21:47.204Z")
}
},
"Kur" : {
"value" : "TL",
"detail" : {
"revisedBy" : "CTA",
"revisionDate" : ISODate("2016-06-21T06:21:47.204Z")
}
},
"Image1" : {
"value" : "http://i.hizliresim.com/nrWAQ0.jpg",
"detail" : {
"revisedBy" : "CTA",
"revisionDate" : ISODate("2016-06-21T06:21:47.204Z")
}
},
"uploadDate" : ISODate("2016-06-17T11:53:00Z"),
"tasks" : [ ]
}
this is sample of database. I want to get data in which:
- modifiedAt is before "modifiedAt" : ISODate("2016-07-21T06:21:47.524Z"),
so i do this and this works:
db.products.find({
'modifiedAt':
{$lte: ISODate("2016-10-18T13:05:18.961Z"
)} }).
count()
14999
But i need to find for each merchant. Beause 14999 result is not true because a merchant have lots of product so 14999 includes multiple products.
I need to group by merchant and distinct. I couldnot do it.
i do this but
db.products.
aggregate([ {
$group: {
_id: '$merchant', } }, {
$match: {
modifiedAt:
{$lte: ISODate("2016-06-18T13:05:18.961Z")} }} ])
brings nothing and no error.
you can try something like this. This gives you the number of products by merchant.
db.products.aggregate([
{$match: {modifiedAt:{$lte: ISODate("2016-06-21T06:21:47.524Z")}}},
{$group: { _id: "$merchant",count: { $sum: 1 }}}
])
Output:
{ "_id" : "a89846f24safa5-e96f-4281-9759-a4a02b306d77", "count" : 1 }
Always place the $match as early in the aggregation pipeline as possible. Because $match limits the total number of documents in the aggregation pipeline, earlier $match operations minimize the amount of processing down the pipe.
So your query would be like
db.products.aggregate([
{
$match: {
modifiedAt: {
$lte: ISODate("2016-06-18T13:05:18.961Z")
}
}
},
{
$group: {
_id: '$merchant'
}
}
])

Return the last "true" value for each group

I have collection in which documents are like:
{
_id: ObjectId(),
user: ObjectId(),
studentName: String,
createdAt: Date,
isAbondoned: boolean
}
example of documents are:
1-
{
"_id" : ObjectId("56cd2d36a489a5b875902f0e"),
"user" : ObjectId("56c4cafabd5f92cd78ae49d4"),
"studentName" : "Aman",
"createdAt" : ISODate("2016-02-24T04:10:30.486+0000"),
"isAbandoned" : true
}
2-
{
"_id" : ObjectId("56cd2dcda489a5b875902fcd"),
"user" : ObjectId("56c4cafabd5f92cd78ae49d4"),
"studentName" : "Aman",
"createdAt" : ISODate("2016-02-24T04:13:01.932+0000"),
"isAbandoned" : false
}
3-
{
"_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev",
"createdAt" : ISODate("2016-02-25T11:27:17.281+0000"),
"isAbandoned" : true,
}
Now I want to find the list of students for which their 'isAbandoned' is true for their last 'createdAt' document.
Required output for above example is:
{
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev"
}
because for studentName "Aman" max(createdAt) is 2nd document and 'isAbandoned' is false for that.
The best way to do this is using the aggregation framework. You need to $group your documents by "user" and return the last document for each user using the $last accumulator operator but for this to work, you need a preliminary sorting stage using the $sort aggregation pipeline operator. To sort your documents, you need to consider both the "createdAt" field and the "user" field.
The last stage in the pipeline is the $match stage where you select only those last documents where "isAbandoned" equals true.
db.students.aggregate([
{ "$sort": { "user": 1, "createdAt": 1 } },
{ "$group": {
"_id": "$user",
"last": { "$last": "$$ROOT" }
}},
{ "$match": { "last.isAbandoned": true } }
])
which returns something like this:
{
"_id" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"last" : {
"_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev",
"createdAt" : ISODate("2016-02-25T11:27:17.281Z"),
"isAbandoned" : true
}
}
To get the expected result, we need to use the $replaceRoot pipeline operator starting from verion 3.4 to promote the embedded document to the top level
{
$replaceRoot: { newRoot: "$last" }
}
In older version, you need to use the $project aggregation pipeline operation to reshape our documents. So if we extend our pipeline with the following stage:
{
"$project": {
"_id": "$last._id",
"user": "$last.user",
"studentName": "$last.studentName",
"createdAt": "$last.createdAt",
"isAbandoned": "$last.isAbandoned"
}}
it produces the expected output:
{
"_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
"user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
"studentName" : "Rajeev",
"createdAt" : ISODate("2016-02-25T11:27:17.281Z"),
"isAbandoned" : true
}
This is a good example of need to group data by specific filed (createdAt) and then compare result set match criteria.
find max by student id,
match only entries by max entry = createdAt
check if they are passing criteria
reshape document
Code:
db.student.aggregate([{
$group : {
_id : "$user",
created : {
$max : "$createdAt"
},
documents : {
$push : "$$ROOT"
}
}
}, {
$project : {
_id : 0,
documents : {
$filter : {
input : "$documents",
as : "item",
cond : {
$eq : ["$$item.createdAt", "$created"]
}
}
}}
}, {
$match : {
"documents.isAbandoned" : true
}},
{ $unwind : "$documents" },
{
$project : {
_id : "$documents._id",
user : "$documents.user",
studentName : "$documents.studentName",
createdAt : "$documents.createdAt",
isAbandoned : "$documents.isAbandoned",
}}
])