I want to write this aggregate query in mongo template using spring.
This is my query:
db.getCollection('CANdata_fc_distance_report').aggregate(
{$match: { device_datetime : { $gte :1462041000000, $lte: 1462732200000 }}},
{"$group" : {_id:{fc :"$fc",vehicle_name:"$vehicle_name",
device_id : "$device_id"},
count:{$sum:1}}}
)
This is the result of the above query
/* 1 */
{
"_id" : {
"fc" : NumberLong(1),
"vehicle_name" : "WPD 9020",
"device_id" : NumberLong(157)
},
"count" : 2
}
/* 2 */
{
"_id" : {
"fc" : NumberLong(2),
"vehicle_name" : "VVD 8966",
"device_id" : NumberLong(137)
},
"count" : 1
}
This is my data in table:
/* 1 */
{
"_id" : ObjectId("581829855d08921ee6f0ac39"),
"_class" : "com.analysis.model.mongo.fc_distance_report",
"device_id" : NumberLong(137),
"vehicle_name" : "VVD 8966",
"distance" : 125.01,
"fc" : NumberLong(1),
"device_datetime" : NumberLong(1462041000000)
}
/* 2 */
{
"_id" : ObjectId("581830335d08921ee6f0ad6b"),
"_class" : "com.analysis.model.mongo.fc_distance_report",
"device_id" : NumberLong(137),
"vehicle_name" : "VVD 8966",
"distance" : 171.88,
"fc" : NumberLong(2),
"device_datetime" : NumberLong(1462127400000)
}
I found example in my google search added match criteria but I have no idea how to write grouping on 3 columns
Aggregation agg = newAggregation(match(Criteria.where("device_datetime").exists(true)
.andOperator(
Criteria.where("device_datetime").gte(startDate),
Criteria.where("device_datetime").lte(endDate))),
group("hosting").count().as("total"),
project("total").and("hosting").previousOperation(),
sort(Sort.Direction.DESC, "total")
);
Please help me. Thank you
You can try something like this. Just and the group keys together.
Aggregation agg = newAggregation(match(Criteria.where("device_datetime").exists(true)
.andOperator(
Criteria.where("device_datetime").gte(startDate),
Criteria.where("device_datetime").lte(endDate))),
group(Fields.fields().and("fc", "$fc").and("vehicle_name", "$vehicle_name").and("device_id", "$device_id"))
.count().as("count"));
Related
I have one field which stores date time in Mongo collection i.e. in Number format i.e. long.
I want to write following query using Aggregation Pipeline
db.my_collection.aggregate(
[{ "$match" : { "createdAt" : { "$gte" : 1656786600000, "$lt" : 1657391400000}}},
{ "$project" : { "createdAt" : {"$dateToString": {format: "%Y-%m-%d", "date": {"$toDate" : "$createdAt"}}}}},
{ "$group" : { "_id" : "$createdAt", "count" : { "$sum" : 1}}}]
)
Output for this query will be
/* 1 */
{
"_id" : "2022-07-04",
"count" : 2888.0
}
/* 2 */
{
"_id" : "2022-07-06",
"count" : 1992.0
}
I have a data like below, and I want to group that data by the type, I'm using spring-data-mongodb .
[
{
"_id" : ObjectId("58a5518aace6132a88309d98"),
"type" : "SMS",
},
{
"_id" : ObjectId("58a5518bace6132a88309d99"),
"type" : "PUSH_NOTIFICATION",
},
{
"_id" : ObjectId("58a5519aace6132a0094d7df"),
"type" : "SMS",
},
{
"_id" : ObjectId("58a5519aace6132a0094d7e0"),
"type" : "PUSH_NOTIFICATION",
}
]
I'm using this method and won't work.
GroupByResults<Queuing> results = mongoTemplate.group("queuing",
GroupBy.key("type"), Queuing.class);
Anyone know the best and clear way to do this grouping using spring-data-mongodb.
Thanks.
This is the correct syntax for group operation.
GroupByResults<Queuing> results = mongoTemplate.group("queuing",
GroupBy.key("type").initialDocument("{}").reduceFunction("function(doc, prev) {}"),
Queuing.class);
More information here http://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mongo.group.example
I have these 2 documents in my collection:
{
"_id" : ObjectId("5722042f8648ba1d04c65dad"),
"companyId" : ObjectId("570269639caabe24e4e4043e"),
"applicationId" : ObjectId("5710e3994df37620e84808a8"),
"steps" : [
{
"id" : NumberLong(0),
"responsiveUser" : "57206f9362d0260fd0af59b6",
"stepOnRejection" : NumberLong(0),
"notification" : "test"
},
{
"id" : NumberLong(1),
"responsiveUser" : "57206fd562d0261034075f70",
"stepOnRejection" : NumberLong(1),
"notification" : "test1"
}
]
}
{
"_id" : ObjectId("5728f317a8f9ba14187b84f8"),
"companyId" : ObjectId("570269639caabe24e4e4043e"),
"applicationId" : ObjectId("5710e3994df37620e84808a8"),
"steps" : [
{
"id" : NumberLong(0),
"responsiveUser" : "57206f9362d0260fd0af59b6",
"stepOnRejection" : NumberLong(0),
"notification" : "erter"
},
{
"id" : NumberLong(1),
"responsiveUser" : "57206f9362d0260fd0af59b6",
"stepOnRejection" : NumberLong(1),
"notification" : "3232"
}
]
}
Now I'm trying to get the document with the max _id and the id that equals 0 from a document inside of the steps array. I also have a projection that is supposed to show only the id of the matched element and nothing else.
Here is my query:
collection
.find(new Document("companyId", companyId)
.append("applicationId", applicationId)
.append("steps",
new Document("$elemMatch",
new Document("id", 0))))
.sort(new Document("_id", 1))
.limit(1)
.projection(new Document("steps.id", 1)
.append("_id", 0));
And it returns:
Document{{steps=[Document{{id=0}}, Document{{id=1}}]}}
Why is it returning 2 documents instead of 1?
The result should be looking like:
Document{{id=0}}
What am I missing here? I know that is something basic, but I really can't spot my mistake here.
Your query document tells Mongo to return those documents where in the 'steps' array they have a document where id: 0. You are NOT telling Mongo to return ONLY that field. You can use $elemMatch inside the projection document to get what you want (I'm writing this in the Mongo shell syntax because I'm not too familiar with the Java syntax):
{ steps: { $elemMatch: { id: 0 } },
'steps.id': 1,
_id: 0
}
I have data in mongodb in following format. i presented below two row of my mongodb data of table named 'feed'.
{
"_id" : ObjectId("55e80a725ae35bbfc6dce074"),
"sourceId" : "12345",
"sourceName" : "MyPage",
"channelId" : "67890",
"channelName" : "Facebook",
"likeCount" : 1,
"feedData" : {
"from" : {
"id" : "416992615172913",
"name" : "Ashish Kumar"
},
"created_time" : "2015-08-04T09:54:39+0000",
},
"sentiment" : "neutral",
}
{
"_id" : ObjectId("55e80a725ae35bbfc6dce074"),
"sourceId" : "23456",
"sourceName" : "YourPage",
"channelId" : "67890",
"channelName" : "Facebook",
"likeCount" : 2,
"feedData" : {
"from" : {
"id" : "416992615172913",
"name" : "Ashish Kumar"
},
"created_time" : "2015-08-04T09:54:39+0000",
},
"sentiment" : "positive",
}
I want to perform groupBy on field feedData.from.id where channelName is equal to 'Facebook', sum of like count, all sources in an array, all sentiment in an array. i want all data associated with feedData.from.id in the format given below using spring mongo.
{
"feedDatafromid" : "416992615172913",
"name" : "Ashish Kumar",
"sourceName" : ["MyPage","YourPage"],
"channel" : "Facebook",
"likeCount" : 3,
"sentiment" : ["neutral","positive"]
}
Can someone help me to write code in java Spring to group the data of mongodb in given manner.
Suppose we have FeedDbBean class to save the result of aggregation.
Aggregation agg = newAggregation(match(criteria),group(userIdKey).sum("likeCount").as("likeCount").sum("commentCount").as("commentCount").addToSet("sourceName").as("sourceName").addToSet("sourceId").as("sourceId").addToSet("sentiment").as("sentiment").addToSet("channelId").as("channelId").addToSet("channelName").as("channelName").addToSet(userIdKey).as("postUserId").addToSet(userNameKey).as("postUserName"));
results = mongoTemplate.aggregate(agg, FEED_COLLECTION_NAME, FeedDbBean.class);
if(null!=results)
List feedList = results.getMappedResults();
...................
so using given code the result on behalf of userIdKey will be stored in list of FeedDbBean.
each FeedDbBean object will have property like following manner.
feedDbBean.userId = (userId)
feedDbBean.userName = (userName)
feedDbBean.likeCount = (sum of like count group by userId)
feedDbBean.commentCount =(sum of comment count groupby userid)
feedDbBean.sourceName = (all unique source name group by userid show here separated by comma)
feedDbBean.sentiment = (all sentiment separated by comma group by userid)
I have the following code snippet that should retrieve the total count of the account using spring-data-mongodb
TypedAggregation<Account> agg = Aggregation.newAggregation(Account.class,
group("user.id"),
group().count().as("total"));
AggregationResults<AccountTotal> result = mongos.aggregate(agg, AccountTotal.class);
AccountTotal account = result.getMappedResults().get(0);
account.getTotal(); // should print 90 but prints 1
Here is the equivalent mongo script returning from the agg field that I use in the mongo shell prints 90
{ "$group" : { "_id" : "$user.id"}} ,
{ "$group" : { "_id" : null , "total" : { "$sum" : 1}}}
> db.accounts.aggregate(
[
{ "$group" : { "_id" : "$user.id"}} ,
{ "$group" : { "_id" : null , "total" : { "$sum" : 1}}}
])
What am I missing actually that I get 1 in the Java platform.
EDIT:
After changing the previous one with the following one I get the expected count:
Aggregation agg = Aggregation.newAggregation(
group("user.id"),
group().count().as("total"));
AggregationResults<AccountTotal> result =
mongos.aggregate(agg, this.getCollectionName(), AccountTotal.class);
Btw, thanks #chridam.
The reason you are getting 1 is because of the current aggregation pipeline which returns all 90 documents grouped by user.id in an array and each may have a total of 1 (I guess). This line result.getMappedResults().get(0) will get the first element in the aggregation results and that element has a total of 1. The total you are trying to get is the total of all the grouped documents i.e. the length of the aggregation result cursor array.
I believe you want to group all the documents by the $user.id field, get the count on each grouped result and then do another $group operation to get the sum of all the group counts:
> db.accounts.aggregate(
[
{ "$group" : { "_id" : "$user.id", "count" : { "$sum" : 1 } } },
{ "$group" : { "_id" : null, "total" : { "$sum" : "$count" } } }
])
which will give you the desired results. The Spring aggregation equivalent
TypedAggregation<Account> agg = Aggregation.newAggregation(Account.class,
group("user.id").count().as("count"),
group().sum("count").as("total"));
AggregationResults<AccountTotal> result = mongos.aggregate(agg, AccountTotal.class);
List<AccountTotal> accountCount = result.getMappedResults();
(accountCount.get(0).total == 90); // should be true