Поиск Elasticsearch по ключевым словам и ускорение

Я использую Spring Boot 2.0.5, Spring Data Elasticsearch 3.1.0 и Elasticsearch 6.4.2.

Я загрузил ElasticSearch набором статей. Для каждой статьи у меня есть поле ключевых слов со строковым списком ключевых слов, например.

"keywords": ["Football", "Barcelona", "Cristiano Ronaldo", "Real Madrid", "Zinedine Zidane"],

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

e.g.

User 1:
    keyword: Football, weight:3.0
    keyword: Tech, weight:1.0 
    keyword: Health, weight:2.0 

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

Это то, что у меня есть до сих пор (только для одного ключевого слова):

 public Page<Article> getArticles(String keyword, float boost, Pageable pageable) {

        SearchQuery searchQuery = new NativeSearchQueryBuilder()
        .withQuery(QueryBuilders.matchQuery("keywords", keyword).boost(boost))
        .build();
        return articleRepository.search(searchQuery);
 }

Поскольку у пользователя может быть n количество предпочтительных ключевых слов, что мне нужно изменить в приведенном выше коде, чтобы поддерживать это?

Любые предложения будут высоко оценены.

Решение

ОК, я включил ведение журнала, чтобы я мог видеть создается эластичный поисковый запрос. Затем я обновил метод getArticles до следующего:

public Page<Article> getArticles(List<Keyword> keywords, Pageable pageable) {

    BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
    List<FilterFunctionBuilder> functions = new ArrayList<FilterFunctionBuilder>();

    for (Keyword keyword : keywords) {
        queryBuilder.should(QueryBuilders.termsQuery("keywords", keyword.getKeyword()));
        functions.add(new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                QueryBuilders.termQuery("keywords", keyword.getKeyword()),
                ScoreFunctionBuilders.weightFactorFunction(keyword.getWeight())));
    }
    FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(queryBuilder,
            functions.toArray(new FunctionScoreQueryBuilder.FilterFunctionBuilder[functions.size()]));

    NativeSearchQueryBuilder searchQuery = new NativeSearchQueryBuilder();
    searchQuery.withQuery(functionScoreQueryBuilder);
    searchQuery.withPageable(pageable); 
    // searchQuery.withSort(SortBuilders.fieldSort("createdDate").order(SortOrder.DESC));
    return articleRepository.search(searchQuery.build());
}

В результате получается следующий эластичный поисковый запрос:

{
  "from" : 0,
  "size" : 20,
  "query" : {
    "function_score" : {
      "query" : {
        "bool" : {
          "should" : [
            {
              "terms" : {
                "keywords" : [
                  "Football"
                ],
                "boost" : 1.0
              }
            },
            {
              "terms" : {
                "keywords" : [
                  "Tech"
                ],
                "boost" : 1.0
              }
            }
          ],
          "disable_coord" : false,
          "adjust_pure_negative" : true,
          "boost" : 1.0
        }
      },
      "functions" : [
        {
          "filter" : {
            "term" : {
              "keywords" : {
                "value" : "Football",
                "boost" : 1.0
              }
            }
          },
          "weight" : 3.0
        },
        {
          "filter" : {
            "term" : {
              "keywords" : {
                "value" : "Tech",
                "boost" : 1.0
              }
            }
          },
          "weight" : 1.0
        }
      ],
      "score_mode" : "multiply",
      "max_boost" : 3.4028235E38,
      "boost" : 1.0
    }
  },
  "version" : true
}

person Swordfish    schedule 18.10.2018    source источник


Ответы (1)


То, что вы ищете, это запрос function_score. Что-то в духе

{
    "query": {
        "function_score": {
            "query": {
                "bool": {
                    "should": [
                        {"term":{"keyword":"Football"}},
                        {"term":{"keyword":"Tech"}},
                        {"term":{"keyword":"Health"}}
                    ]
                }
            },
            "functions": [
                {"filter":{"term":{"keyword":"Football"}},"weight": 3},
                {"filter":{"term":{"keyword":"Tech"}},"weight": 1},
                {"filter":{"term":{"keyword":"Health"}},"weight": 2}
            ]
        }
    }
}

См. здесь справку по API https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-compound-queries.html#java-query-dsl-function-оценка-запрос

person sramalingam24    schedule 18.10.2018
comment
Большое спасибо. Это то, что поддерживается API данных Spring? - person Swordfish; 18.10.2018
comment
Должно быть в соответствии с документами здесь github.com/spring- проекты/spring-data-elasticsearch/blob/. Возможно, вам придется покопаться в документации, чтобы узнать, как это сделать, пример строки запроса в файле readme будет хорошим началом. - person sramalingam24; 18.10.2018
comment
Спасибо, мне удалось сделать это через API, и я добавил его к вопросу выше. Хотя у меня есть пара сомнений. В чем разница между бустом и весом? и как мне сортировать по интересам, а затем по дате создания самой последней статьи. Я включил строку сортировки, описанную выше, и техническая статья отображалась сверху? - person Swordfish; 19.10.2018
comment
Документ по весу/повышению см. в этом elastic.co/guide/en/elasticsearch/reference/6.4/ - person sramalingam24; 19.10.2018
comment
Можете ли вы опубликовать выдержку из результатов, трудно понять, что нужно изменить, не видя того, что есть сейчас. - person sramalingam24; 19.10.2018