Как расставить приоритеты на основе диапазона / фильтра Elastic Search DSL, чтобы можно было отфильтровать список, сначала показать с доступностью> 60%, а затем < - PullRequest
0 голосов
/ 03 января 2019

Релевантность соискателей необходимо отсортировать, исходя из наличия% в месяце. Сначала должны прийти кандидаты с% доступностью более 60%, а затем должны прийти кандидаты с% доступностью менее 60%.

Свободный DSL-запрос с использованием ElasticSearch.net, который я пытаюсь использовать с

var response = await 
_elasticClient.SearchAsync<ApplicantsWithDetailsResponse>(s =>
                             s.Aggregations(a => a

.Filter("higer_average", f => f.Filter(fd => fd.Range(r => r.Field(p 
=> p.AvailablePercentage).GreaterThanOrEquals(60).Boost(5))))

.Filter("lower_average", f => f.Filter(fd => fd.Range(r => r.Field(p 
=> p.AvailablePercentage).GreaterThan(0).LessThan(60).Boost(3)))
                             )));

или

var response = await _elasticClient.SearchAsync<ApplicantsWithDetailsResponse>(
        s => s
          .Query(q => q
           .Bool(p =>
                    p.Must(queryFilter => queryFilter.MatchAll())
                            .Filter(f => f.Range(r => r.Field("AvailablePercentage").GreaterThanOrEquals(60)))
                            .Boost(5)
                            .Filter(f => f.Range(r => r.Field("AvailablePercentage").GreaterThan(0).LessThan(60)))
                            .Boost(1.2)
                             )));

Приход списка заявителя не соответствует логике. Они смешиваются.

Даже если я попытаюсь отфильтровать, чтобы показать только значения больше 60, это также не работает

1 Ответ

0 голосов
/ 30 января 2019

Ваш запрос не верный;он сериализуется в

{
  "query": {
    "bool": {
      "boost": 1.2,
      "filter": [
        {
          "range": {
            "AvailablePercentage": {
              "gt": 0.0,
              "lt": 60.0
            }
          }
        }
      ],
      "must": [
        {
          "match_all": {}
        }
      ]
    }
  }
}
  • усиление применяется ко всему bool запросу
  • , последнее присвоенное Filter перезаписывает все предыдущие фильтры
  • Фильтрыand ed, поэтому все должно быть удовлетворено для совпадения

Во время разработки полезно посмотреть, какой JSON клиент отправляет в Elasticsearch.Есть множество способов сделать это , и один из них полезен:

var defaultIndex = "default-index";
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));

var settings = new ConnectionSettings(pool)
    .DefaultIndex(defaultIndex)
    .DisableDirectStreaming()
    .PrettyJson()
    .OnRequestCompleted(callDetails =>
    {
        if (callDetails.RequestBodyInBytes != null)
        {
            Console.WriteLine(
                $"{callDetails.HttpMethod} {callDetails.Uri} \n" +
                $"{Encoding.UTF8.GetString(callDetails.RequestBodyInBytes)}");
        }
        else
        {
            Console.WriteLine($"{callDetails.HttpMethod} {callDetails.Uri}");
        }

        Console.WriteLine();

        if (callDetails.ResponseBodyInBytes != null)
        {
            Console.WriteLine($"Status: {callDetails.HttpStatusCode}\n" +
                     $"{Encoding.UTF8.GetString(callDetails.ResponseBodyInBytes)}\n" +
                     $"{new string('-', 30)}\n");
        }
        else
        {
            Console.WriteLine($"Status: {callDetails.HttpStatusCode}\n" +
                     $"{new string('-', 30)}\n");
        }
    });

var client = new ElasticClient(settings);

. Он будет записывать все запросы и ответы на консоль.Обратите внимание, что вы можете не захотеть делать это в производственном режиме для каждого запроса, так как это приводит к снижению производительности при буферизации запросов и ответов таким образом.

Ваш запрос должен выглядеть примерно так:

var response = client.Search<ApplicantsWithDetailsResponse>(s => s
    .Query(q => q
        .Bool(p => p
            .Must(queryFilter => queryFilter
                .MatchAll()
            )
            .Should(f => f
                .Range(r => r
                    .Field("AvailablePercentage")
                    .GreaterThanOrEquals(60)
                    .Boost(5)
                ), f => f
                .Range(r => r
                    .Field("AvailablePercentage")
                    .GreaterThan(0)
                    .LessThan(60)
                    .Boost(1.2)
                )
            )
            .MinimumShouldMatch(1)
        )
    )
);

Который генерирует следующий запрос

{
  "query": {
    "bool": {
      "minimum_should_match": 1,
      "must": [
        {
          "match_all": {}
        }
      ],
      "should": [
        {
          "range": {
            "AvailablePercentage": {
              "boost": 5.0,
              "gte": 60.0
            }
          }
        },
        {
          "range": {
            "AvailablePercentage": {
              "boost": 1.2,
              "gt": 0.0,
              "lt": 60.0
            }
          }
        }
      ]
    }
  }
}

Объедините запросы диапазона с предложениями should и укажите, что хотя бы один должен соответствовать, используя MinimumShouldMatch.Это необходимо из-за наличия предложения must, что означает, что предложения should действуют как повышающий сигнал к документам, но документ не должен удовлетворять ни одному из предложений, чтобы считаться совпадением.Если для MinimumShouldMatch установлено значение 1, по крайней мере одно из предложений should должно быть удовлетворено, чтобы считаться совпадающим.

Поскольку предложение must в данном случае является запросом match_all, мыможет просто пропустить его и удалить MinimumShouldMatch.Предложение should без предложения must подразумевает, что хотя бы одно из предложений должно совпадать.

Мы также можем комбинировать запросы, используя перегрузку операторов , для краткости.Окончательный запрос будет выглядеть как

var response = client.Search<ApplicantsWithDetailsResponse>(s => s
    .Query(q => q
        .Range(r => r
            .Field("AvailablePercentage")
            .GreaterThanOrEquals(60)
            .Boost(5)
        ) || q
        .Range(r => r
            .Field("AvailablePercentage")
            .GreaterThan(0)
            .LessThan(60)
            .Boost(1.2)
        )
    )
);

, который отправляет запрос

{
  "query": {
    "bool": {
      "should": [
        {
          "range": {
            "AvailablePercentage": {
              "boost": 5.0,
              "gte": 60.0
            }
          }
        },
        {
          "range": {
            "AvailablePercentage": {
              "boost": 1.2,
              "gt": 0.0,
              "lt": 60.0
            }
          }
        }
      ]
    }
  }
}
...