ES入門和簡單使用

ES入門和簡單使用


項目背景:

項目中有一部分涉及到IM,所有的消息都是以一個JSON串的方式存儲到一張表中。表的結構大概如下

id session_id Message
1 1 [json]

產品提了個需求,可以通過消息關鍵字來搜索會話。但是目前的表是Json格式的,所以直接用sql語句搜索是不友好的。鑑於此,引入ElasticSearch (ES)。

官方地址

https://www.elastic.co/guide/en/elasticsearch/reference/6.0/getting-started.html

目前已經更新到7.8版本,我們項目裏面使用的是7.6

官網有具體的安裝、配置和使用教程,想深入學習的可以仔細閱讀官方文檔

簡單介紹

Elasticsearch是面向文檔(document oriented)的,這意味着它可以存儲整個對象或文檔(document)。然而它不僅僅是存儲,還會**索引(index)**每個文檔的內容使之可以被搜索。在Elasticsearch中,你可以對文檔(而非成行成列的數據)進行索引、搜索、排序、過濾。這種理解數據的方式與以往完全不同,這也是Elasticsearch能夠執行復雜的全文搜索的原因之一。

同傳統數據庫的對比

Relational DB -> Databases -> Tables -> Rows -> Columns

Elasticsearch -> Indices -> Types -> Documents -> Fields

Elasticsearch集羣可以包含多個索引(indices)(數據庫),每一個索引可以包含多個類型(types)(表),每一個類型包含多個文檔(documents)(行),然後每個文檔包含多個字段(Fields)(列)。

簡單使用

1. query

單條件單字段匹配

"query": {
    "match": {
      "event": {                      //字段名稱
        "query": "BitSea 352439384",  //搜索字段的內容,空格可以分詞
        "operator": "and"             //and表示分詞並,都要有,還有個 默認是or 的關係
      }
    }
  }

對應JAVA代碼

//查詢條件
QueryBuilder queryBuilder = QueryBuilders
				.matchQuery("event", "BitSea 352439384").operator(Operator.AND);

單條件多字段

"query": {
   {
    "multi_match": {
        "query":  "搜索內容",
        "fields": [ "字段1", "字段2" ] 
    	}
		}
 }

java代碼

QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery("BitSea 352439384", "field1", "field2").operator(Operator.AND);

多條件多字段

"query": {
    "bool": {
      "should": [
        {"match": { "event": "TEXT"}},
        {"match": { "FIELD": "TEXT"}}
      ]
    }
  }

java代碼

BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.should(QueryBuilders.matchQuery("cname", keyword));
        queryBuilder.should(QueryBuilders.matchQuery("industry", keyword));

2 Aggregations 聚合搜索

Aggregations我是用來去重,和查總數的。 它的方法比較多,很強大。

繼續以上面的來舉例子

去重

{
  "query": {
    "match": {
      "event": {
        "query": "BitSea 352439384",
        "operator": "and"
      }
    }
  },
  "aggs": {
    "name": {                     //去重自定義字段名
      "terms": {
        "field": "session_id",
        "size": 10                //查詢數量的大小
      }
    }
  },
  "size": 1,
  "from": 0
}

aggs和query是同級別的,上面這段的意思是,以session_id 字段對query的結果進行去重,然後查出前10條,來看JAVA代碼

//聚合篩選器,主要用來分頁和去重
        AggregationBuilder aggregation = AggregationBuilders
                .terms("去重字段名字").field("session_id").size(10);
        //新建自定義查詢
        QueryBuilder queryBuilder = QueryBuilders
                .matchQuery("event", "BitSea 352439384").operator(Operator.AND);

查總數

"aggs": {
    "count": {                //查詢總數
      "cardinality": {
        "field":"session_id"
      }
    },
    "測試": {
      "terms": {
        "field": "session_id",
        "size":10,
        "order":{
          "_key": "desc"
        }
      }
    }
  }

java代碼

AggregationBuilder aggregation = AggregationBuilders.cardinality("count").field("session_id");

3. 查詢

查詢條件都梳理好了後,進行查詢,java代碼如下

 SearchSourceBuilder ssb = new SearchSourceBuilder()
                .query(queryBuilder)    //組合查詢條件
                .sort(sortBuilder)      //排序條件
                .aggregation(aggregation)    //上面的去重
                .aggregation(aggregation2);   //上面的查總數
        SearchRequest sr = new SearchRequest(new String[]{"cs_session_session_event_sharding_alias"});     //自己索引名稱
        sr.source(ssb);

SearchResponse searchResponse = esClient.search("searchCluster", sr);  //獲取查詢結果


獲取結果

Terms sessionIds = searchResponse.getAggregations().get("去重字段名字");   //括號裏是剛纔自己起的名字,總共有多少個SessionIds
		Cardinality cardinality = searchResponse.getAggregations().get("總數");
		System.out.println(cardinality.getValue());
		for (Terms.Bucket entry : sessionIds.getBuckets()) {
			String key = String.valueOf(entry.getKey());   //每個session
			long docCount = entry.getDocCount();		   //每個擊中多少條
			System.out.println("key: "+key+ "doc_count:" + docCount);
		}

特別注意

特殊字符

title+-&&||!(){}[]^\"~*?:\\
這些都需要轉義

你需要引用一個jar,lucene-queryparser,按自己的es版本去添加

<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
<version>5.4.1</version>
</dependency>

使用QueryParser.escape(String query)方法處理字符即可,

分詞器的使用

https://blog.csdn.net/ahwsk/article/details/101270300

題外話

ES7.x版本還支持 sql查詢,更推薦這中方式,但是比較複雜的邏輯有時候不太支持,具體的sql關鍵字可以到官網上查。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章