Spring Data MongoDb - критерии, эквивалентные заданному запросу, использующему $ expr - PullRequest
0 голосов
/ 09 мая 2018

У меня есть коллекция с такими документами:

 {
    "_id" : ObjectId("5a8ec4620cd3c2a4062548ec"),
    "start" : 20,
    "end" : 80
 }

, и я хочу показать документы, которые перекрывают определенный процент (50%) с интервалом (startInterval = 10, endInterval = 90).

Я вычисляю перекрывающий участок по следующей формуле:

min(end , endInterval) - max(start, startInterval ) / (endInterval - startInterval)

В этом примере: min (80,90) - max (20,10) / (90-10) = (80-20) / 80 = 0,75 -> 75% Затем этот документ будет показан, так как 75% больше, чем 50%

Я выразил эту формулу в оболочке монго как:

db.getCollection('variants').find(
  {
     $expr: {  

       $gt: [

              { 
                $divide: [
                           { 
                             $subtract: [ 
                                          { $min: [ "$end", endInterval ]  }
                                          , 
                                          { $max: [ "$start", startInterval ]  } 
                             ] 
                           }
                           , 
                           { $subtract: [ endInterval, startInterval ] }
                         ] 
              }
             , 
             overlap 
            ]
      }
  }
)

где

перекрытие = 0,5, startInterval = 10 и endInterval = 90

В оболочке Монго работает нормально.

Я прошу эквивалентный способ вычисления этогоиспользуя Spring Data Criteria, поскольку функциональность $ expr, которую я использовал в оболочке mongo, все еще должна быть реализована в Spring Data Mongo.В настоящее время я использую Spring Boot 2.0.0, Spring Data MongoDb 2.0.5 и mongodb 3.6.

Большое спасибо за ваше время.

Ответы [ 2 ]

0 голосов
/ 27 февраля 2019

Как вы упомянули, Spring Data Mongo в настоящее время не поддерживает $expr, поэтому я должен использовать пользовательский документ BSON и отражение MongoTemplate.

public List<Variant> listTest() throws Exception {

    double overlap = 0.5;
    int startInterval = 10;
    int endInterval= 90;

    String jsonQuery = "{$expr:{$gt:[{$divide:[{$subtract:[{$min:[\"$end\","+endInterval+"]},{$max:[\"$start\","+startInterval+"]}]},{$subtract:["+endInterval+","+startInterval+"]}]},"+overlap+"]}}";
    Document query = Document.parse(jsonQuery);

    Method doFind = MongoTemplate.class.getDeclaredMethod("doFind", String.class, Document.class,Document.class,Class.class);
    doFind.setAccessible(true);
    return (List<Variant>) doFind.invoke(mongoTemplate, "variants", query, new Document(), Variant.class);
}

@NoArgsConstructor @Getter @Setter @ToString
public static class Variant{
    int start;
    int end;
}

Как видите, отображение полей работает нормально.

Используется артефакт Монго Данных Spring org.springframework:data.spring-data-mongodb:2.1.5.RELEASE

0 голосов
/ 16 мая 2018

На всякий случай, если это кому-нибудь пригодится, я наконец-то решил свою проблему с помощью $ 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)
    );      

, где RedactAggregationOperation -

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);
    }
}
...