分布式电商项目 谷粒商城 学习笔记<2>
文章目录
- 六、三级分类
- 1.按照父子类的结构获取所有分类
- 2.跨域问题的解决
- 1、使用nginx部署为同一域
- 2、让服务器告诉预检请求能跨域
- 3.过滤器优先级问题
- 4.删除
- 5.增加修改拖拽
- 七、品牌管理
- 1.阿里云上传
- 2.代码上传品牌图片
- 3.JSR303校验
- @Valid内置异常
- 统一异常处理
- 八、商品SPU和SKU管理
- 1.概念
- 2.三级分类表和属性表
- 3.分页插件
- 4.模糊查询
- 5.冗余字段保持一致
- 6.PO VO DTO POJO
- 九、规格参数新增与VO
- 1.新建VO
- 2.查询涉及到多个表
- 3.采购
- 十、ES
- 1.基本概念
- 2.安装
- 3.配置
- 4.基本命令
- 新增/修改
- 查询
- 删除
- 5.批量操作
- 6.进阶--检索
- 首先是检查一下虚拟机状态
- DSL领域特定语言
- query/match匹配查询
- query/match_phrase [不拆分匹配]
- 字段.keyword:必须全匹配上才检索成功
- query/multi_math【多字段匹配】
- query/bool/must复合查询
- query/filter【结果过滤】
- query/term
六、三级分类
1.按照父子类的结构获取所有分类
所有的分类都是一样的表,依靠表的级别和父标签来区分子父表。
要想一次性按父子结构打印出所有的分类,那么分类这个类中必须还得有子类,这个类要存在于entity中,但不能存在于数据库。代码如下:
@TableField(exist = false)
private List<CategoryEntity> children;
@Override
public List<CategoryEntity> listWithTree(){//1、查出所有分类 null表名没有查找的条件 即全部查出List<CategoryEntity> entities = baseMapper.selectList(null);//2、组装成父子的树形结构//2.1 找到所有的一级分类List<CategoryEntity> level1Menus = entities.stream().filter(categoryEntity ->categoryEntity.getParentCid()==0).map((menu)->{menu.setChildren(getChildrens(menu,entities));return menu;}).collect(Collectors.toList());return level1Menus;
}private List<CategoryEntity> getChildrens(CategoryEntity root,List<CategoryEntity> all){List<CategoryEntity> children = all.stream().filter(categoryEntity -> {return categoryEntity.getParentCid == root.getCatId();}).map(categoryEntity -> {categoryEntity.setChildren(getChildrens(categoryEntity,all));return categoryEntity;}).sorted((menu1,menu2)->{return (menu1.getSort()==null?0:menu1.getSort()) - (menu2.getSort()==null?0:menu2.getSort())}).collect(Collectors.toList());return children;
}
2.跨域问题的解决
跨域:当前网址与请求的网址 协议、域名、端口三者不完全相同
解决思路:
1、使用nginx部署为同一域
2、让服务器告诉预检请求能跨域
在网关中定义配置类
package com.atguigu.gulimall.gateway.config;@Configuration // gateway
public class GulimallCorsConfiguration {@Bean // 添加过滤器public CorsWebFilter corsWebFilter(){// 基于url跨域,选择reactive包下的UrlBasedCorsConfigurationSource source=new UrlBasedCorsConfigurationSource();// 跨域配置信息CorsConfiguration corsConfiguration = new CorsConfiguration();// 允许跨域的头corsConfiguration.addAllowedHeader("*");// 允许跨域的请求方式corsConfiguration.addAllowedMethod("*");// 允许跨域的请求来源corsConfiguration.addAllowedOrigin("*");// 是否允许携带cookie跨域corsConfiguration.setAllowCredentials(true);// 任意url都要进行跨域配置source.registerCorsConfiguration("/**",corsConfiguration);return new CorsWebFilter(source);}
}
这里配置跨域后前端访问还是会出错,因为脚手架工程renren-fast里面也对跨域做了一些配置,需要把那里面的配置注释掉,才能成功。
3.过滤器优先级问题
- id: ware_routeuri: lb://gulimall-warepredicates:- Path=/api/ware/**filters:- RewritePath=/api/(?<segment>.*),/$\{segment}- id: admin_routeuri: lb://renren-fastpredicates:- Path=/api/**filters: # 这段过滤器和验证码有关,api内容缓存了/renren-fast,还得注意/renren-fast也注册到nacos中- RewritePath=/api/(?<segment>.*),/renren-fast/$\{segment}
两个过滤器有明显的层次关系。 /api/** 包含了/api/ware/** 所以,要把比较精确的那个路由放到上面。
也就是把 /api/ware/** 放到 /api/** 的上面、
4.删除
@RequestBody:获取请求体,必须发送POST请求
SpringMVC自动将请求体的数据(json),转为对应的对象
多数时候我们并不希望真的把数据库中的数据删除,而只是采用逻辑删除。
也就是给所有数据加一个标记位,标记位为1则代表数据存在,为0则代表数据已被删除(举例)。
本质上就是把delete语句变成了update、当然这个可以去mybatis-plus中配置一下直接实现
application.yml:
mybatis-plus:mapper-locations: classpath:/mapper/**/*.xmlglobal-config:db-config:id-type: autologic-delete-value: 1logic-not-delete-value: 0
CategoryEntity :
/*** 是否显示[0-不显示,1显示]*/@TableLogic(value = "1",delval = "0")private Integer showStatus;
@TableLogic这个注解是要加的,让mybatis-plus识别这个是逻辑删除的标记位。置于什么标志代表是删还是不删,是可以通过在@TableLogic中加参数来声明,默认是1代表删,0代表没删。
前端的删除代码 就是发送post请求,把要逻辑删除的数据的ids发来
下面是vue前端代码
remove(node, data) {var ids = [data.catId];// 弹窗 确认this.$confirm(`是否删除【${data.name}】菜单?`, "提示", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning"}).then(() => { // 点击确定this.$http({// 给delete发送url: this.$http.adornUrl("/product/category/delete"),method: "post",data: this.$http.adornData(ids, false)}).then(({ data }) => {// 删除成功$messagethis.$message({message: "菜单删除成功",type: "success"});//刷新出新的菜单this.getMenus();//设置需要默认展开的菜单this.expandedKey = [node.parent.data.catId];});}).catch(// 取消() => {});}},//生命周期 - 创建完成(可以访问当前this实例)created() {this.getMenus();},//生命周期 - 挂载完成(可以访问DOM元素)mounted() {},beforeCreate() {}, //生命周期 - 创建之前beforeMount() {}, //生命周期 - 挂载之前beforeUpdate() {}, //生命周期 - 更新之前updated() {}, //生命周期 - 更新之后beforeDestroy() {}, //生命周期 - 销毁之前destroyed() {}, //生命周期 - 销毁完成activated() {} //如果页面有keep-alive缓存功能,这个函数会触发
};
5.增加修改拖拽
都属于前端vue知识,在官网有具体的操作步骤,这里就偷懒了。
https://blog.csdn.net/hancoder/article/details/107612619
七、品牌管理
还是基本一样,数据库拉数据显示到前端页面。和前面三级分类一样的部分就不记了。
然后品牌的话,涉及到图片,所以这里用阿里云云仓库。
1.阿里云上传
和传统的单体应用不同,这里我们选择将数据上传到分布式文件服务器上。
这里我们选择将图片放置到阿里云上,使用对象存储。
和图床类似,可以直接手动在网页上上传,这里的图片存储空间叫bucket
下面主要介绍代码上传
2.代码上传品牌图片
代码上传中,使用的 “AccessKey ID”和“AccessKeySecret” 是阿里云用户的子用户,这也是为了保证安全。该子用户拥有root用户的所有读写对象权限。
新建一个微服务用于专门上传图片。
依赖:
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alicloud-oss</artifactId><version>2.2.0.RELEASE</version></dependency>
具体按照官网操作即可
access-key secret-key endpoint 写入配置中心 然后再读取
@SpringBootTestclass GulimallThirdPartyApplicationTests { @Autowired OSSClient ossClient; @Test public void testUpload() throws FileNotFoundException { // Endpoint以杭州为例,其它Region请按实际情况填写。 String endpoint = "oss-cn-qingdao.aliyuncs.com"; // 云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,创建并使用RAM子账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建。 String accessKeyId = "LTAI4G4W1RA4JXz2QhoDwHhi"; String accessKeySecret = "R99lmDOJumF2x43ZBKT259Qpe70Oxw"; // 创建OSSClient实例。 OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); //上传文件流。 InputStream inputStream = new FileInputStream("C:\\Users\\HAN\\Downloads\\123.jpg"); ossClient.putObject("gulimall-fermhan", "333.jpg", inputStream); // 关闭OSSClient。 ossClient.shutdown(); System.out.println("上传成功."); }}
通过ossClient 操作、
上面的逻辑中,我们的想法是先把字节流给服务器,服务器给阿里云,还是传到了服务器。我们需要一些前端代码完成这个功能,字节流就别来服务器了
改进后:
@RestControllerpublic class OssController { @Autowired OSS ossClient; @Value ("${spring.cloud.alicloud.oss.endpoint}") String endpoint ; @Value("${spring.cloud.alicloud.oss.bucket}") String bucket ; @Value("${spring.cloud.alicloud.access-key}") String accessId ; @Value("${spring.cloud.alicloud.secret-key}") String accessKey ; @RequestMapping("/oss/policy") public Map<String, String> policy(){ String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); String dir = format; // 用户上传文件时指定的前缀。 Map<String, String> respMap=null; try { // 签名有效事件 long expireTime = 30; long expireEndTime = System.currentTimeMillis() + expireTime * 1000; Date expiration = new Date(expireEndTime); PolicyConditions policyConds = new PolicyConditions(); policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000); policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir); String postPolicy = ossClient.generatePostPolicy(expiration, policyConds); byte[] binaryData = postPolicy.getBytes("utf-8"); String encodedPolicy = BinaryUtil.toBase64String(binaryData); // 签名 String postSignature = ossClient.calculatePostSignature(postPolicy); respMap= new LinkedHashMap<String, String>(); respMap.put("accessid", accessId); respMap.put("policy", encodedPolicy); respMap.put("signature", postSignature); respMap.put("dir", dir); respMap.put("host", host); respMap.put("expire", String.valueOf(expireEndTime / 1000)); } catch (Exception e) { // Assert.fail(e.getMessage()); System.out.println(e.getMessage()); } finally { ossClient.shutdown(); } return respMap; }}
核心思想就是自己组装一个policy,发送给阿里云。这样的话,前端的请求只需要获取到这个policy,发送给阿里云就ok了。而不需要经过ossClient,也就是不需要经过服务器。
3.JSR303校验
前端提供一些校验,比如两次密码输入是否一致,然后定义一些输入规则。
详见原链接,或vue官网的组件。
后端可以通过一些注解来简单实现参数校验,主要在 javax.validation.constraints 包下,提供了如@Email,@NotNull等注解。
<!--jsr3参数校验器--><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId></dependency>里面依赖了hibernate-validator
@Valid内置异常
这里内置异常的意思是发生异常时返回的json不是我们的R对象,而是mvc的内置类
@RequestMapping("/save")public R save(@Valid @RequestBody BrandEntity brand){ brandService.save(brand); return R.ok();}
比如这样开启后,如果参数出错,返回的就不是R对象了,而是一些错误信息。
错误信息也可以自定义,比如:
@NotBlank(message = "品牌名必须非空") private String name;
这里有很多处理参数异常的注解,不细看了,因为实际开发中还不涉及,如果需要可以看:
https://blog.csdn.net/hancoder/article/details/107612619
统一异常处理
@Slf4j@RestControllerAdvice(basePackages = "com.atguigu.gulimall.product.controller")//管理的controllerpublic class GulimallExceptionControllerAdvice { @ExceptionHandler(value = Exception.class) // 也可以返回ModelAndView public R handleValidException(MethodArgumentNotValidException exception){ Map<String,String> map=new HashMap<>(); // 获取数据校验的错误结果 BindingResult bindingResult = exception.getBindingResult(); // 处理错误 bindingResult.getFieldErrors().forEach(fieldError -> { String message = fieldError.getDefaultMessage(); String field = fieldError.getField(); map.put(field,message); }); log.error("数据校验出现问题{},异常类型{}",exception.getMessage(),exception.getClass()); return R.error(400,"数据校验出现问题").put("data",map); }}
basePackages 包下所有controller的异常都会由这个类 GulimallExceptionControllerAdvice 处理
八、商品SPU和SKU管理
1.概念
SPU:standard product unit(标准化产品单元):是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性。
SKU:stock keeping unit(库存量单位):库存进出计量的基本单元,可以是件/盒/托盘等单位。SKU是对于大型连锁超市DC配送中心物流管理的一个必要的方法。现在已经被引申为产品统一编号的简称,每种产品对应有唯一的SKU号。
也就是说SPU是product(产品)级别的、比如iphoneX iphone9 小米8 什么的
而比如,手机颜色,内存,显卡这些,就是SKU,是keeping(库存)级别的。根据SKU才可以确定到一个具体的商品
简单说 三级分类 -> SPU -> SKU
手机/运营商/数码 -> 手机通讯 -> 手机 -> Apple iPhone 11 (A2223) 128GB 白色 移动联通电信4G手机 双卡双待 -> 128G 公开版 …
2.三级分类表和属性表
三级分类表包含了所有分类,属性表里有所有三级分类所拥有的属性。但这些属性和三级分类并非一一对应,比如属性表有1,2,3,三级分类表有A,B,C,那么A可能有1,2属性,B有1,2,3属性,C有2,3属性,三级分类和属性多了甚至会更复杂。
所以牵扯到三级分类表和属性表,这里一共需要四张表,三级分类表,属性表,属性分组表,三级分类和属性分组对应表。
属性分组表,就比如,一号属性分组内有1,2,3属性,二号属性分组表内有2,3属性。之所以要多一个属性分组表,是因为三级分类里面有很多这样的情况:A分类属性有1,2,3, B分类属性也有1,2,3 所以有了分组,会更便于管理。
3.分页插件
https://mp.baomidou.com/
mybatis-plus一个配置可以搞定
@EnableTransactionManagement@MapperScan("com.atguigu.gulimall.product.dao")@Configurationpublic class MybatisConfig { @Bean public PaginationInterceptor paginationInterceptor() { PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false paginationInterceptor.setOverflow(true); // 设置最大单页限制数量,默认 500 条,-1 不受限制 paginationInterceptor.setLimit(1000); return paginationInterceptor; }}
@MapperScan下面是dao接口的包
@EnableTransactionManagement是开启事务
4.模糊查询
@Override // BrandServiceImplpublic PageUtils queryPage(Map<String, Object> params) { QueryWrapper<BrandEntity> wrapper = new QueryWrapper<>(); String key = (String) params.get("key"); if(!StringUtils.isEmpty(key)){ // 字段等于 or 模糊查询 wrapper.eq("brand_id", key).or().like("name", key); } // 按照分页信息和查询条件 进行查询 IPage<BrandEntity> page = this.page( // 传入一个IPage对象,他是接口,实现类是Page new Query<BrandEntity>().getPage(params), wrapper ); return new PageUtils(page);}
此处的 .eq 意思是key必须和brand_id完全相同
而or的意思是两边条件是或的关系
like是模糊匹配 是左右模糊的 执行的sql类似于
wrapper就是存放匹配规则的model
SELECT * FROM users WHERE (firstname = '海' OR lastname LIKE '%海%')
5.冗余字段保持一致
也就是说,后台管理系统,修改一些字段的时候,涉及到的关联关系也要同步修改。此处略
https://blog.csdn.net/hancoder/article/details/107612619
6.PO VO DTO POJO
PO就是对应数据库中某个表中的一条记录,多个记录可以用PO的集合。PO中应该不包含任何对数据的操作。
DTO这个概念来源于J2EE的设汁模式,原来的目的是为了EJB的分布式应用握供粗粒度的数据实体,以减少分布式调用的次数,从而握分布式调用的性能和降低网络负载,但在这里,泛指用于示层与服务层之间的数据传输对象。
VO通常用于业务层之间的数据传递,和PO一样也是仅仅包含数据而已。但应是抽象出的业务对象,可以和表对应,也可以不,这根据业务的需要。用new关韃字创建,由GC回收的。
POJO简单无规则java对象。
九、规格参数新增与VO
1.新建VO
现在的情况是,它在保存的时候,只是保存了attr,并没有保存attrgroup,为了解决这个问题,我们新建了一个vo/AttrVo.java,在原Attr基础上增加了attrGroupId字段,使得保存新增数据的时候,也保存了它们之间的关系。
通过" BeanUtils.copyProperties(attr,attrEntity);"能够实现在两个Bean之间属性对拷
简单来说就是,现在我这个请求需要的参数,并不是一个完整的数据库表的数据,也就是前端传来的数据并不是一个PO,此时就需要VO的新建。然后把VO的数据提取到各个PO中,再去业务层CRUD。
@Transactional@Overridepublic void saveAttr(AttrVo attrVo) { AttrEntity attrEntity = new AttrEntity(); // 重要的工具 BeanUtils.copyProperties(attrVo, attrEntity); //1、保存基本数据 this.save(attrEntity); //2、保存关联关系 if (attrVo.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() && attrVo.getAttrGroupId() != null) { AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity(); relationEntity.setAttrGroupId(attrVo.getAttrGroupId()); relationEntity.setAttrId(attrEntity.getAttrId()); relationEntity.setAttrSort(0); relationDao.insert(relationEntity); }}
2.查询涉及到多个表
要分步骤查询,根据一个参数从一个表中查出一个结果,这个结果作为参数再去查另一个表。
不要多表联查。因为多表联查太耗费性能。
3.采购
采购需求的生成方式可能有两种:
- 人工新增
- 系统检测到库存量低自动创建
新建采购需求后还要可以提供合并采购单,比如一个仓库的东西可以合并到一起,让采购人员一趟采购完
领取采购单时要查询该采购单的状态是否是未领取,防止重复领取。
采购完成后更新库存。
十、ES
1.基本概念
index type document
分别相当于mysql的数据库 表 记录
ES通过倒排索引来提高查询效率、也就是关键词匹配
2.安装
docker中安装elastic search(也就是在linux虚拟机中docker pull)
下载ealastic search(存储和检索)和kibana(可视化检索)
3.配置
docker目录中的es目录挂载到linux 、 方便修改数据
设置es可以被任何机器访问
设置开机自启动 设置访问权限 设置占用内存的大小
kibana也一样 设置开机自启动 设置与es的交互端口 设置自己的主页端口
kibana只是一个es的可视化界面 不安装也可以 因为我们是通过发请求的方式操作es的
4.基本命令
这些命令是通过发送请求的方式 形如:http://192.168.56.10:9200/_cat/nodes
GET /_cat/nodes:查看所有节点
GET /_cat/health:查看es健康状况
GET /_cat/master:查看主节点
GET/_cat/indices:查看所有索引 ,等价于mysql数据库的show databases(之前说过 es的索引相当于mysql的数据库)
新增/修改
# # 在customer索引下的external类型下保存1号数据PUT customer/external/1# POSTMAN输入http://192.168.56.10:9200/customer/external/1{ "name":"John Doe"}
此处put也可以换成post 两者区别:
put必须有标号 而post可以没有 没有标号的时候会默认随机一个不重复的标号
当标号相同时,会从新增改为修改操作
结果:
返回数据:带有下划线开头的,称为元数据,反映了当前的基本信息。 { "_index": "customer", 表明该数据在哪个数据库下; "_type": "external", 表明该数据在哪个类型下; "_id": "1", 表明被保存数据的id; "_version": 1, 被保存数据的版本 "result": "created", 这里是创建了一条数据,如果重新put一条数据,则该状态会变为updated,并且版本号也会发生变化。 "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 0, "_primary_term": 1}
每次更新 _version 变化
_id可以指定 不指定会随机一个不重复的 _id
seq_no和version的区别:
每个文档的版本号" _ version" 起始值都为1 每次对当前文档成功操作后都加1
而序列号"_seq_no"则可以看做是索引的信息 在第一次为索引插入数据时为0,每对索引内数据操作成功一次 _seq_no 加1, 并且文档会记录是第几次操作使它成为现在的情况的
更新命令:(发送请求的方式)
POST customer/externel/1/_update{ "doc":{ "name":"111" }}或者POST customer/externel/1{ "doc":{ "name":"222" }}或者PUT customer/externel/1{ "doc":{ "name":"222" }}PUT http://192.168.56.10:9200/customer/external/1?if_seq_no=18&if_primary_term=6当 _seq_no 和 _primary_term 匹配时,才修改
可以看到更新和新增请求是有重复部分的
区别可以看原网页
主要就是两种
一种会对比原来的数据,一样就不动
一种是不对比,数据不变,版本号依然会增加
https://blog.csdn.net/hancoder/article/details/113922398
查询
GET /customer/external/1
http://192.168.56.10:9200/customer/external/1
查询结果示例:
{ "_index": "customer", "_type": "external", "_id": "1", "_version": 10, "_seq_no": 18,//并发控制字段,每次更新都会+1,用来做乐观锁 "_primary_term": 6,//同上,主分片重新分配,如重启,就会变化 "found": true, "_source": { "name": "John Doe" }}
删除
DELETE customer/external/1
DELETE customer
此处只能删除文档和索引(相当于数据库的一条数据和数据库)
es是不支持删除类型的(相当于数据库的一张表)
5.批量操作
执行多条数据(指定索引/类型)
POST /customer/external/_bulk{"index":{"_id":"1"}}{"name":"John Doe"}{"index":{"_id":"2"}}{"name":"John Doe"}
对于整个索引执行批量操作
POST /_bulk{"delete":{"_index":"website","_type":"blog","_id":"123"}}{"create":{"_index":"website","_type":"blog","_id":"123"}}{"title":"my first blog post"}{"index":{"_index":"website","_type":"blog"}}{"title":"my second blog post"}{"update":{"_index":"website","_type":"blog","_id":"123"}}{"doc":{"title":"my updated blog post"}}
可以看到是在具体的条目上加了操作类型(delete、create、update),索引、类型、文档id(创建可以不加)
批量导入样本测试数据(此处仅导入一条,其余与此类似)
POST bank/account/_bulk{"index":{"_id":"1"}}{ "account_number": 1, "balance": 39225, "firstname": "Amber", "lastname": "Duke", "age": 32, "gender": "M", "address": "880 Holmes Lane", "employer": "Pyrami", "email": "amberduke@pyrami.com", "city": "Brogan", "state": "IL"}
6.进阶–检索
首先是检查一下虚拟机状态
sudo docker ps检查当前在运行的容器sudo docker ps -a检查容器中的所有应用(启动未启动都罗列)sudu docker start 84c 847 启动容器中84c 847唯一标识的应用(两个)sudo docker update 84c --restart=always让84c标识的应用每次都自动重启
请求参数方式检索GET bank/_search?q=*&sort=account_number:ascq就是检索条件 *代表查所有 sort是排序信息 account_number升序排列
uri+请求体进行检索GET /bank/_search{ "query": { "match_all": {} }, "sort": [ { "account_number": "asc" }, { "balance":"desc"} ]}
DSL领域特定语言
Elasticsearch提供了一个可以执行查询的Json风格的DSL(domain-specific language领域特定语言)。这个被称为Query DSL,该查询语言非常全面。
示例 使用时不要加#注释内容GET bank/_search{ "query": { # 查询的字段 "match_all": {} }, "from": 0, # 从第几条文档开始查 "size": 5, "_source":["balance","firstname"], # 返回哪些字段 不写就全部返回 "sort": [ { "account_number": { # 返回结果按哪个列排序 "order": "desc" # 降序 } } ]}_source为要返回的字段from+size限定,完成分页功能;sort排序,多字段排序,会在前序字段相等时后续字段内部排序,否则以前序为准;
query/match匹配查询
如果是非字符串,会进行精确匹配。如果是字符串,会进行全文检索,然后按照匹配度降序返回。
GET bank/_search{ "query": { "match": { "account_number": "20" } }}GET bank/_search{ "query": { "match": { "address": "mill road" # 匹配到的包括:包含mill的 包含road的 包含mill road的 } }}
query/match_phrase [不拆分匹配]
前面的是包含mill或road就查出来,我们现在要都包含才查出
GET bank/_search{ "query": { "match_phrase": { "address": "mill road" # 就是说不要匹配只有mill或只有road的,要匹配mill road一整个子串 } }}
字段.keyword:必须全匹配上才检索成功
GET bank/_search{ "query": { "match": { "address.keyword": "990 Mill" # 字段后面加上 .keyword } }}
address必须为"990 Mill" 有一点差别都不能匹配
query/multi_math【多字段匹配】
state或者address中包含mill,并且在查询过程中,会对于查询条件进行分词。
GET bank/_search{ "query": { "multi_match": { # 前面的match仅指定了一个字段。 "query": "mill", "fields": [ # state和address有mill子串 不要求都有 "state", "address" ] } }}
query/bool/must复合查询
也就是bool查询 内部可以写多个match语句
GET bank/_search{ "query": { "bool": { "must": [ { "match": { "gender": "M" #gender必须包含M } }, { "match": { "address": "mill" #address必须包含mill } } ], "must_not": [ { "match": { "age": "18" #年龄必须不包含18 } } ], "should": [ { "match": { "lastname": "Wallace" #lastname最好是wallace 不是也可以 只影响max_score(匹配度) } } ] } }}
query/filter【结果过滤】
filter对查询的最终结果进行过滤 不贡献得分(max_score)
GET bank/_search{ "query": { "bool": { "must": [ { "match": {"address": "mill" } } ], "filter": { # query.bool.filter "range": { "balance": { # 哪个字段 过滤剩下balance在10000~20000之间的 且该条件不会影响匹配得分 "gte": "10000", "lte": "20000" } } } } }}
query/term
和match一样。匹配某个属性的值。
- 全文检索字段用match,
- 其他非text字段匹配用term。
不要使用term来进行文本字段查询
GET bank/_search{ "query": { "term": { "age": "30" } }}
分布式电商项目 谷粒商城 学习笔记<2>相关推荐
- 尚硅谷2020微服务分布式电商项目《谷粒商城》学习笔记
尚硅谷2020微服务分布式电商项目<谷粒商城> 项目简介 资料 百度云 链接:https://pan.baidu.com/s/1eGCTi6pLtKbDCwBs-zCOzQ 提取码:1pm ...
- JavaEE大型分布式电商项目 上海淘淘商城 29期
上海29期_张志君老师_淘淘商城_大型分布式电商项目 JavaEE大型分布式电商项目 淘淘商城 29期 需要的加qq:350226234,备注:程序员学习视频 ==================== ...
- 分布式电商项目五:使用人人开源搭建前后分离的后台管理系统
分布式电商项目五:使用人人开源搭建前后分离的后台管理系统 现在我们开始搭建一个后台管理系统,使用的是码云上面的开源项目:人人开源 需要使用两个开源项目:fast和fast-vue. 使用git把需要的 ...
- ActiveMQ+Redis+Dubbo+SpringMVC+Mybatis高并发高集群分布式电商项目视频课程(免费不加密)
ActiveMQ+Redis+FastDFS+Dubbo+Nginx+SpringMVC+Mybatis高并发高集群分布式电商项目视频课程 分布式实战项目1.mp4 分布式实战项目2.mp4 分布式实 ...
- 谷粒商城 - 微服务分布式电商项目
谷粒商城 1.项目背景 谷粒商城项目是尚硅谷研究院最新推出的完整大型分布式架构电商平台,技术全面.业务深入,全网无出其右.技术涵盖:微服务架构 + 分布式 + 全栈 + 集群 + 部署 + 自动化运维 ...
- 尚硅谷2020微服务分布式电商项目《谷粒商城》-单点登录(jwt)
学习更多的知识,整理不易,拒绝白嫖,记得三连哦 关注公众号:java星星 获取全套课件资料 1. 用户管理提供数据接口 1.1. 数据验证功能 根据接口文档知: 请求方式:GET 请求路径:check ...
- 尚硅谷2020微服务分布式电商项目《谷粒商城》-支付、秒杀
学习更多的知识,整理不易,拒绝白嫖,记得三连哦 关注公众号:java星星 获取全套课件资料 1. 支付 订单搞定之后就是支付了,首先搭建支付工程. 1.1. 搭建环境 pom.xml <?xml ...
- 尚硅谷2020微服务分布式电商项目《谷粒商城》-商品搜索
关注公众号:java星星 获取全套课件资料 1. 导入商品数据 1.1. 搭建搜索工程 pom.xml内容如下: <?xml version="1.0" encoding=& ...
- JavaEE大型分布式电商项目 上海淘淘商城
原文出自:https://blog.csdn.net/hjsw1/article/details/76615681 淘淘商城是一个综合性的B2C平台,类似与京东.天猫商城,其打造的是商业模式为&quo ...
最新文章
- linux驱动设备树
- 中国移动短信网关CMPP3.0 C#源代码:CMPP30类(1)(转)
- Spring框架中的内容协商
- 给年薪不到48w的程序员提个醒!!
- 只需一行代码,完美呈现Markdown格式,写作展示两不误
- 不能使用sizeof计算的表达式
- hexo搭建博客系列(六)百度,必应,谷歌收录
- 嫦娥五号顺利升空,NASA、欧洲航天局回应
- Matlab中的plotyy细讲(双坐标图)
- npm安装同一个包的不同版本,以echarts为例
- MAC OS下设置bits/stdc++.h万能头文件
- Redis 存储List对象
- 优麒麟mysql_Ubuntu kylin优麒麟下配置Hive环境
- 扫描MAC地址脚本--保存
- 【思维导图】巩固你的JavaScript知识体系
- 大数据时代下的贝叶斯公式
- MySQl 面试重点_2.常见的索引面试题总结
- 广州坐标系转换大地2000_地方坐标到2000国家大地坐标转换方法
- 基于 Go 语言开发 Serverless 云原生应用
- 电商裂变新玩法—全新拼团!
热门文章
- java程序员微信群,欢迎准java行业人员加入,会一直更新
- 关于PyTorch Geometric的安装及问题解决记录
- 打印一只Nyan Cat(彩虹猫)(C++)3.0[多色版]
- Unity + Kinect基本上所有的手势二次封装(一)
- 英文文章汇总+翻译小亮点
- S形曲线-斜坡指(S形加减速)
- 简易制作智能插座WIFI版--硬件篇
- 全闪存阵列叩开企业级应用大门
- 怎么用计算机算出一个人的生日,怎样才能在网上查到一个人的生日
- 竹林蹊径:深入浅出Windows驱动开发(china-pub预订中)