elasticsearch使用原理-阿里云开发者社区

开发者社区> 阿里云GTS能力中心-浩鲸智能> 正文
登录阅读全文

elasticsearch使用原理

简介: Elasticsearch也是基于Lucene的全文检索库,本质也是存储数据,很多概念与MySQL类似的。 对比关系: 索引库(indices)--------------------------------Databases 数据库 类型(type)--------------------------------Table 数据表 文档(Document)-----------------------Row 行 字段(Field)-----------------------Columns 列

与Lucene和solr中的概念类似。
另外,在SolrCloud中,有一些集群相关的概念,在Elasticsearch也有类似的:

  • 索引集(Indices,index的复数):逻辑上的完整索引
  • 分片(shard):数据拆分后的各个部分
  • 副本(replica):每个分片的复制

要注意的是:Elasticsearch本身就是分布式的,因此即便你只有一个节点,Elasticsearch默认也会对你的数据进行分片和副本操作,当你向集群添加新数据时,数据也会在新加入的节点中进行平衡。

一、创建索引
Elasticsearch采用Rest风格API,因此其API就是一次http请求,你可以用任何工具发起http请求
创建索引的请求格式:

  • 请求方式:PUT
  • 请求路径:/索引库名

{

"settings": {
    "number_of_shards": 3,
    "number_of_replicas": 2
  }

}

查看索引设置:
Get请求可以帮我们查看索引信息,格式:
GET /索引库名

二、删除索引
删除索引使用DELETE请求
DELETE /索引库名

三、映射配置
索引库有了,接下来肯定是添加数据。不过数据存储到索引库中,必须指定一些相关属性,在学习Lucene中我们都见到过,包括但不限于以下内容:
字段的数据类型
是否要存储
是否要索引
是否分词
分词器种类
只有配置清楚,Elasticsearch才会帮我们进行索引库的创建(不一定)
1.创建映射字段
PUT /索引库名/_mapping/类型名称
{
"properties": {

"字段名": {
  "type": "类型",
  "index": true,
  "store": true,
  "analyzer": "分词器"
}

}
}
类型名称:就是前面讲的type的概念,类似于数据库中的不同表
字段名:任意填写 ,可以指定许多属性,例如:
type:类型,可以是text、long、short、date、integer、object等
index:是否索引,默认为true
store:是否存储,默认为false
analyzer:分词器,这里的ik_max_word即使用ik分词器
2.查看映射关系
GET /索引库名/_mapping
3.字段属性详解
说几个关键的:
String类型,又分两种:text:可分词,不可参与聚合 keyword:不可分词,数据会作为完整字段进行匹配,可以参与聚合
Numerical:数值类型,分两类:基本数据类型:long、interger、short、byte、double、float、half_float
浮点数的高精度类型:scaled_float 需要指定一个精度因子,比如10或100。elasticsearch会把真实值乘以这个因子后存储,取出时再还原。
Date:日期类型。elasticsearch可以对日期格式化为字符串存储,但是建议我们存储为毫秒值,存储为long,节省空间。
index影响字段的索引情况。index的默认值就是true,也就是说你不进行任何配置,所有字段都会被索引。
boost:激励因子,这个与lucene中一样
4.新增数据
通过POST请求,可以向一个已经存在的索引库中添加数据。
POST /索引库名/类型名
{

"key":"value"

}
5.修改数据
把刚才新增的请求方式改为PUT,就是修改了。不过修改必须指定id

二:查询
我们从4块来讲查询:

  • 基本查询
  • _source过滤
  • 结果过滤
  • 高级查询
  • 排序

1.基本查询
GET /索引库名/_search
{

"query":{
    "查询类型":{
        "查询条件":"查询条件值"
    }
}

}
2、多字段查询(multi_match)
GET /_search
{

"query":{
    "multi_match": {
        "query":    "小米",
        "fields":   [ "title", "subTitle" ]
    }
}

}
3.词条匹配(term)
GET /_search
{

"query":{
    "term":{
        "price":
    }
}

}

4.多词条精确匹配
GET /_search
{

"query":{
    "terms":{
        "price":[2699.00,2899.00,3899.00]
    }
}

}

三、聚合
image.png
基本概念
image.png
image.png
聚合为桶
image.png
桶内度量
image.png
GET /cars/_search
{

"size" : 0,
"aggs" : { 
    "popular_colors" : { 
        "terms" : { 
          "field" : "color"
        },
        "aggs":{
            "avg_price": { 
               "avg": {
                  "field": "price" 
               }
            }
        }
    }
}

}

五、Spring Data Elasticsearch
image.png
Spring Data 是的使命是给各种数据访问提供统一的编程接口,不管是关系型数据库(如MySQL),还是非关系数据库(如Redis),或者类似Elasticsearch这样的索引数据库。从而简化开发人员的代码,提高开发效率。
image.png
image.png
示例:
@Document(indexName = "item",type = "docs", shards = 1, replicas = 0)
public class Item {

@Id
private Long id;

@Field(type = FieldType.Text, analyzer = "ik_max_word")
private String title; //标题

@Field(type = FieldType.Keyword)
private String category;// 分类

@Field(type = FieldType.Keyword)
private String brand; // 品牌

@Field(type = FieldType.Double)
private Double price; // 价格

@Field(index = false, type = FieldType.Keyword)
private String images; // 图片地址

}
image.png
image.png
删除索引:
image.png
自定义查询:
image.png
分页查询:
@Test
public void searchByPage(){

// 构建查询条件
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 添加基本分词查询
queryBuilder.withQuery(QueryBuilders.termQuery("category", "手机"));
// 分页:
int page = 0;
int size = 2;
queryBuilder.withPageable(PageRequest.of(page,size));

// 搜索,获取结果
Page<Item> items = this.itemRepository.search(queryBuilder.build());
// 总条数
long total = items.getTotalElements();
System.out.println("总条数 = " + total);
// 总页数
System.out.println("总页数 = " + items.getTotalPages());
// 当前页
System.out.println("当前页:" + items.getNumber());
// 每页大小
System.out.println("每页大小:" + items.getSize());

for (Item item : items) {
    System.out.println(item);
}

}

排序:
排序也通用通过NativeSearchQueryBuilder完成:
@Test
public void searchAndSort(){

// 构建查询条件
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 添加基本分词查询
queryBuilder.withQuery(QueryBuilders.termQuery("category", "手机"));

// 排序
queryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.ASC));

// 搜索,获取结果
Page<Item> items = this.itemRepository.search(queryBuilder.build());
// 总条数
long total = items.getTotalElements();
System.out.println("总条数 = " + total);

for (Item item : items) {
    System.out.println(item);
}

}

聚合:
@Test
public void testAgg(){

NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 不查询任何结果
queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));
// 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brand
queryBuilder.addAggregation(
    AggregationBuilders.terms("brands").field("brand"));
// 2、查询,需要把结果强转为AggregatedPage类型
AggregatedPage<Item> aggPage = (AggregatedPage<Item>) this.itemRepository.search(queryBuilder.build());
// 3、解析
// 3.1、从结果中取出名为brands的那个聚合,
// 因为是利用String类型字段来进行的term聚合,所以结果要强转为StringTerm类型
StringTerms agg = (StringTerms) aggPage.getAggregation("brands");
// 3.2、获取桶
List<StringTerms.Bucket> buckets = agg.getBuckets();
// 3.3、遍历
for (StringTerms.Bucket bucket : buckets) {
    // 3.4、获取桶中的key,即品牌名称
    System.out.println(bucket.getKeyAsString());
    // 3.5、获取桶中的文档数量
    System.out.println(bucket.getDocCount());
}

}

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:

阿里云GTS能力中心(浩鲸智能),从交付的视角探讨数字化转型过程中大型软件开发实践、以及阿里云产品在各行业被集成的案例分享、技术沉淀等内容。敬请关注!

官方博客
官网链接