elasticsearch之十五springboot測試文檔復合查詢及排序

個人專題目錄](http://www.reibang.com/p/140e2a59db2c)


elasticsearch文檔復合查詢及排序

1. 復合查詢

1.1 bool查詢

bool (布爾)過濾器污朽。 這是個復合過濾器(compound filter) 捺萌,它可以接受多個其他過濾器作為參數(shù)围俘,并將這些過濾器結(jié)合成各式各樣的布爾(邏輯)組合荔仁。
格式
一個 bool 過濾器由三部分組成:

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

參數(shù)定義:

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查詢的文檔才會被包含到結(jié)果集中胎撇,但是同時匹配了negative查詢的文檔會被降低其相關度介粘,通過將文檔原本的_score和negative_boost參數(shù)進行相乘來得到新的_score。因此晚树,negative_boost參數(shù)必須小于1.0姻采。在上面的例子中,任何包含了指定負面詞條的文檔的_score都會是其原本_score的一半爵憎。

例如:

在互聯(lián)網(wǎng)上搜索"蘋果"也許會返回慨亲,水果或者各種食譜的結(jié)果。我們可以通過排除“水果 喬木 維生素”和這類單詞宝鼓,結(jié)合bool查詢中的must_not子句巡雨,將結(jié)果范圍縮小到只剩蘋果手機。

POST  /book-index/_search
{
    "query": {
        "boosting": {
            "positive": {
                "match": {
                    "title": {
                        "query": "三星 手機 聯(lián)通",
                        "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查詢的文檔才會被包含到結(jié)果集中铐望,
 * 但是同時匹配了negative查詢的文檔會被降低其相關度,通過將文檔原本的_score和negative_boost參數(shù)進行相乘來得到新的_score茂附。
 * 因此正蛙,negative_boost參數(shù)必須小于1.0。在上面的例子中营曼,任何包含了指定負面詞條的文檔的_score都會是其原本_score的一半乒验。
 *
 * @throws Exception
 */
@Test
public void testBoostingQuery() throws Exception {
    //都可以查出來,只是SCORE值減少蒂阱,可以通過SCORE值來去掉排名在后面的
    baseQuery.boostingQuery(Constants.INDEX_NAME, "title", "三星 手機 聯(lián)通", "title", "白色 黑色");
}

2. 排序(Sort)

默認情況下锻全,結(jié)果集會按照相關性進行排序 -- 相關性越高,排名越靠前录煤。

為了使結(jié)果可以按照相關性進行排序鳄厌,我們需要一個相關性的值。在ElasticSearch的查詢結(jié)果中妈踊, 相關性分值會用_score字段來給出一個浮點型的數(shù)值了嚎,所以默認情況下,結(jié)果集以_score進行倒序排列廊营。

注意:在Elasticsearch中歪泳,如果使用text類型的字段作為排序依據(jù),會有問題露筒。Elasticsearch需要對text類型字段數(shù)據(jù)做分詞處理呐伞。如果使用text類型字段做排序,Elasticsearch給出的排序結(jié)果未必友好慎式,畢竟分詞后伶氢,先使用哪一個單詞做排序都是不合理的假哎。所以Elasticsearch中默認情況下不允許使用text類型的字段做排序,如果需要使用字符串做結(jié)果排序鞍历,則可使用keyword類型字段作為排序依據(jù)舵抹,因為keyword字段不做分詞處理。

如果對一個text field進行排序劣砍,結(jié)果往往不準確惧蛹,因為分詞后是多個單詞,再排序就不是我們想要的結(jié)果了刑枝。

通常解決方案是香嗓,將一個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("結(jié)果" + hit.getSourceAsMap() + ",score:" + hit.getScore());
    }
}
@Test
public void testSortQueryBySort() throws IOException {
    sortQuery.sortQuery(Constants.INDEX_NAME, "brandName", "三星", "id", SortOrder.DESC);
}
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末像云,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蚂夕,更是在濱河造成了極大的恐慌迅诬,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件婿牍,死亡現(xiàn)場離奇詭異侈贷,居然都是意外死亡,警方通過查閱死者的電腦和手機等脂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門俏蛮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人上遥,你說我怎么就攤上這事搏屑。” “怎么了露该?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵睬棚,是天一觀的道長。 經(jīng)常有香客問我解幼,道長,這世上最難降的妖魔是什么包警? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任撵摆,我火速辦了婚禮,結(jié)果婚禮上害晦,老公的妹妹穿的比我還像新娘特铝。我一直安慰自己暑中,他們只是感情好,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布鲫剿。 她就那樣靜靜地躺著鳄逾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪灵莲。 梳的紋絲不亂的頭發(fā)上雕凹,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機與錄音政冻,去河邊找鬼枚抵。 笑死,一個胖子當著我的面吹牛明场,可吹牛的內(nèi)容都是我干的汽摹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼苦锨,長吁一口氣:“原來是場噩夢啊……” “哼逼泣!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤淤袜,失蹤者是張志新(化名)和其女友劉穎碌识,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體砍的,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年莺治,在試婚紗的時候發(fā)現(xiàn)自己被綠了廓鞠。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡谣旁,死狀恐怖床佳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情榄审,我是刑警寧澤砌们,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站搁进,受9級特大地震影響浪感,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜饼问,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一影兽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧莱革,春花似錦峻堰、人聲如沸讹开。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽旦万。三九已至,卻和暖如春镶蹋,著一層夾襖步出監(jiān)牢的瞬間成艘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工梅忌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留狰腌,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓牧氮,卻偏偏與公主長得像琼腔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子踱葛,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容