Elasticsearch搜索引擎一些参数含义和用法

目录

Elasticsearch

实体类

序列化

@Document

indexName:

type:

shards:

replicas:

indexStoreType

refreshInterval

@Id

@Field

@GeoPointField Elasticsearch 地理坐标类型 (Geo-point)

geo_point

@GeoPointField 地理坐标类型用法

以某坐标点为中心搜索指定范围的其它点

GeoDistance计算两个给定坐标点之间的距离

Geo Distance地理距离过滤器

按距点的距离进行排序:

Faster Geo-Distance Calculations更快的地理距离计算

geo_distance_range过滤器:1km内-2km外

keyword和text的区别


Elasticsearch

Elasticsearch是一个开源的分布式、RESTful 风格的搜索和数据分析引擎,它的底层是开源库Apache Lucene。它使用 Java 编写,内部采用 Lucene 做索引与搜索

经过一段时间对ES的研究与实践应用,使用虽然没什么问题了,但对一些参数还是不求甚解,再了解学习下。

实体类

  

@Document(indexName = "elastic_search_user", type = "user", shards = 5, replicas = 1)
public class User implements Serializable {

    @Id
    private String id;
}

序列化

  • 用elasticsearch存储Document类型的实体类时,实体类需要实现Serializable接口,并为实体类生成序列号,否则查询结果很可能会得到unKNown instance
  • 其实无论我们是把数据存入到关系型数据库还是非关系型数据库,我们都需要对存入数据进行序列化,因为在异地传输,存储时序列化可以保证我们的传输以及之后我们能原样的读取数据,那么由于在关系型数据库,比如MySQL中,我们其实存储的数实体类的字段属性,多为String,int等类型,这些类型数据库都有对应的数据结构支持,而且这些类型在声明是以及实现了Serializable接口的,所以我们才不用手动实现该接口,但是像ES这种非关系型数据库(NoSQL),其实存入的是整个实体类对象,NoSQL并没有支持他们的数据结构,所以为了保证我们能够正确读取数据,我们就需要实体类实现Serializable接口,并为实体类生成序列号。
  • 其实java中的Serializable接口并没有定义任何东西,是一个空的接口,具体的序列化操作还是需要交给JVM来做。
  • 再一个类序列化之后的序列化id的作用,是在反序列化的时候,如果系统检测到反序列化文件的id与当前类的序列化id不同,那么反序列化就会失败,他能保证我们反序列化得到完全一样的结果

Spring Data通过注解来声明字段的映射属性,有下面的三个注解:

@Document

作用在类,标记实体类为文档对象

indexName:

对应索引库名称,是一个逻辑命名空间相当于数据库名 必须为小写

type:

对应在索引库中的类型

shards:

分片数量,默认5默认情况下,Elasticsearch为每个索引创建一个主分片和一个副本。这意味着每个索引将包含一个主分片,每个分片将具有一个副本。Elasticsearch自动管理这些分片的排列,用户无需担心细节。

  • 允许你水平分割/扩展你的内容容量
  • 允许你在分片(潜在地,位于多个节点上)之上进行分布式的、并行的操作,进而提高性能/吞吐量
  • 有两种类型的分片:primary shard和replica shard
    • Primary shard: 每个文档都存储在一个Primary shard。
    • Replica shard: 每个主分片可以具有零个或多个副本。
      - 增加故障转移:如果主要故障,可以将副本分片提升为主分片
      - 提高性能:get和search请求可以由主shard或副本shard处理。

replicas:

副本数量,默认1分配多个分片和副本是分布式搜索功能设计的本质,提供高可用性和快速访问索引中的文档。主副本和副本分片之间的主要区别在于只有主分片可以接受索引请求。副本和主分片都可以提供查询请求。number_of_shards值与索引有关,而不是与整个群集有关。此值指定每个索引的分片数(不是群集中的主分片总数)。

indexStoreType

文件存储类型,index.store.type可以在节点的elasticsearch.yml里设置,也可以在索引的setting里设置,但只有索引创建时才可以。

可选的存储类型有:

  • fs  :默认实现,取决于操作系统
  • simplefs  :对应Lucene SimpleFsDirectory
  • niofs  :对应Lucene NIOFSDirectory
  • mmapfs  :对应Lucene MMapDirectory

改变这种设置,通过在config/elasticsearch.yml中添加如下配置,例如:

index.store.type: niofs

也可以在索引创建的时候针对某一个特定的索引进行设置

  

refreshInterval

index.refresh_interval  :多久执行一次刷新操作,使得最近的索引更改对搜索可见。默认是1秒。设置为-1表示禁止刷新。

@Id

作用在成员变量,标记一个字段作为id主键

@Field

作用在成员变量,标记为文档的字段,并指定字段映射属性:

  • type:字段类型,是枚举:FieldType,可以是text、long、short、date、integer、object等
  • text:存储数据时候,会自动分词,并生成索引
  • keyword:存储数据时候,不会分词建立索引
  • Numerical:数值类型,分两类
    • 基本数据类型:long、interger、short、byte、double、float
    • half_float 浮点数的高精度类型:scaled_float 需要指定一个精度因子,比如10或100。  elasticsearch会把真实值乘以这个因子后存储,取出时再还原。
  • Date:日期类型 elasticsearch可以对日期格式化为字符串存储,但是建议我们存储为毫秒值,存储为long,节省空间。
  • index:是否索引,布尔类型,默认是true
  • store:是否存储,布尔类型,默认是false 
  • analyzer:分词器名称,这里的ik_max_word即使用ik分词器
  • Auto:自动加载

@GeoPointField Elasticsearch 地理坐标类型 (Geo-point)

geo_point

GeoPoint应该使用org.springframework.data.elasticsearch.core.geo

    /**
     * 地理位置经纬度
     * lat纬度,lon经度 "40.715,-74.011"
     * 如果用数组则相反[-73.983, 40.719]
     */
    @GeoPointField
    private String address;

    /**
     * 坐标位置
     */
    @GeoPointField
    private GeoPoint location;

 数据:

  

结构:

  

  

@GeoPointField 地理坐标类型用法

以某坐标点为中心搜索指定范围的其它点

文档https://www.elastic.co/guide/en/elasticsearch/guide/current/geo-distance.html

通过继承ElasticsearchRepository<T, ID extends Serializable>来简化完成相关查询

public interface TestRepository extends ElasticsearchRepository<User, String> {
}
    @Resource
    private TestRepository testRepository;
	
    public Page<Test> findPage(double latitude, double longitude, String distance, Pageable pageable) {
		// 间接实现了QueryBuilder接口
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

        // 以某点为中心,搜索指定范围
        GeoDistanceQueryBuilder distanceQueryBuilder = new GeoDistanceQueryBuilder("location");
        distanceQueryBuilder.point(latitude, longitude);
		// 定义查询单位:公里
        distanceQueryBuilder.distance(distance, DistanceUnit.KILOMETERS);
        boolQueryBuilder.filter(distanceQueryBuilder);

        return testRepository.search(boolQueryBuilder, pageable);
    }

GeoDistance计算两个给定坐标点之间的距离

	// 计算两点距离
	double distance = GeoDistance.ARC.calculate(srcLat, srcLon, dstLat, dstLon, DistanceUnit.KILOMETERS);

Geo Distance地理距离过滤器

geo_distance过滤器周围绘制指定的位置了一圈,发现有一个圆圈内的地理点的所有文件:

{
  "query": {
    "filtered": {
      "filter": {
        "geo_distance": {
          "distance": "1km", 
          "location": { 
            "lat":  40.715,
            "lon": -73.988
          }
        }
      }
    }
  }
}

查找指定点location内1km的所有字段。有关可接受单位的列表:

  • 英里Mile:     mi 要么 miles
  • Yard:        yd 要么 yards
  • Feet:        ft 要么 feet
  • 英寸Inch:     in 要么 inch
  • 公里Kilometer:       km 要么 kilometers
  • 仪表Meter:   m 要么 meters
  • 厘米Centimeter:     cm 要么 centimeters
  • 毫米Millimeter:       mm 要么 millimeters
  • 海里Nautical mile:  NM,nmi或nauticalmiles  

中心点可以指定为字符串,数组或对象(如本例所示)。纬度/经度格式:

  • 字符串表示形式,带有"lat,lon"。“ location” :“ 40.715,-74.011”
  • 具有lat并lon明确命名的对象表示。 “ lat” :40.722 ,“ lon” :- 73.989
  • 数组表示形式[lon,lat]。“位置” :[ - 73.983 ,40.719 ]

按距点的距离进行排序:

GET / 景点/ 餐厅/ _search
{
  "query": {
    "filtered": {
      "filter": {
        "geo_bounding_box": {
          "type":       "indexed",
          "location": {
            "top_left": {
              "lat":  40.8,
              "lon": -74.0
            },
            "bottom_right": {
              "lat":  40.4,
              "lon": -73.0
            }
          }
        }
      }
    }
  },
  "sort": [
    {
      "_geo_distance": {
        "location": { 
          "lat":  40.715,
          "lon": -73.998
        },
        "order":         "asc",
        "unit":          "km", 
        "distance_type": "plane" 
      }
    }
  ]
}
  • location:计算每个文档字段中指定lat/lon点与地理位置之间的距离location
  • unit:返回的距离kmsort每个结果键
  • distance_type:使用更快但不太准确的plane计算

Faster Geo-Distance Calculations更快的地理距离计算

GeoDistance.ARCGeoDistance.PLANE,前者比后者计算起来要慢,但精确度要比后者高

  • arc:最慢但最准确的是arc计算,它将世界视为一个球体。精度仍然受到限制,因为世界并不是真正的球体。
  • plane:plane将世界视为平坦世界 的计算速度更快,但准确性较低。它在赤道处最精确,而在极点处变得不那么精确。
  • sloppy_arc:之所以这么称呼,是因为它使用SloppyMathLucene类来交换速度的准确性,因此sloppy_arc计算使用 Haversine公式来计算距离。它的速度是的四到五倍arc,距离的准确度为99.9%。这是默认计算。

 使用更快但不太准确的plane计算:

GET / 景点/ 餐馆/ _search
{
  "query": {
    "filtered": {
      "filter": {
        "geo_distance": {
          "distance":      "1km",
          "distance_type": "plane", 
          "location": {
            "lat":  40.715,
            "lon": -73.988
          }
        }
      }
    }
  }
}

geo_distance_range过滤器:1km内-2km外

geo_distancegeo_distance_range 过滤器之间的唯一区别是,过滤器具有甜甜圈形状,并且排除了中心孔内的文档。

distance您可以指定最小距离(使用gtgte)和最大距离(使用lt或 lte),而不是从中心指定一个,就像range过滤器一样:

GET / 景点/ 餐厅/ _search
{
  "query": {
    "filtered": {
      "filter": {
        "geo_distance_range": {
          "gte":    "1km", 
          "lt":     "2km", 
          "location": {
            "lat":  40.715,
            "lon": -73.988
          }
        }
      }
    }
  }
}
匹配至少1km从中心到小于 2km中心的位置

除了主键其他成员变量上的注解例如:

@Field(type = FieldType.Keyword)

可省略,默认创建为text类型

特殊处理的字段还是建议加上,如@GeoPointField

keyword和text的区别

20-07-07 14.03增加

 按照官方文档的阐述,text类型的数据被用来索引长文本,例如电子邮件主体部分或者一款产品的介绍,这些文本会被分析,在建立索引文档之前会被分词器进行分词,转化为词组。经过分词机制之后es允许检索到该文本切分而成的词语,但是text类型的数据不能用来过滤、排序和聚合等操作。

    keyword类型的数据可以满足电子邮箱地址、主机名、状态码、邮政编码和标签等数据的要求,不进行分词,常常被用来过滤、排序和聚合。

    综上,可以发现text类型在存储数据的时候会默认进行分词,并生成索引。而keyword存储数据的时候,不会分词建立索引,显然,这样划分数据更加节省内存。

PUT /zk_test/info/_mapping
{
  "info":{
    "properties":{
      "address":{"type":"text","analyzer":"standard"}
    }
  }
}

analyzer 还有中文分词 chinese,英文分词 english 等参数

已创建索引实体类字段增加问题

20-07-07 14.29增加

如ES里字段增加实体类增加字段后,执行插入操作会自动创建,不需要重新创建索引

如增加字段时不使用@Field指定类型 int -> long,String -> text,所以提前执行好

如ES里字段已增加,再进行变更修改类型@Field(type = FieldType.Keyword)需要删除再创建索引,不然会报错 

ElasticsearchRepository和ElasticsearchTemplate的选择

20-07-07 14.29增加

混合使用更方便,一个进行简单的增删改查,一个进行复杂查询

  • 7
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瑶山

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值