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关键字可以到官网上查。

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