ElasticSearch全文详解及具体配置
一、全文检索基础
1.什么是全文检索
将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引
例如:字典。字典的拼音表和部首检字表就相当于字典的索引,对每一个字的解释是非结构化的,如果字典没有音节表和部首检字表,在茫茫辞海中找一个字只能顺序扫描。然而字的某些信息可以提取出来进行结构化处理,比如读音,就比较结构化,分声母和韵母,分别只有几种可以一一列举,于是将读音拿出来按一定的顺序排列,每一项读音都指向此字的详细解释的页数。我们搜索时按结构化的拼音搜到读音,然后按其指向的页数,便可找到我们的非结构化数据——也即对字的解释
这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-text Search)
虽然创建索引的过程也是非常耗时的,但是索引一旦创建就可以多次使用,全文检索主要处理的是查询,所以耗时间创建索引是值得的。
2.相关概念
- 索引库
索引库就是存储索引的保存在磁盘上的一系列的文件。里面存储了建立好的索引信息以及文档对象
一个索引库相当于数据库中的一张表
document对象
获取原始内容的目的是为了索引,在索引前需要将原始内容创建成文档(Document),文档中包括一个一个的域(Field),域中存储内容。每个文档都有一个唯一的编号,就是文档id
document对象相当于表中的一条记录
field对象
如果我们把document看做是数据库中一条记录的话,field相当于是记录中的字段。field是索引库中存储数据的最小单位。field的数据类型大致可以分为数值类型和文本类型,一般需要查询的字段都是文本
类型的,field的还有如下属性:是否分词:是否对域的内容进行分词处理。前提是我们要对域的内容进行查询
是否索引:将Field分析后的词或整个Field值进行索引,只有索引方可搜索到
比如:商品名称、商品简介分析后进行索引,订单号、身份证号不用分词但也要索引,这些将来都
要作为查询条件是否存储:将Field值存储在文档中,存储在文档中的Field才可以从Document中获取 比如:商品
名称、订单号,凡是将来要从Document中获取的Field都要存储term对象 从文档对象中拆分出来的每个单词叫做一个Term,不同的域中拆分出来的相同的单词是不同的term。term中包含两部分一部分是文档的域名,另一部分是单词的内容。term是创建索引的关键词对象
二、ElasticSearch简介
2.1 什么是ElasticSearch
Elaticsearch,简称为es, es是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。es也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单
2.2 ElasticSearch对比Solr
- Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能
- Solr 支持更多格式的数据,而 Elasticsearch 仅支持json文件格式
- Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能,高级功能多有第三方插件提
供 - Solr 在传统的搜索应用中表现好于 Elasticsearch,但在处理实时搜索应用时效率明显低于Elasticsearch
三、Elasticsearch 安装
采用docker安装
- docker镜像下载
docker pull elasticsearch:5.6.8
- 安装es容器
docker run -di --name=kkb_es -p 9200:9200 -p 9300:9300 elasticsearch:5.6.8
9200端口(Web管理平台端口) 9300(服务默认端口)
- 开启远程连接
elasticsearch从5版本以后默认不开启远程连接,程序直接连接会报错
我们需要修改es配置开启远程连接
登录容器
docker exec -it kkb_es /bin/bash
进去config目录
cd config
修改elasticsearch.yml文件
若出现vi命令无法识别,则安装该编辑器
设置apt下载源
docker cp ~/sources.list kkb_es:/etc/apt/sources.list
安装vim编辑器
apt-get update
apt-get install vim
安装好之后就可以修改elasticsearch.yml配置文件了
http.host: 0.0.0.0transport.host: 0.0.0.0
#集群的名称
cluster.name: my-application
#跨域配置
http.cors.enabled: true
http.cors.allow-origin: "*"
network.host: 192.168.249.4
配置完毕之后退出容器,重启该容器
docker restart kkb_es
- 系统参数配置
因为elasticsearch在启动时会比较占据资源,所以将虚拟机进行系统调优开放更多的资源
修改vi /etc/security/limits.conf,追加如下内容
* soft nofile 65536
* hard nofile 65536
修改vi /etc/sysctl.conf,追加内容
vm.max_map_count=655360
执行下面命令,使修改后的内核参数生效
sysctl -p
重启虚拟机,再启动容器,即可远程访问
reboot
四、ElasticSearch的客户端操作
IK分词器
IKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。从2006年12月推出1.0版开始,IKAnalyzer已经推出 了3个大版本。最初,它是以开源项目Lucene为应用主体的,结合词典分词和文法分析算法的中文分词组件。新版本的IKAnalyzer3.0则发展为 面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现
安装
- 下载地址https://github.com/medcl/elasticsearch-analysis-ik/releases
将ik分词器上传到服务器.解压并改名为ik
unzip elasticsearch-analysis-ik-5.6.8.zip
mv elasticsearch ik
将ik目录拷贝到docker容器的plugins目录下
docker cp ./ik kkb_es:/usr/share/elasticsearch/plugins
- 测试
访问 :http://192.168.249.4:9200/_analyze?analyzer=ik_smart&pretty=true&text=我是程序员
出现如下页面
ik_max_word:会将文本做最细粒度的拆分
比如会将“中华人民共和国人民大会堂”拆分为“中华人民共和国、中华人民、中华、华人、人民共和国、人民、共和国、大会堂、大会、会堂等词语。
ik_smart:会做最粗粒度的拆分
比如会将“中华人民共和国人民大会堂”拆分为中华人民共和国、人民大会堂。
Kibana使用
Kibana 是一款开源的数据分析和可视化平台,它是 Elastic Stack 成员之一,设计用于和 Elasticsearch协作。您可以使用 Kibana 对 Elasticsearch 索引中的数据进行搜索、查看、交互操作。您可以很方便的利用图表、表格及地图对数据进行多元化的分析和呈现
Kibana 可以使大数据通俗易懂。它很简单,基于浏览器的界面便于您快速创建和分享动态数据仪表板来追踪 Elasticsearch 的实时数据变化
下载安装
这里使用docker安装
- 镜像安装
docker pull docker.io/kibana:5.6.8
- 安装kibana容器
docker run -it -d -e ELASTICSEARCH_URL=http://192.168.249.4:9200 --name kibana -p 5601:5601 kibana:5.6.8
ELASTICSEARCH_URL=http://192.168.249.4:9200:是指链接的es的地址
restart=always:每次服务都会重启,也就是开启启动
5601:5601:端口号
- 测试
访问http:192.168.249.4:5601
如下图所示
Kibana使用
Kibana具体使用可以查看其他文档,这里不再赘述
ElasticSearch编程操作
创建工程
<dependencies><dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>5.6.8</version></dependency><dependency><groupId>org.elasticsearch.client</groupId><artifactId>transport</artifactId><version>5.6.8</version></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-to-slf4j</artifactId><version>2.9.1</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.24</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-simple</artifactId><version>1.7.21</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.12</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency></dependencies>
创建索引index
@Testpublic void createIndex() {//1. 配置Settings settings = Settings.builder().put("cluster.name", "my-application").build();//2. 客户端client = new PreBuiltTransportClient(settings);client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("192.168.249.4"), 9300));//3. 使用api创建索引client.admin().indices().prepareCreate("hello_index").get();//4. 关闭clientclient.close();}
索引即相当于数据库
创建mapping映射
//创建映射@Testpublic void setMappings() throws IOException, ExecutionException, InterruptedException {// 添加映射/*** 格式:* "mappings" : {}}"article" : {"dynamic" : "false","properties" : {"id" : { "type" : "string" },"content" : { "type" : "string" },"author" : { "type" : "string" }}}}*/XContentBuilder builder = XContentFactory.jsonBuilder().startObject().startObject("article").startObject("properties").startObject("id").field("type", "integer").field("store", "yes").endObject().startObject("title").field("type", "string").field("store", "yes").field("analyzer","ik_smart").endObject().startObject("content").field("type", "string").field("store", "yes").field("analyzer","ik_smart").endObject().endObject().endObject().endObject();
// 创建索引client.admin().indices().preparePutMapping("hello_index").setType("article").setSource(builder).get();
//释放资源client.close();}
mapping映射如下所示
建立文档document
建立文档(通过XContentBuilder)
/*** 通过XContentBuilder构建Document对象* @throws Exception*/@Testpublic void testAddDocument() throws Exception {//创建一个client对象//创建一个文档对象XContentBuilder builder = XContentFactory.jsonBuilder().startObject().field("id", 2l).field("title", "北方入秋速度明显加快 多地降温幅度最多可达10度 22222").field("content", "阿联酋一架客机在纽约机场被隔离 10名乘客病倒").endObject();//把文档对象添加到索引库client.prepareIndex()//设置索引名称.setIndex("hello_index")//设置type.setType("article")//设置文档的id,如果不设置的话自动的生成一个id.setId("2")//设置文档信息.setSource(builder)//执行操作.get();//关闭客户端client.close();}
查看数据浏览板块里面的hello_index索引,如下图所示
建立文档(使用Jackson转换实体)
- 创建Article实体类
package com.study;public class Article {private Integer id;private String title;private String content;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}
}
- 添加jackson依赖
<!-- jackson依赖--><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.8.1</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.8.1</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.8.1</version></dependency>
- 构造相关方法
@Testpublic void testAddDocument2() throws Exception {//创建一个Article对象Article article = new Article();//设置对象的属性article.setId(3l);article.setTitle("MH370坠毁在柬埔寨密林?中国一公司调十颗卫星去拍摄");article.setContent("警惕荒唐的死亡游戏!俄15岁少年输掉游戏后用电锯自杀");//把article对象转换成json格式的字符串。ObjectMapper objectMapper = new ObjectMapper();String jsonDocument = objectMapper.writeValueAsString(article);System.out.println(jsonDocument);//使用client对象把文档写入索引库client.prepareIndex("hello_index","article", "3").setSource(jsonDocument, XContentType.JSON).get();//关闭客户端client.close();}
查看数据浏览中的hello_index相关索引库的信息
对hello_index索引库添加多条Document对象,方便接下来的操作
@Testpublic void testAddDocument3() throws Exception {for (int i = 4; i < 100; i++) {//创建一个Article对象Article article = new Article();//设置对象的属性article.setId(i);article.setTitle("女护士路遇昏迷男子跪地抢救:救人是职责更是本能" + i);article.setContent("江西变质营养餐事件已致24人就医 多名官员被调查" + i);//把article对象转换成json格式的字符串。ObjectMapper objectMapper = new ObjectMapper();String jsonDocument = objectMapper.writeValueAsString(article);//使用client对象把文档写入索引库client.prepareIndex("hello_index","article", i + "").setSource(jsonDocument, XContentType.JSON).get();}//关闭客户端client.close();}
查询文档操作
抽取共用方法
构建共用方法,方便后续操作调用使用
public void search(QueryBuilder queryBuilder) {//执行查询得到SearchResponse searchResponse = client.prepareSearch("hello_index").setTypes("article").setQuery(queryBuilder).get();//处理结果SearchHits searchHits = searchResponse.getHits();System.out.println("总行数" + searchHits.getTotalHits());Iterator<SearchHit> it = searchHits.iterator();while (it.hasNext()){SearchHit searchHit = it.next();//打印迭代器里面 source-document的json输出System.out.println(searchHit.getSourceAsString());}}
termQuery
@Testpublic void testQueryTearm(){//构建quertBuilderQueryBuilder queryBuilder = QueryBuilders.termQuery("title","女护士");search(queryBuilder);}
testQueryByQueryString
//创建一个QueryBuilder对象//参数1:要搜索的字段//参数2:要搜索的关键词QueryBuilder queryBuilder = QueryBuilders.queryStringQuery("美丽的女护士").defaultField("title");search(queryBuilder);
testQueryByMatchQuery
@Testpublic void testQueryByMatchQuery() throws Exception {//创建一个QueryBuilder对象//参数1:要搜索的字段//参数2:要搜索的关键词QueryBuilder queryBuilder = QueryBuilders.matchQuery("title", "美丽的女护士");search(queryBuilder);}
使用文档ID查询文档
@Testpublic void testSearchById() throws Exception {//创建一个client对象//创建一个查询对象QueryBuilder queryBuilder = QueryBuilders.idsQuery().addIds("1", "2");search(queryBuilder);}
查询文档分页操作
@Testpublic void testQueryMatchAllQuery() throws Exception {//创建一个QueryBuilder对象QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();//执行查询//执行查询得到SearchResponse searchResponse = client.prepareSearch("hello_index").setTypes("article").setQuery(queryBuilder)//下标起始位置.setFrom(0)//一页条数.setSize(5).get();//处理结果SearchHits searchHits = searchResponse.getHits();System.out.println("总行数" + searchHits.getTotalHits());Iterator<SearchHit> it = searchHits.iterator();while (it.hasNext()){SearchHit searchHit = it.next();//打印迭代器里面 source-document的json输出System.out.println(searchHit.getSourceAsString());}}
查询结果高亮操作
代码实现
@Testpublic void highlightSearchTest() throws Exception {QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery("北京市民","title", "content");HighlightBuilder highlightBuilder = new HighlightBuilder();highlightBuilder.field("title").field("content");highlightBuilder.preTags("<em>");highlightBuilder.postTags("</em>");//执行查询SearchResponse searchResponse = client.prepareSearch("hello_index").setTypes("article").setQuery(queryBuilder)//设置高亮信息.highlighter(highlightBuilder).get();//取查询结果SearchHits searchHits = searchResponse.getHits();//取查询结果的总记录数System.out.println("查询结果总记录数:" + searchHits.getTotalHits());//查询结果列表Iterator<SearchHit> iterator = searchHits.iterator();while(iterator.hasNext()) {SearchHit searchHit = iterator.next();//取文档的属性System.out.println("-----------文档的属性");Map<String, Object> document = searchHit.getSource();System.out.println(document.get("title"));System.out.println(document.get("content"));System.out.println("************高亮结果");Map<String, HighlightField> highlightFields =searchHit.getHighlightFields();// //取title高亮显示的结果if (highlightFields.size() <=0) continue;for (Map.Entry<String, HighlightField> entry : highlightFields.entrySet()) {System.out.println(entry.getKey() + ":\t" + Arrays.toString(entry.getValue().getFragments()));}}//关闭clientclient.close();}
Spring Data ElasticSearch
简介
Spring Data ElasticSearch 基于 spring data API 简化 elasticSearch操作,将原始操作elasticSearch的客户端API 进行封装 。Spring Data为Elasticsearch项目提供集成搜索引擎。Spring Data ElasticsearchPOJO的关键功能区域为中心的模型与Elastichsearch交互文档和轻松地编写一个存储库数据访问层。
官方网站:http://projects.spring.io/spring-data-elasticsearch/
入门案例
- 导入依赖
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.16.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
- 配置启动器
@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class,args);}
}
- 配置yml文件
spring:data:elasticsearch:cluster-name: my-applicationcluster-nodes: 192.168.249.4:9300
- 编写实体类
@Document(indexName = "wx_blog", type = "article")
public class Article {@Id@Field(type = FieldType.Long, store = true)private long id;@Field(type = FieldType.Text, store = true, analyzer = "ik_smart")private String title;@Field(type = FieldType.Text, store = true, analyzer = "ik_smart")private String content;
}
- 编写Dao
方法命名规则查询的基本语法findBy + 属性 + 关键词 + 连接符
public interface ArticleRepository extends ElasticsearchRepository<Article,Long> {}
- 创建测试类
package com.study;import com.study.dao.ArticleRepository;
import com.study.entity.Article;
import org.elasticsearch.index.query.QueryBuilders;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runner.notification.RunListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.test.context.junit4.SpringRunner;import java.util.List;
import java.util.Optional;@RunWith(SpringRunner.class)
@SpringBootTest
public class ElaticSearchTest {@Autowiredprivate ArticleRepository articleRepository;@Autowiredprivate ElasticsearchTemplate elasticsearchTemplate;@Testpublic void createIndex(){elasticsearchTemplate.createIndex(Article.class);}@Testpublic void addDocument() throws Exception {for (int i = 10; i <= 20; i++) {//创建一个Article对象Article article = new Article();article.setId(i);article.setTitle("女护士路遇昏迷男子跪地抢救:救人是职责更是本能" + i);article.setContent("这是一个美丽的女护士妹妹" + i);//把文档写入索引库articleRepository.save(article);}}@Testpublic void deleteDocumentById() throws Exception {articleRepository.deleteById(1l);//全部删除
// articleRepository.deleteAll();}@Testpublic void findAll() throws Exception {Iterable<Article> articles = articleRepository.findAll();articles.forEach(a-> System.out.println(a));}@Testpublic void testFindById() throws Exception {Optional<Article> optional = articleRepository.findById(10l);Article article = optional.get();System.out.println(article);}@Testpublic void testFindByTitle() throws Exception {List<Article> list = articleRepository.findByTitle("女护士");list.stream().forEach(a-> System.out.println(a));}@Testpublic void testFindByTitleOrContent() throws Exception {Pageable pageable = PageRequest.of(1, 5);articleRepository.findByTitleOrContent("title", "女护士", pageable).forEach(a-> System.out.println(a));}@Testpublic void testNativeSearchQuery() throws Exception {//创建一个查询对象NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(QueryBuilders.queryStringQuery("女护士").defaultField("title")).withPageable(PageRequest.of(0, 15)).build();//执行查询List<Article> articleList = elasticsearchTemplate.queryForList(query, Article.class);articleList.forEach(a-> System.out.println(a));}
}
聚合查询
实体类
@Document(indexName = "car_index", type = "car")
public class Car {@Id@Field(type = FieldType.Long, store = true)private Long id;@Field(type = FieldType.Text, store = true, analyzer = "ik_smart")private String name;@Field(type = FieldType.Text, store = true, analyzer = "ik_smart", fielddata= true)private String color;@Field(type = FieldType.Text, store = true, analyzer = "ik_smart", fielddata= true)private String brand;@Field(type = FieldType.Double, store = true)private Double price;public Car(Long id, String name, String brand, String color, Double price) {this.id = id;this.name = name;this.color = color;this.brand = brand;this.price = price;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}public Double getPrice() {return price;}public void setPrice(Double price) {this.price = price;}
}
Dao
public interface CarDao extends ElasticsearchRepository<Car,Long> {
}
初始化索引库
@Autowiredprivate CarDao carDao;@Testpublic void initIndex() {carDao.save(new Car(1l, "比亚迪A1", "红色", "比亚迪", 50000d));carDao.save(new Car(2l, "比亚迪A2", "白色", "比亚迪", 70000d));carDao.save(new Car(3l, "比亚迪A3", "白色", "比亚迪", 80000d));carDao.save(new Car(4l, "比亚迪A4", "红色", "比亚迪", 60000d));carDao.save(new Car(5l, "比亚迪A5", "红色", "比亚迪", 90000d));carDao.save(new Car(6l, "宝马A1", "红色", "宝马", 10000d));carDao.save(new Car(7l, "宝马A2", "黑色", "宝马", 20000d));carDao.save(new Car(8l, "宝马A3", "黑色", "宝马", 30000d));carDao.save(new Car(9l, "宝马A4", "红色", "宝马", 40000d));carDao.save(new Car(10l, "宝马A5", "红色", "宝马", 50000d));carDao.save(new Car(11l, "奔驰A1", "红色", "奔驰", 10000d));carDao.save(new Car(12l, "奔驰A2", "黑色", "奔驰", 20000d));carDao.save(new Car(13l, "奔驰A3", "黑色", "奔驰", 30000d));carDao.save(new Car(14l, "奔驰A4", "红色", "奔驰", 40000d));carDao.save(new Car(15l, "奔驰A5", "红色", "奔驰", 50000d));
}
代码实现
划分桶
@Testpublic void testQuerySelfAggs(){//查询条件的构建器NativeSearchQueryBuilder queryBuilder = newNativeSearchQueryBuilder().withQuery(QueryBuilders.matchAllQuery());//排除所有的字段查询,queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{},null));//添加聚合条件queryBuilder.addAggregation(AggregationBuilders.terms("group_by_color").field("color"));//执行查询,把查询结果直接转为聚合pageAggregatedPage<Car> aggPage = (AggregatedPage<Car>)carDao.search(queryBuilder.build());//从所有的聚合中获取对应名称的聚合StringTerms agg = (StringTerms) aggPage.getAggregation("group_by_color");//从聚合的结果中获取所有的桶信息List<StringTerms.Bucket> buckets = agg.getBuckets();for (StringTerms.Bucket bucket : buckets) {String brand = bucket.getKeyAsString();long docCount = bucket.getDocCount();System.out.println("color = " + brand+" 总数:"+docCount);}}
桶内度量
@Testpublic void testQuerySelfSubAggs(){//查询条件的构建器NativeSearchQueryBuilder queryBuilder = newNativeSearchQueryBuilder().withQuery(QueryBuilders.matchAllQuery());//排除所有的字段查询,queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{},null));//添加聚合条件queryBuilder.addAggregation(AggregationBuilders.terms("group_by_color").field("color").subAggregation(AggregationBuilders.avg("avg_price").field("price")));//执行查询,把查询结果直接转为聚合pageAggregatedPage<Car> aggPage = (AggregatedPage<Car>)carDao.search(queryBuilder.build());//从所有的聚合中获取对应名称的聚合StringTerms agg = (StringTerms) aggPage.getAggregation("group_by_color");//从聚合的结果中获取所有的桶信息List<StringTerms.Bucket> buckets = agg.getBuckets();
for (StringTerms.Bucket bucket : buckets) {String brand = bucket.getKeyAsString();long docCount = bucket.getDocCount();//取得内部聚合InternalAvg avg = (InternalAvg)bucket.getAggregations().asMap().get("avg_price");System.out.println("brand = " + brand+" 总数:"+docCount+" 平均价格:"+avg.getValue());}
}
ElasticSearch全文详解及具体配置相关推荐
- ElasticSearch搜索引擎详解-持续更新中
ElasticSearch搜索引擎详解 1. ElasticSearch概述 1.1 elasticsearch是什么 1.2 全文搜索引擎 1.3 elasticsearch and solr 1. ...
- Git客户端图文详解如何安装配置GitHub操作流程攻略
Git客户端图文详解如何安装配置GitHub操作流程攻略 软件应用 爱分享 3个月前 (08-15) 8896浏览 0评论 Git介绍 分布式 : Git版本控制系统是一个分布式的系统, 是用来 ...
- ActiveMQ配置详解之如何配置自动重新连接
2019独角兽企业重金招聘Python工程师标准>>> ActiveMQ配置详解之如何配置自动重新连接 博客分类: MQ 这从这一篇开始,将讲解在activeMQ中的相关配置.由于a ...
- vue.js2.0 java_详解vite2.0配置学习(typescript版本)
介绍 尤于溪的原话. vite与 Vue CLI 类似,vite 也是一个提供基本项目脚手架和开发服务器的构建工具. vite基于浏览器原生ES imports的开发服务器.跳过打包这个概念,服务端按 ...
- 今日头条推荐算法原理全文详解之一
本次分享将主要介绍今日头条推荐系统概览以及内容分析.用户标签.评估分析,内容安全等原理. 今日头条推荐算法原理全文详解 今日头条 数据分析 产品经理 产品 好文分享 第1张 一.系统概览 推荐系统,如 ...
- 抖音推荐算法原理全文详解
阅读目录 一.系统概览 二.内容分析 三.用户标签 四.评估分析 五.内容安全 抖音推荐算法原理全文详解 本次分享将主要介绍今日头条推荐系统概览以及内容分析.用户标签.评估分析,内容安全等原理. 回到 ...
- K8SPod详解之pod配置
K8SPod详解之pod配置 Pod定义 Pod配置 pod.spec.containers 基本配置 镜像拉取 启动命令 环境变量 端口设置 资源配额 每个pod中都可以包含一个或者多个容器,这些容 ...
- 今日头条推荐算法原理全文详解之四
三.用户标签 内容分析和用户标签是推荐系统的两大基石.内容分析涉及到机器学习的内容多一些,相比而言,用户标签工程挑战更大. 今日头条推荐算法原理全文详解 今日头条 数据分析 产品经理 产品 好文分享 ...
- 单臂路由的详解及简单配置
单臂路由的详解及简单配置 前言 1.什么是单臂路由 2.什么是逻辑子接口 3.单臂路由的配置 4.单臂路由的优缺点 1.什么是单臂路由 单臂路由(router-on-a-stick)是指在路由器的一个 ...
最新文章
- android异常 More than one file was found with OS independent path ‘META-INF/XXX‘
- C++从0到1的入门级教学(二)——数据类型
- fiddler怎么修改服务器返回数据,基于Fiddler实现修改接口返回数据进行测试
- mysql source导入_读取MySQL数据库中的数据【Python数据分析百例连载】
- GAN诞生记:最火的AI模型,来自一群博士的酒后争吵
- Java跳出多重循环的方法
- PyTorch搭建LeNet-5模型(在MNIST数据集上准确率接近100%)
- 考研408院校合集以及学科评估
- 通过top查看程序cpu使用率为什么会超过100%
- ffmpeg4.x支持的编解码器等相关信息一览表
- 腾讯优图实现人脸对比
- 网站被反诈中心DNS劫持解决教程
- 白杨SEO:什么是产品运营?产品运营要求有哪些?SEO如何转行产品运营?
- MFC之图像绘制---高速绘图控件(High-speed Charting Control)应用(一)
- C语言用递归调用实现阶乘
- 奥比中光astra 摄像头采集深度图和RGB图像(小白版)
- 机器学习与深度学习一些基础知识点
- 大厂的职级晋升答辩是什么 · 职级晋升系列
- 无头浏览器(Headless Chrome)的使用
- 微信美食菜谱小程序系统毕业设计毕设(1)开发概要
热门文章
- 谷歌地球Google Earth Pro 7.3.3.7721 mac中文版
- 线性回归和贝叶斯的线性回归
- php热图,科学网—使用ComplexHeatmap包绘制个性化热图 - 刘永鑫的博文
- “保姆级”车载LIN总线教程(三)-堪称全网“最细”系列
- MPC5748G开发笔记-----S32DS提示The target may have entered reset escalation
- Pixhawk系统架构介绍
- 名人名言 托尔斯泰 富兰克林 马克思 罗兰 培根
- java用星星符号打印出一个直角三角形
- 为什么我推荐你一定要学Python?
- 那些你可能用得上的在线办公神器系列(三)