天天看點

elasticsearch 介紹、查詢及使用(must、should)

建立索引

{
  "mappings": {
    "properties": {
        "id": {"type":"keyword"},
        "pname": {"type":"text", "analyzer": "ik_max_word", "search_analyzer": "ik_max_word","fields": {"keyword":{"type":"keyword"}}},
        "title": {"type":"text", "analyzer": "ik_max_word", "search_analyzer": "ik_max_word","fields": {"keyword":{"type":"keyword"}}},
        "describe": {"type":"text", "analyzer": "ik_max_word", "search_analyzer": "ik_max_word","fields": {"keyword":{"type":"keyword"}}},
        "rich_text": {"type":"text", "analyzer": "ik_max_word", "search_analyzer": "ik_max_word","fields": {"keyword":{"type":"keyword"}}},
        "update_time": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"}
    }
  }
}
           
@Id
    @Field(index=true, store = true, type = FieldType.Keyword)
    private String id;
​
    /**
     * 更新時間
     */
    @JSONField(serialize = false)
    @Field(index = true, store = true, type = FieldType.Date,format = DateFormat.custom,pattern = "yyyy-MM-dd HH:mm:ss")
    private Date update_time;
   
    /**
     * 标題
     */
    @Field(index = true, analyzer = "ik_max_word", store = true, searchAnalyzer = "ik_smart", type = FieldType.Text)
    private String title;
    
    /** 名稱*/
    @Field(index = true, analyzer = "ik_max_word", store = true, searchAnalyzer = "ik_smart", type = FieldType.Text)
    private String pname;
    
    /**
     * 摘要
     */
    @Field(index = true, analyzer = "ik_max_word", store = true, searchAnalyzer = "ik_smart", type = FieldType.Text)
    private java.lang.String describe;
    
    /**
     * 文章正文
     */
    @JSONField(serialize = false)
    @Field(index = true, analyzer = "ik_max_word", store = true, searchAnalyzer = "ik_smart", type = FieldType.Text)
    private String rich_text;
           

查詢介紹

must 傳回的文檔必須滿足must子句的條件,并且參與計算分值

filter 傳回的文檔必須滿足filter子句的條件,但是不會像must一樣,參與計算分值

should 傳回的文檔可能滿足should子句的條件.在一個bool查詢中,如果沒有must或者filter,有一個或者多個should子句,那麼隻要滿足一個就可以傳回.

must_not 傳回的文檔必須不滿足定義的條件

matchAllQuery比對所有

termQuery精準比對,大小寫敏感且不支援

matchPhraseQuery對中文精确比對

matchQuery("key", Obj) 單個比對, field不支援通配符, 字首具進階特性

multiMatchQuery("text", "field1", "field2"..); 比對多個字段, field有通配符忒行

實作比對模糊查詢和等值查詢

模糊查詢

BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
​
boolQueryBuilder.should(QueryBuilders.wildcardQuery("title", "*" + keyword + "*"));
           

等值查詢 必須儲存此字段有 “字段”.keyword 索引

BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
​
boolQueryBuilder.should(QueryBuilders.matchQuery("title.keyword", keyword))
           

注意:當使用should查詢時,如果包含了must或者filter查詢,那麼should的查詢語句就不是或者的意思了,而是有或者沒有都行的含義。

例如:在a=1且b=2的資料中,找出c=1或者d=2的資料

{
    "query": {
        "bool": {
            "must": [{
                "match": {
                    "a": "1",
                    "b": "2"
                }
            }],
            "should": [{
                    "match": {
                        "c": "1" 
                    }
                },
                {
                    "match": {   
                        "d": "2"    
                    }
                }  
            ]
        }
    }
}
           

這樣寫的時候should是沒有用的,這是新手可能犯的錯誤之一。 在編寫查詢條件的時候,不能用口頭上的邏輯進行編寫,而是要換成數學邏輯才能進行執行(資料庫同理)。 如上例,數學邏輯應該是 (a==1&&b==2&&c==1)||(a==1&&b==2&&d==2)(java and c語言版),這樣的結構去查詢。

實作方式一:

QueryBuilder query = QueryBuilders.boolQuery()
.should(QueryBuilders.boolQuery()
        .filter(QueryBuilders.termQuery("a", 1))
        .filter(QueryBuilders.termQuery("b", 2))
        .filter(QueryBuilders.termQuery("c", 1))
.should(QueryBuilders.boolQuery()
        .filter(QueryBuilders.termQuery("a", 1))
        .filter(QueryBuilders.termQuery("b", 2))
        .filter(QueryBuilders.termQuery("d", 2));
           
{
    "query": {
        "bool": {
            "should": [{
                "match": {
                    "a": "1",
                    "b": "2",
                    "c": "1"
                }
            }],
            "should": [{
                "match": {
                    "a": "1",
                    "b": "2",
                    "d": "2"
                }
            }]
        }
    }
}
           

實作方式二:

BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.should(QueryBuilders.matchQuery("title", keyword))
boolQueryBuilder.should(QueryBuilders.matchQuery("pname", keyword));
//要求至少滿足一個Should條件
boolQueryBuilder.minimumShouldMatch(1);
           
{
  "bool" : {
    "must" : [
      {
        "term" : {
          "site_id" : {
            "value" : 110,
            "boost" : 1.0
          }
        }
      }
    ],
    "should" : [
      {
        "match" : {
          "title" : {
            "query" : "咖啡",
            "operator" : "OR"
          }
        }
      },
​
      {
        "match" : {
          "pname" : {
            "query" : "咖啡",
            "operator" : "OR"
          }
        }
      },
    ],
    "minimum_should_match" : "1"
  }
}
           

實作方式三:

String[] searchArray = new String[]{"title","pname"};
searchKeys.toArray(searchArray);
boolQueryBuilder.must(QueryBuilders.multiMatchQuery(keyword, searchArray).operator(Operator.AND));
           
{
  "bool" : {
    "must" : [
      {
        "term" : {
          "site_id" : {
            "value" : 110,
            "boost" : 1.0
          }
        }
      },
      {
        "multi_match" : {
          "query" : "咖啡",
          "fields" : [
            "pname^1.0",
            "title^1.0"
          ],
          "operator" : "AND"
        }
      }
    ]
  }
}
           

繼續閱讀