栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

分布式电商项目 谷粒商城 学习笔记<2>

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

分布式电商项目 谷粒商城 学习笔记<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 children;
@Override
public List listWithTree(){
	//1、查出所有分类 null表名没有查找的条件 即全部查出
	List entities = baseMapper.selectList(null);
	
	//2、组装成父子的树形结构
	//2.1 找到所有的一级分类
	List level1Menus = entities.stream().filter(categoryEntity ->
		categoryEntity.getParentCid()==0
	).map((menu)->{
		menu.setChildren(getChildrens(menu,entities));
		return menu;
	}).collect(Collectors.toList());
	
	return level1Menus;
}

private List getChildrens(CategoryEntity root,List all){
    
    List 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("*.xml
  global-config:
    db-config:
      id-type: auto
      logic-delete-value: 1
      logic-not-delete-value: 0

CategoryEntity :

	@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/i(`是否删除【${data.name}】菜单?`, "提示", {
        /confirm/iButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      })
        .then(() => { // 点击确定
          this.$http({
              // 给delete发送
            url: this.$http.adornUrl("/product/category/delete"),
            method: "post",
            data: this.$http.adornData(ids, false)
          }).then(({ data }) => {
              // 删除成功$message
            this.$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用户的所有读写对象权限。

新建一个微服务用于专门上传图片。

依赖:

		
            com.alibaba.cloud
            spring-cloud-starter-alicloud-oss
            2.2.0.RELEASE
        

具体按照官网操作即可

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 policy(){        String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint        String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());        String dir = format; // 用户上传文件时指定的前缀。        Map 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();            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等注解。

    org.springframework.boot    spring-boot-starter-validation里面依赖了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 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 params) {    QueryWrapper wrapper = new QueryWrapper<>();    String key = (String) params.get("key");    if(!StringUtils.isEmpty(key)){        // 字段等于  or  模糊查询        wrapper.eq("brand_id", key).or().like("name", key);    }    // 按照分页信息和查询条件  进行查询    IPage page = this.page(        // 传入一个IPage对象,他是接口,实现类是Page        new Query().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"    }  }}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/450710.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号