Sort by array last element mongodb
I was trying to sort documents by last interaction. meta_data.access_times is an array that is updated every time the user interacts and the new date object is appended to the last element of the array. Is there a way to sort by the last element of the array?
Attempt 1:
private Aggregation makeQuery(String userId) {
return newAggregation(
match(Criteria.where("user_id").is(userId)),
sort(Sort.Direction.DESC, "$meta_data.access_times"),
group(Fields.fields().and("first_name", "$meta_data.user_data.first_name").and("last_name", "$meta_data.user_data.last_name").and("profile_pic", "$meta_data.user_data.profile_pic").and("user_id", "$user_id").and("access_times", "$meta_data.access_times"))
);
}
Attempt 2:
private Aggregation makeQuery(String userId) {
return newAggregation(
match(Criteria.where("user_id").is(user_id)),
group(Fields.fields().and("first_name", "$meta_data.user_data.first_name").and("last_name", "$meta_data.user_data.last_name").and("profile_pic", "$meta_data.user_data.profile_pic").and("user_id", "$user_id")).max("$meta_data.access_times").as("access_time"),
sort(Sort.Direction.DESC, "access_time")
);
}
sample meta_data array in document
"meta_data" : { "access_times" : [
ISODate("2017-06-20T14:04:14.910Z"),
ISODate("2017-06-22T06:27:32.210Z"),
ISODate("2017-06-22T06:27:35.326Z"),
ISODate("2017-06-22T06:31:28.048Z"),
ISODate("2017-06-22T06:36:19.664Z"),
ISODate("2017-06-22T06:37:00.164Z")
] }
source to share
I solve the problem using the $ unwind operation.
private Aggregation makeQuery(String userId) {
return newAggregation(
match(Criteria.where("user_id").is(userId)),
unwind("$meta_data.access_times"),
group(Fields.fields().and("first_name", "$meta_data.user_data.first_name").and("last_name", "$meta_data.user_data.last_name").and("profile_pic", "$meta_data.user_data.profile_pic").and("user_id", "$user_id")).max("$meta_data.access_times").as("access_time"),
sort(Sort.Direction.DESC, "access_time")
);
}
source to share
If you don't know if a Push item is set or not (like the user who clicks on it Score ...) you can use $ push and $ sort in order to have an ordered array, you can just sort it by address " find ({userId: yourUseId} .sort ("metadata.access_time.0": - 1).
This solution assumes your array is ordered with $ sort when created / updated: LINK
If you are sure that Push does not require sorting (for example, you are pressing Access_Date for that user), you can $ push and void $ sort using $ operator (tnx Erdenezul). LINK
In theory, you don't need an index in the "access_time" array if find () is only retrieving a few documents. Otherwise, you can simply add the index with {"metadata.access_time.0": -1}.
Good luck!
source to share