文章目录

  • 一、SQL转换
  • 1、单条件查询
  • (1)模糊查询
  • 1.常用的字符串查询
  • 2.前缀查询 如果字段没分词,就匹配整个字段前缀
  • (2)多字段模糊查询
  • (3)wildcard query
  • 2、多条件查询
  • 1、and、or、not
  • 2、排序查询
  • 3、一个字段匹配多个值
  • 4、一个值匹配多个字段
  • 5、范围查询
  • (1)统计某个字段的数量
  • (2)去重统计某个字段的数量(有少量误差)
  • (3)聚合过滤
  • (5)求和
  • (6)求平均
  • (7)求最大值
  • (8)求最小值
  • (9)按日期间隔分组
  • (10)获取聚合里面的结果
  • (11)嵌套的聚合
  • (12)反转嵌套
  • 获取数据查询结果
  • 获取聚合函数结果
  • 1、布尔查询
  • 集合查询
  • 3、获取聚合结果集
  • 6、常见问题
  • 1、匹配的字段:
  • **2、条件查询中范围查询**
  • 3、排序查询:
  • **4、分组后的桶类型**
  • 5、条件查询和聚合分组查询的结果是分开的
  • 6、聚合查询时报UnmappedTerms转换错误
  • 二、ES索引操作
  • 添加字段并赋值
  • 删除字段
  • 添加mappping映射
  • 修改mapping字段类型
  • 三、ES分页查询
  • 1、不用重启集群就可以实现(亲测,可实现)
  • 2、通过配置文件设置(需重启集群,未测试)
  • 3、scroll深度搜索(推荐使用)

一、SQL转换

Select
From
Where and or not
Group by
Having
Order by

1、单条件查询

Select from book where name = “小明”

精确匹配

QueryBuilders.matchQuery("name",”小明”);

(1)模糊查询

1.常用的字符串查询
Select  from book where name like “%小%”

QueryBuilders.queryStringQuery("fieldValue").field("fieldName");//左右模糊
2.前缀查询 如果字段没分词,就匹配整个字段前缀
QueryBuilders.prefixQuery("fieldName","fieldValue");

(2)多字段模糊查询

String[] fieldName = new String[2];

fieldName[0] = "明";

fieldName[1] = "年";

QueryBuilders.moreLikeThisQuery(fieldName);

(3)wildcard query

通配符查询,支持* 任意字符串;?任意一个字符

QueryBuilders.wildcardQuery("fieldName","ctr*");//前面是fieldname,后面是带匹配字符的字符串

QueryBuilders.wildcardQuery("fieldName","c?r?");

2、多条件查询

1、and、or、not

组合查询BoolQueryBuilder

  must(QueryBuilders)  :AND

  mustNot(QueryBuilders) :NOT

  should:        :OR

例子:

Select * from book where author = “年轻” or count =1

builder.must(QueryBuilders.queryStringQuery("年轻").field("author"));

 builder.should(QueryBuilders.matchQuery("count",1));

2、排序查询

1、排序查询

Select * from book order by count asc

FieldSortBuilder sort = SortBuilders.fieldSort("count").order(SortOrder.ASC);

3、一个字段匹配多个值

builder.must(QueryBuilders.termsQuery("desc", "年","书"));

4、一个值匹配多个字段

builder.must(QueryBuilders.multiMatchQuery("小", "author", "desc"));

5、范围查询

闭区间查询

QueryBuilder queryBuilder0 = QueryBuilders.rangeQuery("fieldName").from("fieldValue1").to("fieldValue2");

开区间查询

QueryBuilder queryBuilder1 = QueryBuilders.rangeQuery("fieldName").from("fieldValue1").to("fieldValue2").includeUpper(false).includeLower(false);//默认是true,也就是包含

大于

QueryBuilder queryBuilder2 = QueryBuilders.rangeQuery("fieldName").gt("fieldValue");

大于等于

QueryBuilder queryBuilder3 = QueryBuilders.rangeQuery("fieldName").gte("fieldValue");

小于

QueryBuilder queryBuilder4 = QueryBuilders.rangeQuery(“fieldName”).lt(“fieldValue”);

小于等于

QueryBuilder queryBuilder5 = QueryBuilders.rangeQuery("fieldName").lte("fieldValue");1、

聚合查询

桶Buckets:类似于group by分组后的结果放入一个一个的桶中

指标Metrics:类似于min,max、sum筛选计算。

(1)统计某个字段的数量

ValueCountBuilder vcb=  AggregationBuilders.count("count_uid").field("uid");

(2)去重统计某个字段的数量(有少量误差)

CardinalityBuilder cb= AggregationBuilders.cardinality("distinct_count_uid").field("uid");

(3)聚合过滤

FilterAggregationBuilder fab= AggregationBuilders.filter("uid_filter").filter(QueryBuilders.queryStringQuery("uid:001"));

(4)按某个字段分组

TermsBuilder tb=  AggregationBuilders.terms("group_name").field("name");

(5)求和

SumBuilder  sumBuilder=	AggregationBuilders.sum("sum_price").field("price");

(6)求平均

AvgBuilder ab= AggregationBuilders.avg("avg_price").field("price");

(7)求最大值

MaxBuilder mb= AggregationBuilders.max("max_price").field("price");

(8)求最小值

MinBuilder min=	AggregationBuilders.min("min_price").field("price");

(9)按日期间隔分组

DateHistogramBuilder dhb= AggregationBuilders.dateHistogram("dh").field("date");

(10)获取聚合里面的结果

TopHitsBuilder thb=  AggregationBuilders.topHits("top_result");

(11)嵌套的聚合

NestedBuilder nb= AggregationBuilders.nested("negsted_path").path("quests");

(12)反转嵌套

AggregationBuilders.reverseNested("res_negsted").path("kps ");

获取数据查询结果

  • 第一种方式
Page<Book> search = bookRepository.search(nativeSearchQuery);

 List<Book> content = search.getContent();
  • 第二种方式

使用封装的对象。

List<Book> bookList = elasticsearchTemplate.queryForList(nativeSearchQuery, Book.class);

  for (Book b1:bookList){

   System.out.printf(b1.getAuthor());

 }

获取聚合函数结果

Aggregations aggregations = elasticsearchTemplate.query(nativeSearchQuery, new ResultsExtractor<Aggregations>() {

      @Override

      public Aggregations extract(SearchResponse searchResponse) {

        return searchResponse.getAggregations();

      }

    });

1、代码样例

1、布尔查询

BoolQueryBuilder queryBuilder = new BoolQueryBuilder();

字段匹配

queryBuilder.must(QueryBuilders.matchPhraseQuery("itemKey", itemKey));

范围查询

RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("statDate").from(startDate).to(endDate);

类似于 sql语句中 hourkey in (1,2,3,4);

集合查询

if (null != hour) {
  queryBuilder.must(QueryBuilders.termsQuery("hourKey",hour));
}

queryBuilder.must(rangeQueryBuilder);

NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();

构建查询对象

nativeSearchQueryBuilder.withIndices("dwl_over_time_event_report_hour") //索引    .withQuery(queryBuilder)				//查询语句   .addAggregation(AggregationBuilders.terms("statDateGroup").field("statDate") //聚合       .subAggregation(AggregationBuilders.sum("over_time_event_num_total").field("overTimeEventNumTotal"))); NativeSearchQuery nativeSearchQuery = nativeSearchQueryBuilder.build(); List<DwlOverTimeEventReportHourEs> list = new ArrayList<>();

3、获取聚合结果集

Aggregations aggregations = elasticsearchTemplate.query(nativeSearchQuery, new ResultsExtractor<Aggregations>() { @Override
  public Aggregations extract(SearchResponse searchResponse) {
   return searchResponse.getAggregations();
  }
});

聚合结果转成map

Map<String, Aggregation> aggregationMap = aggregations.asMap();

//获取聚合后的桶、类似group by 后的结果。

LongTerms hourKeyGroup_list = (LongTerms) aggregationMap.get("statDateGroup");

List<LongTerms.Bucket> buckets1 = hourKeyGroup_list.getBuckets();
for (int i = 0; i < buckets1.size(); i++) {
  Aggregations aggregations1 = buckets1.get(i).getAggregations();

获取分组字段

String statDate = buckets1.get(i).getKeyAsString();
  Map<String, Aggregation> aggregationMap1 = aggregations1.asMap();

获取对应类型的聚合值

InternalSum sum_over_time_event_num_total = (InternalSum) aggregationMap1.get("over_time_event_num_total");
  int value = (int) sum_over_time_event_num_total.getValue();

  DwlOverTimeEventReportHourEs dwlOverTimeEventReportHour = new DwlOverTimeEventReportHourEs();
  dwlOverTimeEventReportHour.setStatDate(DateUtil.parseDate(statDate,"yyyy-MM-dd"));
  dwlOverTimeEventReportHour.setOverTimeEventNumTotal(value);

  list.add(dwlOverTimeEventReportHour);
}
return list;

6、常见问题

1、匹配的字段:

要转换成与ES中字段类型

例如Es时间类型:yyyy-MM-dd ,我们也要转换成这种类型才能匹配

2、条件查询中范围查询

Ps:注意names是一个字符串数组,获取是一个整形数组的话,你需要范围查询时,一定要在后面加上.keyword,不然无法起到类似于mysql中in的类型。

if (null != names) {
  queryBuilder.must(QueryBuilders.termsQuery("name.keyword",name));
}

3、排序查询:

Ps:排序查询需要注意的是,如果是string类型,不希望分词就要加上.keyword,不然会报错。

Ps:还有一个我认为重要的就是,如果索引建立了,没有数据的情况其中(也就是es中的index没有字段),使用排序查询需要在后面对象字段的类型.unmappedType(“String”)。不然会报错,原因:es中没有对应的字段,也就没有对应字段的类型。

FieldSortBuilder sort = SortBuilders.fieldSort("name.keywrod").order(SortOrder.DESC).unmappedType("string");

4、分组后的桶类型

Ps:根据你分组的字段类型进行类型转换,例如,你的分组字段类型是int,flat,double类型的,可以全部转成LongTerms类型(Date日期类型可以也是LongTerms)

如果是其他类型的,例如String转换成StringTerms类型。

LongTerms hourKeyGroup_list = (LongTerms) aggregationMap.get("statDateGroup");

5、条件查询和聚合分组查询的结果是分开的

PS:es中这里很难受,不先mysql,一条sql语句就解决了,

Es中条件查询中有聚合分组,结果是聚合分组之前的原始数据。无法得到分组后的结果,

这也就是上面为什么要单独获取聚合分组后的结果,然后进行数据组装了。

PS:分组查询一定要住处一个问题,默认返回10条数据,一定要设置分组后的条数,不认查询的数据不准确。多分terms都需要设置。

.addAggregation(AggregationBuilders.terms("yearmonthKeyGroup").field("yearmonthKey.keyword").size(EsPageConstant.totalPageSize)


6、聚合查询时报UnmappedTerms转换错误

出现这种情况是因为,ES索引建立了,但是没有记录查询,也就是没有数据。

解决:

Aggregation yearmonthKeyMapper = aggregationMap.get("yearmonthKeyGroup");
 if (yearmonthKeyMapper instanceof UnmappedTerms){
 	return list;
 }

二、ES索引操作

添加字段并赋值

POST http://10.10.206.34:9200/dwl_high_volatility_report_week/_update_by_query
{
    "script": {
        "float": "painless",
        "inline": "if (ctx._source.intervEventDiff== null) {ctx._source.intervEventDiff= 0}"
    }
}

删除字段

POST index/type/_update_by_query
{
"script":{
"lang":"painless",
"inline":"ctx._source.remove(\"dept_name\")"
}
}

添加mappping映射

PUT /myindex/_mapping/article
{
  "properties": {
       "new_field_name": {
           "type":  "text"
       }
   }
}

修改mapping字段类型

一、原索引

PUT my_index
{
  "mappings": {
    "_doc": {
      "properties": {
        "create_date": {
          "type":   "date",
          "format": "yyyy-MM-dd ||yyyy/MM/dd"
           
        }
      }
    }
  }
}

二、创建新索引

PUT my_index2
    {
      "mappings": {
        "_doc": {
          "properties": {
            "create_date": {
              "type":   "text"

            }
          }
        }
      }
    }

三、同步数据

POST _reindex                   
{
  "source": {
    "index": "my_index"
  },
  "dest": {
    "index": "my_index2"
  }
}

四、删除原索引

DELETE 	my_index

五、设置别名

POST /_aliases
  {
        "actions": [
            {"add": {"index": "my_index2", "alias": "my_index"}}
        ]
  }

三、ES分页查询

int pageNum = 1;
int pageSize = 10;
Pageable pageable = PageRequest.of(pageNum-1, pageSize);
FieldSortBuilder fsb = SortBuilders.fieldSort("index").order(SortOrder.DESC)
                .unmappedType("string");

//NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withSort(fsb).build();
        
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withSort(fsb)
                .withPageable(pageable).build();

//NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().build();

Page<TestModelEs> page = (Page<TestModelEs>)testModelEsRepository.search(searchQuery);

//获取总条数
long totalElements = page.getTotalElements();
//获取总页数
int totalPages = page.getTotalPages();

List<TestModelEs> content = page.getContent();

二、ES查询限制(<10000)

1、不用重启集群就可以实现(亲测,可实现)

例如:
curl -H “Content-Type: application/json” -XPUT http://10.10.203.90:9200/test_es_page_limit/_settings -d ‘{ “index” : { “max_result_window” : 50000}}’

2、通过配置文件设置(需重启集群,未测试)

配置文件路径:config/elasticsearch.yml
新配置:
max_result_window: 200000

3、scroll深度搜索(推荐使用)

//要查询第几页(传递的参数)
int pageNum = 0;
Int pageSize = 10;
List resultAdminLogs = new ArrayList<>();

//排序
    FieldSortBuilder fsb = SortBuilders.fieldSort("index").order(SortOrder.DESC)
            .unmappedType("string");

    //构建查询
    NativeSearchQueryBuilder nsQueryBuilder = new NativeSearchQueryBuilder();

    //分页
//pageSize:每页查出多条数据
 int count = 0;
 Pageable pageable = PageRequest.of(count, pageSize);nsQueryBuilder.withPageable(pageable).withIndices(“test_es_page_limit”)
 .withSort(fsb);//深度搜索
    ScrolledPage<TestModelEs> scrollAdminLog = elasticsearchTemplate
            .startScroll(SCROLL_TIMEOUT, nsQueryBuilder.build(), TestModelEs.class);

    while (scrollAdminLog.hasContent()){
        count++;
        List<TestModelEs> content = scrollAdminLog.getContent();
        if(pageNum == count){
            return content; //返回结果
        }
        resultAdminLogs.addAll(content);
        //取下一页,scrollId在es服务器上可能会发生变化,需要用最新的;发起				continueScroll请求会重新刷新快照保留时间
        scrollAdminLog = (ScrolledPage<TestModelEs>) elasticsearchTemplate
                .continueScroll(scrollAdminLog.getScrollId(), SCROLL_TIMEOUT, 					TestModelEs.class);
    }
    //及时清除es快照,释放资源
    elasticsearchTemplate.clearScroll(scrollAdminLog.getScrollId());