一、创建映射字段的语法格式
需要先构建索引库,在构建索引库中的映射关系
PUT /索引库名/_mapping
{
"properties": {
"字段名": {
"type": "类型",
"index": true,
"store": false,
"analyzer": "分词器"
}
}
}
-
类型名称:映射的名称,字段名:任意填写。Elasticsearch7.0之后不支持类名名称写法所以需要添加include_type_name=true参数进行支持设置。
-
type:类型,可以是text、long、short、date、integer、object等
-
index:是否可以使用索引查询,默认为true
-
store:是否额外存储,默认为false
-
analyzer:分词器,这里的
ik_max_word
即使用ik分词器
二、了解数据类型
1、字符串
text: 可分词 不可聚合
keyword:不可分词 可聚合
2、数值
整数和浮点(float、double、half_float、scaled_float)
3、日期
date
三、使用springboot创建es项目
1、jar包
spring-boot-starter-data-elasticsearch
2、配置文件
spring:
elasticsearch:
uris: http://1.94.230.82:9200
3、使用esTemplate模版工具类
@RestController
@RequestMapping("/es")
public class EsController {
@Autowired
private ElasticsearchRestTemplate restTemplate;
四、Es实现的功能
1、创建索引库
restTemplate.indexOps(User.class).create();
/*
@Document(indexName = "索引库名",shards = 分片数,replicas = 副本数)
*/
@Document(indexName = "user",shards = 1,replicas = 0)
public class User {
}
package com.hl.es.web;
import com.hl.es.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/es")
public class EsController {
@Autowired
private ElasticsearchRestTemplate restTemplate;
@RequestMapping("/test")
public void getEsTemplate(){
boolean flag = restTemplate.indexOps(User.class).exists();
System.out.println("索引库是否存在:"+flag);
if(!flag){
//创建索引库
boolean flag2 = restTemplate.indexOps(User.class).create();
System.out.println("索引库创建结果:"+flag2);
}
}
}
2、创建映射
@Document(indexName = "user",shards = 1,replicas = 0)
@Data
public class User {
@Id
private Integer id;
@Field(type = FieldType.Text,analyzer = "ik_max_word")
private String username;
@Field(type = FieldType.Text,analyzer = "ik_max_word")
private String desc;
@Field(type = FieldType.Keyword,index = false)
private String password;
@Field(type = FieldType.Text,analyzer = "ik_max_word")
private String address;
@Field(type = FieldType.Double)
private Double money;
@Field(type = FieldType.Date,format = DateFormat.custom,pattern = "YYYY-MM-dd")
private Date createTime;
}
@RequestMapping("/createMapping")
public Object createMapping(){
Document document = restTemplate.indexOps(User.class).createMapping();
boolean flag = restTemplate.indexOps(User.class).putMapping(document);
System.out.println("创建映射:"+flag);
return flag;
}
3、新增数据
@RequestMapping("/save")
public Object save(User user){
User user2 = restTemplate.save(user);
return user2;
}
4、查询数据
自定义查询
package com.hl.es.dao;
import com.hl.es.pojo.User;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.List;
public interface UserDao
extends ElasticsearchRepository<User, Integer> {
//根据用户名查询集合
//单字段
public List<User> findByUsername(String username);
public List<User> findByAddress(String address);
//多字段
public List<User> findByDescAndAddress(String desc, String address);
public List<User> findByDescOrAddress(String desc, String address);
//范围查询
public List<User> findAllByIdGreaterThanEqual(Integer minId);
public List<User> findByMoneyBetween(Double minPrice, Double maxPrice);
//先根据范围查询,再降序排序
public List<User> findByMoneyBetweenOrderByMoneyDesc(Double minPrice, Double maxPrice);
}
高级查询
1、分页查询
/**
* 高级查询-分页查询
*/
//高级查询-分页查询
@RequestMapping("/pageQuery")
public List<Goods> matchPageQuery(){
//构建queryBuilder
NativeSearchQueryBuilder searchQueryBuilder = new
NativeSearchQueryBuilder();
//设置基础的查询条件
searchQueryBuilder.withQuery(QueryBuilders.termQuery("category","手
机"));
//设置分页
int page = 0; //查询的当前页 0表示第一页数据
int size = 3; //每页显示条数
searchQueryBuilder.withPageable(PageRequest.of(page,size));
Page<Goods> search =
esRepository.search(searchQueryBuilder.build());
//总条数
System.out.println(search.getTotalElements());
//总页数
System.out.println(search.getTotalPages());
//每页显示条数
System.out.println(search.getSize());
//当前页
System.out.println(search.getNumber());
//获取分页数据
List<Goods> content = search.getContent();
return content;
}
2、聚合查询
/**
* 高级查询-聚合查询
*/
@RequestMapping("/matchQueryAgg")
public void matchQueryAgg() {
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 不查询任何结果
queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""},
null));
// 1、添加一个新的聚合,聚合类型为terms,聚合名称为brands,聚合字段为brand
queryBuilder.addAggregation(
AggregationBuilders.terms("images").field("image"));
// 2、查询,需要把结果强转为AggregatedPage类型
AggregatedPage<Goods> aggPage = (AggregatedPage<Goods>)
goodsRepository.search(queryBuilder.build());
// 3、解析
// 3.1、从结果中取出名为pimgs的那个聚合,
Terms agg = (Terms) aggPage.getAggregation("images");
// 3.2、获取桶
List<StringTerms.Bucket> buckets = (List<StringTerms.Bucket>)
agg.getBuckets();
// 3.3、遍历
for (Terms.Bucket bucket : buckets) {
// 3.4、获取桶中的key,即图片
System.out.println(bucket.getKeyAsString());
// 3.5、获取桶中的文档数量
System.out.println(bucket.getDocCount());
}
}
3、高亮查询
//创建elasticsearch操作类
public interface GoodsRepository extends
ElasticsearchRepository<Goods,Long> {
//高亮处理
@Highlight(
fields = {@HighlightField(name = "title"),@HighlightField(name
= "brand")},
parameters = @HighlightParameters(preTags = {"<span
style='color:red'>"},postTags = {"</span>"})
)
public List<SearchHit<Goods>> findByTitleOrBrand(String title,String
brand);
}
//高亮查询
@RequestMapping("/findByTitleOrBrand")
public List<Goods> findByTitleOrBrand(){
//根据标题和品牌获取高亮数据,分为两部分:1.普通数据{id:1,title:小米手
机} 2.高亮的部分 title:小米<span style='color:red'>手机</span>
List<SearchHit<Goods>> list =
goodsRepository.findByTitleOrBrand("手机", "手机");
List<Goods> newList = new ArrayList<>();
for (SearchHit searchHit:list) {
//获取普通数据
Goods goods = (Goods) searchHit.getContent();
//获取高亮的数据
/*{
title:[
"小米<span style='color:red'>手机</span>"
],
brand:[
"小米<span style='color:red'>手机</span>"
]
}
*/
Map<String,List<String>> highlightFields =
searchHit.getHighlightFields();
//获取title的高亮数据
List<String> titles = highlightFields.get("title");
if (titles != null){
goods.setTitle(titles.get(0));
}
List<String> brands = highlightFields.get("brand");
2.elasticsearch集群
2.1.搭建集群
Elasticsearch如果做集群的话节点至少三台服务器或者三个实例加入相同集群,三个节点最多只
能故障一台节点,如果故障两个节点,Elasticsearch将无法组成集群.会报错,Kibana也无法启
动,因为Kibana无法获取集群中的节点信息。
由于,我们使用只有一台虚拟机,所以我们在虚拟机中安装三个ES实例,搭建伪集群。
2.1.1.拷贝副本
修改elasticsearch的JVM占用内存参数,防止内存不足错误
默认情况下,ES启动JVM最小内存1G,最大内存1G
将opt目录下的elasticsearch安装目录拷贝3个
2.1.2. 修改elasticsearch.yml配置文件
创建日志目录
if (brands != null){
goods.setBrand(brands.get(0));
}
//把处理好的数据存储到list中
newList.add(goods);
}
return newList;
}
五、es专业名词
节点
分片
副本
索引
六、mysq+es的数据同步
-
使用RabbitMQ实现Mysql与ElasticSearch实时同步。
当前项目
主数据库: mysql 事务机制
辅助数据库:redis (小数据量的频繁访问 内存 首页商品分类 推荐商品)
es(大量数据的检索 模糊查询 | 数据来自于多个字段 百度搜索 商城的搜索)
mysql:商品表
redis:查询mysql中的数据,新增到redis
mysql------------------》es
方法(saveToMysql -->mq--> saveToEs )(updateToMysql -->mq--->updateToEs ) (deleteToMysql deleteToEs)
项目上线:首次同步,批量同步
项目运行:增量同步