I have a collection with documents like this:
{
"_id" : ObjectId("5a8ec4620cd3c2a4062548ec"),
"start" : 20,
"end" : 80
}
and I want to show the documents that overlap a given percentage (50%) with an interval (startInterval = 10, endInterval = 90).
I calculate the overlaping section with the following formula:
min(end , endInterval) - max(start, startInterval ) / (endInterval - startInterval)
In this example: min(80,90) - max(20,10) / (90-10) = (80-20)/80 = 0.75 --> 75% Then this document will be shown, as 75% is greater than 50%
I expressed this formula in mongo shell as:
db.getCollection('variants').find(
{
$expr: {
$gt: [
{
$divide: [
{
$subtract: [
{ $min: [ "$end", endInterval ] }
,
{ $max: [ "$start", startInterval ] }
]
}
,
{ $subtract: [ endInterval, startInterval ] }
]
}
,
overlap
]
}
}
)
where
overlap = 0.5, startInterval = 10 and endInterval= 90
It works fine in mongo shell.
I'm asking for an equivalent way to calculate this using Spring Data Criteria, since the $expr functionality I used in mongo shell is still to be implemented in Spring Data Mongo. Currently I'm using Spring Boot 2.0.0, Spring Data MongoDb 2.0.5 and mongodb 3.6.
Thanks a lot for your time.
Just in case it is helpful for somebody, I finally solved my problem using $redact.
String redact = "{\n" +
" \"$redact\": {\n" +
" \"$cond\": [\n" +
" {\n" +
" \"$gte\": [\n" +
" {\n" +
" \"$divide\": [\n" +
" {\n" +
" \"$subtract\": [\n" +
" {\n" +
" \"$min\": [\n" +
" \"$end\",\n" +
" " + endInterval + "\n" +
" ]\n" +
" },\n" +
" {\n" +
" \"$max\": [\n" +
" \"$start\",\n" +
" " + startInterval + "\n" +
" ]\n" +
" }\n" +
" ]\n" +
" },\n" +
" {\n" +
" \"$subtract\": [\n" +
" " + endInterval + "\n" +
" " + startInterval + "\n" +
" ]\n" +
" }\n" +
" ]\n" +
" },\n" +
" " + overlap + "\n" +
" ]\n" +
" },\n" +
" \"$$KEEP\",\n" +
" \"$$PRUNE\"\n" +
" ]\n" +
" }\n" +
" }";
RedactAggregationOperation redactOperation = new RedactAggregationOperation(
Document.parse(redact)
);
where RedactAggregationOperation is
public class RedactAggregationOperation implements AggregationOperation {
private Document operation;
public RedactAggregationOperation (Document operation) {
this.operation = operation;
}
@Override
public Document toDocument(AggregationOperationContext context) {
return context.getMappedObject(operation);
}
}