美文网首页
elasticsearch之十五springboot测试文档复合

elasticsearch之十五springboot测试文档复合

作者: Java及SpringBoot | 来源:发表于2020-04-01 10:36 被阅读0次

    个人专题目录](https://www.jianshu.com/p/140e2a59db2c)


    elasticsearch文档复合查询及排序

    1. 复合查询

    1.1 bool查询

    bool (布尔)过滤器。 这是个复合过滤器(compound filter) ,它可以接受多个其他过滤器作为参数,并将这些过滤器结合成各式各样的布尔(逻辑)组合。
    格式
    一个 bool 过滤器由三部分组成:

    {
       "bool" : {
          "must" :     [],
          "should" :   [],
          "must_not" : [],
       }
    }
    

    参数定义:

    must
    所有的语句都 必须(must) 匹配,与 AND 等价。
    must_not
    所有的语句都不能(must not) 匹配,与 NOT 等价。
    should
    至少有一个语句要匹配,与 OR 等价。

    例如查询条件:

    POST /book-index/_search
    {
      "from": 0,
      "size": 100,
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "title": {
                  "query": "三星",
                  "operator": "OR",
                  "prefix_length": 0,
                  "max_expansions": 50,
                  "fuzzy_transpositions": true,
                  "lenient": false,
                  "zero_terms_query": "NONE",
                  "auto_generate_synonyms_phrase_query": true,
                  "boost": 1
                }
              }
            }
          ],
          "must_not": [
            {
              "term": {
                "brandName": {
                  "value": "诺基亚",
                  "boost": 1
                }
              }
            }
          ],
          "should": [
            {
              "term": {
                "categoryName": {
                  "value": "手机",
                  "boost": 1
                }
              }
            },
            {
              "term": {
                "categoryName": {
                  "value": "平板电视",
                  "boost": 1
                }
              }
            }
          ],
          "adjust_pure_negative": true,
          "boost": 1
        }
      }
    }
    
    @Override
    public void boolQuery(String indexName) throws Exception {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.should(QueryBuilders.termQuery("categoryName", "手机"));
        queryBuilder.should(QueryBuilders.termQuery("categoryName", "平板电视"));
        queryBuilder.must(QueryBuilders.matchQuery("title", "三星"));
        queryBuilder.mustNot(QueryBuilders.termQuery("brandName", "诺基亚"));
        builder(indexName, queryBuilder);
    }
    
    @Test
    public void testBoolQuery() throws Exception {
        baseQuery.boolQuery(Constants.INDEX_NAME);
    }
    

    1.2 booting查询

    该查询用于将两个查询封装在一起,并降低其中一个查询所返回文档的分值。

    它接受一个positive查询和一个negative查询。只有匹配了positive查询的文档才会被包含到结果集中,但是同时匹配了negative查询的文档会被降低其相关度,通过将文档原本的_score和negative_boost参数进行相乘来得到新的_score。因此,negative_boost参数必须小于1.0。在上面的例子中,任何包含了指定负面词条的文档的_score都会是其原本_score的一半。

    例如:

    在互联网上搜索"苹果"也许会返回,水果或者各种食谱的结果。我们可以通过排除“水果 乔木 维生素”和这类单词,结合bool查询中的must_not子句,将结果范围缩小到只剩苹果手机。

    POST  /book-index/_search
    {
        "query": {
            "boosting": {
                "positive": {
                    "match": {
                        "title": {
                            "query": "三星 手机 联通",
                            "operator": "AND",
                            "prefix_length": 0,
                            "max_expansions": 50,
                            "fuzzy_transpositions": true,
                            "lenient": false,
                            "zero_terms_query": "NONE",
                            "auto_generate_synonyms_phrase_query": true,
                            "boost": 1.0
                        }
                    }
                },
                "negative": {
                    "match": {
                        "title": {
                            "query": "白色 黑色",
                            "operator": "OR",
                            "prefix_length": 0,
                            "max_expansions": 50,
                            "fuzzy_transpositions": true,
                            "lenient": false,
                            "zero_terms_query": "NONE",
                            "auto_generate_synonyms_phrase_query": true,
                            "boost": 1.0
                        }
                    }
                },
                "negative_boost": 0.1,
                "boost": 1.0
            }
        }
    }
    
    @Override
    public void boostingQuery(String indexName, String positiveField, String positiveKeyWord, String negativeField, String negativeKeyWord) throws Exception {
        MatchQueryBuilder matchQueryPositiveBuilder = QueryBuilders.matchQuery(positiveField, positiveKeyWord);
        MatchQueryBuilder matchQueryNegativeBuilder = QueryBuilders.matchQuery(negativeField, negativeKeyWord);
        BoostingQueryBuilder boostingQueryBuilder = QueryBuilders.boostingQuery(matchQueryPositiveBuilder,
                matchQueryNegativeBuilder).negativeBoost(0.1f);
    
        builder(indexName, boostingQueryBuilder);
    }
    
    /**
     * 它接受一个positive查询和一个negative查询。只有匹配了positive查询的文档才会被包含到结果集中,
     * 但是同时匹配了negative查询的文档会被降低其相关度,通过将文档原本的_score和negative_boost参数进行相乘来得到新的_score。
     * 因此,negative_boost参数必须小于1.0。在上面的例子中,任何包含了指定负面词条的文档的_score都会是其原本_score的一半。
     *
     * @throws Exception
     */
    @Test
    public void testBoostingQuery() throws Exception {
        //都可以查出来,只是SCORE值减少,可以通过SCORE值来去掉排名在后面的
        baseQuery.boostingQuery(Constants.INDEX_NAME, "title", "三星 手机 联通", "title", "白色 黑色");
    }
    

    2. 排序(Sort)

    默认情况下,结果集会按照相关性进行排序 -- 相关性越高,排名越靠前。

    为了使结果可以按照相关性进行排序,我们需要一个相关性的值。在ElasticSearch的查询结果中, 相关性分值会用_score字段来给出一个浮点型的数值,所以默认情况下,结果集以_score进行倒序排列。

    注意:在Elasticsearch中,如果使用text类型的字段作为排序依据,会有问题。Elasticsearch需要对text类型字段数据做分词处理。如果使用text类型字段做排序,Elasticsearch给出的排序结果未必友好,毕竟分词后,先使用哪一个单词做排序都是不合理的。所以Elasticsearch中默认情况下不允许使用text类型的字段做排序,如果需要使用字符串做结果排序,则可使用keyword类型字段作为排序依据,因为keyword字段不做分词处理。

    如果对一个text field进行排序,结果往往不准确,因为分词后是多个单词,再排序就不是我们想要的结果了。

    通常解决方案是,将一个text field建立两次索引,一个分词,用来进行搜索;一个不分词,用来进行排序。

    fielddate:true
    
    {
      "query": {
        "match_all": {}
      },
      "sort": [
        {
          "title.keyword": {
            "order": "desc"
          }
        }
      ]
    }
    
    POST /book-index/_search
    {
      "query": {
        "match": {
          "brandName": {
            "query": "三星",
            "operator": "OR",
            "prefix_length": 0,
            "max_expansions": 50,
            "fuzzy_transpositions": true,
            "lenient": false,
            "zero_terms_query": "NONE",
            "auto_generate_synonyms_phrase_query": true,
            "boost": 1
          }
        }
      },
      "sort": [
        {
          "id": {
            "order": "desc"
          }
        }
      ]
    }
    
    @Override
    public void sortQuery(String indexName, String field, String keyWord, String sort, SortOrder sortOrder) throws IOException {
        SearchRequest searchRequest = new SearchRequest(indexName);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchQuery(field, keyWord));
        searchSourceBuilder.sort(sort, sortOrder);
        searchRequest.source(searchSourceBuilder);
        log.info("source:" + searchRequest.source());
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchResponse.getHits();
        log.info("count:" + hits.getTotalHits());
        SearchHit[] h = hits.getHits();
        for (SearchHit hit : h) {
            log.info("结果" + hit.getSourceAsMap() + ",score:" + hit.getScore());
        }
    }
    
    @Test
    public void testSortQueryBySort() throws IOException {
        sortQuery.sortQuery(Constants.INDEX_NAME, "brandName", "三星", "id", SortOrder.DESC);
    }
    

    相关文章

      网友评论

          本文标题:elasticsearch之十五springboot测试文档复合

          本文链接:https://www.haomeiwen.com/subject/dcrouhtx.html