Elasticsearch поиск по ключевым словам и повышение - PullRequest
0 голосов
/ 18 октября 2018

Я использую 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"],

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

например

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
}

1 Ответ

0 голосов
/ 18 октября 2018

Что вы ищете, так это запрос 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-score-query

...