【elasticsearch系】1.初识玩转elasticSearch

news2024/9/25 23:23:59

首先给大家介绍下我使用的版本是7.17.3这个版本,关于之前6.x的版本还是有些区别的。

elasticSearch

Elasticsearch 是一个分布式文档存储。Elasticsearch 不是将信息存储为列式数据行,而是存储已序列化为 JSON 文档的复杂数据结构。存储文档时,会在1 秒内近乎实时地为其建立索引并完全可搜索。Elasticsearch 使用称为倒排索引的数据结构,支持非常快速的全文搜索。关于具体详细的大家可以查看官方文档来了解下

安装使用

因为elasticSearch是java语言开发的,关于java环境的安装这里就不介绍了,大家可自行搜索解决

为了方便学习和联系,这里我直接使用的是window安装的版本

下载elasticSearch

https://www.elastic.co/cn/downloads/past-releases#elasticsearch

解压后,我们可以看下elasticsearch.bat 启动文件引用调用了elasticsearch-env.bat这个文件。我么可以大概看下elasticsearch-env的文件内容

 所以我们可以配置下es的系统环境变量

 直接双击点击elasticsearch.bat文件启动,简直不能太easy

 

如果你的控制台没有什么异常问题的话,可以访问http://localhost:9200 默认端口9200验证下,出现下面的显示就代表启动没有什么问题

访问看下我们本地节点监控  http://localhost:9200/_cat/nodes?v

 客户端kibana安装

Kibana是一个开源分析和可视化平台,旨在与Elasticsearch协同工作。使用这个工具可以方便我们使用Rest API来操作我们的elasticSearch

这里注意我们最好使用和es相同的版本号

Past Releases of Elastic Stack Software | Elastic

修改对应的配置yml 国际化为zh_CN

i18n.locale: "zh-CN"

# Kibana is served by a back end server. This setting specifies the port to use.
server.port: 5601

# Specifies the address to which the Kibana server will bind. IP addresses and host names are both valid values.
# The default is 'localhost', which usually means remote machines will not be able to connect.
# To allow connections from remote users, set this parameter to a non-loopback address.
server.host: "localhost"

# Enables you to specify a path to mount Kibana at if you are running behind a proxy.
# Use the `server.rewriteBasePath` setting to tell Kibana if it should remove the basePath
# from requests it receives, and to prevent a deprecation warning at startup.
# This setting cannot end in a slash.
#server.basePath: ""

# Specifies whether Kibana should rewrite requests that are prefixed with
# `server.basePath` or require that they are rewritten by your reverse proxy.
# This setting was effectively always `false` before Kibana 6.3 and will
# default to `true` starting in Kibana 7.0.
#server.rewriteBasePath: false

# Specifies the public URL at which Kibana is available for end users. If
# `server.basePath` is configured this URL should end with the same basePath.
#server.publicBaseUrl: ""

# The maximum payload size in bytes for incoming server requests.
#server.maxPayload: 1048576

# The Kibana server's name.  This is used for display purposes.
#server.name: "your-hostname"

# The URLs of the Elasticsearch instances to use for all your queries.
elasticsearch.hosts: ["http://localhost:9200"]

# Kibana uses an index in Elasticsearch to store saved searches, visualizations and
# dashboards. Kibana creates a new index if the index doesn't already exist.
#kibana.index: ".kibana"

# The default application to load.
#kibana.defaultAppId: "home"

# If your Elasticsearch is protected with basic authentication, these settings provide
# the username and password that the Kibana server uses to perform maintenance on the Kibana
# index at startup. Your Kibana users still need to authenticate with Elasticsearch, which
# is proxied through the Kibana server.
#elasticsearch.username: "kibana_system"
#elasticsearch.password: "pass"

# Kibana can also authenticate to Elasticsearch via "service account tokens".
# If may use this token instead of a username/password.
# elasticsearch.serviceAccountToken: "my_token"

# Enables SSL and paths to the PEM-format SSL certificate and SSL key files, respectively.
# These settings enable SSL for outgoing requests from the Kibana server to the browser.
#server.ssl.enabled: false
#server.ssl.certificate: /path/to/your/server.crt
#server.ssl.key: /path/to/your/server.key

# Optional settings that provide the paths to the PEM-format SSL certificate and key files.
# These files are used to verify the identity of Kibana to Elasticsearch and are required when
# xpack.security.http.ssl.client_authentication in Elasticsearch is set to required.
#elasticsearch.ssl.certificate: /path/to/your/client.crt
#elasticsearch.ssl.key: /path/to/your/client.key

# Optional setting that enables you to specify a path to the PEM file for the certificate
# authority for your Elasticsearch instance.
#elasticsearch.ssl.certificateAuthorities: [ "/path/to/your/CA.pem" ]

# To disregard the validity of SSL certificates, change this setting's value to 'none'.
#elasticsearch.ssl.verificationMode: full

# Time in milliseconds to wait for Elasticsearch to respond to pings. Defaults to the value of
# the elasticsearch.requestTimeout setting.
#elasticsearch.pingTimeout: 1500

# Time in milliseconds to wait for responses from the back end or Elasticsearch. This value
# must be a positive integer.
#elasticsearch.requestTimeout: 30000

# List of Kibana client-side headers to send to Elasticsearch. To send *no* client-side
# headers, set this value to [] (an empty list).
#elasticsearch.requestHeadersWhitelist: [ authorization ]

# Header names and values that are sent to Elasticsearch. Any custom headers cannot be overwritten
# by client-side headers, regardless of the elasticsearch.requestHeadersWhitelist configuration.
#elasticsearch.customHeaders: {}

# Time in milliseconds for Elasticsearch to wait for responses from shards. Set to 0 to disable.
#elasticsearch.shardTimeout: 30000

# Logs queries sent to Elasticsearch. Requires logging.verbose set to true.
#elasticsearch.logQueries: false

# Specifies the path where Kibana creates the process ID file.
#pid.file: /run/kibana/kibana.pid

# Enables you to specify a file where Kibana stores log output.
#logging.dest: stdout

# Set the value of this setting to true to suppress all logging output.
#logging.silent: false

# Set the value of this setting to true to suppress all logging output other than error messages.
#logging.quiet: false

# Set the value of this setting to true to log all events, including system usage information
# and all requests.
#logging.verbose: false

# Set the interval in milliseconds to sample system and process performance
# metrics. Minimum is 100ms. Defaults to 5000.
#ops.interval: 5000

# Specifies locale to be used for all localizable strings, dates and number formats.
# Supported languages are the following: English - en , by default , Chinese - zh-CN .
i18n.locale: "zh-CN"

双击启动kibana.bat文件即可

 浏览器打开访问 http://localhost:5601/    

 找到主页面菜单-》开发者工具  我们就可以使用练习操作es的api了

 

操作es索引脚本

以下就是练习操作es索引的一些请求,大家可以直接在kibana 开发者工具操作执行练习

GET _search
{
  "query": {
    "match_all": {}
  }
}

#查看索引列表
GET /_cat/indices

#默认分词器
POST _analyze
{
  "analyzer": "standard",
  "text":"中华人民共和国"
}

# icu分词器 粗粒度的拆
POST _analyze
{
  "analyzer": "icu_analyzer",
  "text":"中华人民共和国"
}

# ik分词器 粗粒度的拆
POST _analyze
{
  "analyzer": "ik_smart",
  "text":"中华人民共和国"
}

# ik分词器 细粒度
POST _analyze
{
  "analyzer": "ik_max_word",
  "text":"中华人民共和国"
}


#创建索引
PUT  /user

#删除索引
DELETE /user

# 字段属性type为keyword代表不分词
GET /user



# 当我们添加数据的时候,默认会动态映射帮我们创建字段的类型
# 但是我们还是需要自己做静态映射来创建对应字段的类型

PUT  /user
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 1
  },
  "mappings": {
    "properties": {
       "id":{
        "type": "long"
      },
      "name":{
        "type": "keyword"
      },
      "age":{
        "type": "long"
      },
      "address":{
        "type": "text"
      }
    }
  }
}



# 创建/修改一条数据
# 这种方式做修改的话,注意下是全量做的修改,如果使用下面这种方式,直
# 会把我们的age字段干掉
# PUT /user/_doc/1
# {
#  "name":"john2",
#  "address":"陕西西安"
# }
#
PUT /user/_doc/1
{
  "id":1,
  "name":"john",
  "age":32,
  "address":"陕西西安"
}


PUT /user/_doc/2
{
  "id":2,
  "name":"mark",
  "age":18,
  "address":"陕西渭南"
}

GET /user/_doc/2

#查询数据
GET /user/_search
{
  "query":{
    "match": {
      "address": "西"
    }
  }
}


#term不分词查询
GET /user/_search
{
  "query": {
    "term": {
      "name.keyword": "john"
    }
  }
}


#重建索引 比如我现在想把name类型设置为text,address字段使用ik分词器
# 步骤:先创建一个新的索引user2
#       _reindx给新建的索引起个别名为原来的索引名称user
#       删除旧的索引
#       _alias给新的索引起别名为user  /user2/_alias/user

## 下面是重建索引的详细步骤 开始 ##
PUT /user2
{
  "mappings": {
    "properties": {
       "id":{
        "type": "long"
      },
      "name":{
        "type": "text"
      },
      "age":{
        "type": "long"
      },
      "address":{
        "type": "text",
        "analyzer": "ik_max_word"
      }
    }
  }
}

POST  _reindex
{
  "source": {
    "index": "user"
  },
  "dest": {
    "index": "user2"
  }
}

#删除索引
DELETE /user

#给user2索引起别名为user
PUT /user2/_alias/user

#查看user索引
GET /user 


#查询数据
GET /user/_search
{
  "query":{
    "match": {
      "address": "西安"
    }
  }
}

## 重建索引的详细步骤 结束 ##


# 修改索引默认的分词器

DELETE /user2
PUT /user
{
  "settings": {
    "index":{
      "analysis.analyzer.default.type":"ik_max_word"
    }
  }
}
GET /user


#URI query查询(了解即可)
GET /user/_doc/_search?q=age:>30


#DSL query查询(重点平常工作中)
#match匹配查询,会对查询文本分词后匹配

GET /user/_search
{
  "query":{
    "match": {
      "address": "陕西"
    }
  }
}

#term 词项查询,属于精确查询,不会对查询文本进行分词
GET /user/_search
{
  "query": {
    "term": {
      "address": "陕西西安"
    }
  }
}

#查看ik分词器对于"陕西西安"这个文本是怎么分词的
POST _analyze
{
  "analyzer": "ik_max_word",
  "text":"陕西西安"
}


#使用脚本语句来更新
GET /user/_doc/2
POST  /user/_update_by_query
{
  "query": {
    "match": {
      "_id": "2"
    }
  },
  "script": {
    "source": "ctx._source.age=28"
  }
}


# 使用_update部分更新
# _update不会删除原来的文档,而是实现真正的数据更新
POST  /user/_update/2
{
  "doc":{
    "age":30
  }
}


# 批量操作可以减少网络连接所产生的开销,提升性能
# 批量创建文档create

POST _bulk
{"create":{"_index":"article","_type":"_doc","_id":1}}
{"id":1,"title":"策略设计模式","content":"策略设计模式content","tags":["设计模式","代码设计"],"create_time":1554015482530}
{"create":{"_index":"article","_type":"_doc","_id":2}}
{"id":1,"title":"工厂设计模式","content":"工厂设计模式content","tags":["设计模式","代码设计"],"create_time":1554015482530}



# 批量普通创建或全量替换索引index
# 如果原文档不存在,则是创建
# 如果原文档存在,则是替换(全量修改原文档)
POST _bulk
{"index":{"_index":"article","_type":"_doc","_id":1}}
{"id":1,"title":"策略设计模式","content":"策略设计模式解决if-else繁琐问题","tags":["设计模式","代码设计"],"create_time":1554015482530}
{"index":{"_index":"article","_type":"_doc","_id":2}}
{"id":1,"title":"工厂设计模式","content":"工厂设计模式封装对象创建使用","tags":["设计模式","代码设计"],"create_time":1554015482530}


# 批量修改update不会全量覆盖
POST _bulk
{"update":{"_index":"article", "_type":"_doc", "_id":1}}
{"doc":{"title":"策略模式"}}
{"update":{"_index":"article", "_type":"_doc", "_id":2}}
{"doc":{"create_time":1554018421008}}


GET /article/_search


# 批量删除
POST _bulk
{"delete":{"_index":"article", "_type":"_doc", "_id":1}}
{"delete":{"_index":"article", "_type":"_doc", "_id":2}}
GET /article/_search



springboot集成elasticSearch

版本选择

这里是springboot官方文档的推荐版本 ,看下图需要我们的springboot版本使用2.7.x版本即可

pom文件引入依赖

 <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

application.yml配置

spring:
  elasticsearch:
    uris: http://localhost:9200
    connection-timeout: 3s

创建索引对象实体

@Data
@AllArgsConstructor
@Document(indexName = "user")
public class EsUserModel {
    @Id
    private Long id;
    @Field(type= FieldType.Keyword)
    private String name;
    private int age;
    @Field(type= FieldType.Text,analyzer="ik_max_word")
    private String address;

}

操作测试代码

package com.es.example;

import com.es.example.model.EsUserModel;
import lombok.extern.slf4j.Slf4j;
import net.minidev.json.JSONValue;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.ArrayList;
import java.util.List;


@SpringBootTest
@Slf4j
public class ElasticsearchRestTemplateTest {

    @Autowired
    ElasticsearchRestTemplate elasticsearchRestTemplate;

    private final String index_name = "user";


    /**
     * 删除索引
     */
    @Test
    public void testDeleteIndex() {
        //删除索引
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(IndexCoordinates.of(index_name));
        indexOperations.delete();
    }

    /**
     * 创建索引
     */
    @Test
    public void testCreateIndex() {
        //创建索引
        IndexOperations indexOperations = elasticsearchRestTemplate.indexOps(IndexCoordinates.of(index_name));
        if (indexOperations.exists()) {
            log.info("索引已经存在");
        } else {
            //创建索引
            indexOperations.create();
        }
    }

    /**
     * 批量添加文档数据
     */
    @Test
    public void testInsertBatch() {
        List<EsUserModel> esUserModels = new ArrayList<>();
        esUserModels.add(new EsUserModel(1L, "张三", 16, "陕西渭南"));
        esUserModels.add(new EsUserModel(2L, "李四", 18, "陕西西安"));
        esUserModels.add(new EsUserModel(3L, "王五", 19, "广州天河"));

        List<IndexQuery> queries = new ArrayList<>();
        for (EsUserModel esUserModel : esUserModels) {
            IndexQuery indexQuery = new IndexQuery();
            indexQuery.setId(esUserModel.getId().toString());
            String json = JSONValue.toJSONString(esUserModel);
            indexQuery.setSource(json);
            queries.add(indexQuery);
        }
        //bulk批量插入
        elasticsearchRestTemplate.bulkIndex(queries, EsUserModel.class);

    }

    @Test
    public void testQueryDocument() {
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        //查询
        builder.withQuery(QueryBuilders.matchQuery("address", "陕西"));
        // 设置分页信息
        builder.withPageable(PageRequest.of(0, 5));
        // 设置排序
        builder.withSort(SortBuilders.fieldSort("age").order(SortOrder.DESC));
        SearchHits<EsUserModel> search = elasticsearchRestTemplate.search(builder.build(), EsUserModel.class);
        List<SearchHit<EsUserModel>> searchHits = search.getSearchHits();
        for (SearchHit hit : searchHits) {
            log.info("返回结果:" + hit.toString());
        }
    }


}

控制台输出

我们使用kibana开发者工具请求验证是否和控制台输出一样

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/809718.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PHP8的数据类型-PHP8知识详解

在PHP8中&#xff0c;变量不需要事先声明&#xff0c;赋值即声明。 不同的数据类型其实就是所储存数据的不同种类。在PHP8.0、8.1中都有所增加。以下是PHP8的15种数据类型&#xff1a; 1、字符串&#xff08;String&#xff09;&#xff1a;用于存储文本数据&#xff0c;可以使…

【深度学习】High-Resolution Image Synthesis with Latent Diffusion Models,论文

13 Apr 2022 论文&#xff1a;https://arxiv.org/abs/2112.10752 代码&#xff1a;https://github.com/CompVis/latent-diffusion 文章目录 PS基本概念运作原理 AbstractIntroductionRelated WorkMethodPerceptual Image CompressionLatent Diffusion Models Conditioning Mec…

【13】STM32·HAL库-正点原子SYSTEM文件夹 | SysTick工作原理、寄存器介绍 | printf函数使用、重定向

目录 1.sys文件夹介绍&#xff08;掌握&#xff09;2.deley文件夹介绍&#xff08;掌握&#xff09;2.1deley文件夹函数简介2.2SysTick工作原理2.3SysTick寄存器介绍2.4delay_init()函数&#xff08;F1&#xff09;2.5delay_us()函数&#xff08;F1&#xff09;2.6delay_ms()函…

网络安全-防御需知

目录 网络安全-防御 1.网络安全常识及术语 资产 漏洞 0day 1day 后门 exploit APT 2.什么会出现网络安全问题&#xff1f; 网络环境的开放性 协议栈自身的脆弱性 操作系统自身的漏洞 人为原因 客观原因 硬件原因 缓冲区溢出攻击 缓冲区溢出攻击原理 其他攻击…

Java另一种debug方法(not remote jmv debug),类似python远程debug方式

这种Debug类似python的debug方式&#xff0c;是运行时将业务代码及依赖推送到Linux并使用Linux的java运行运行程。只要本地能运行&#xff0c;就能自动将代码推送到Linux运行&#xff0c;不需打包及设置远程debug jvm参数&#xff0c;适合一些项目Debug调试 运行时会推送一些依…

Flowable-中间事件-空中间抛出事件

定义 空中间抛出事件是一个 Throwing 事件&#xff0c;在 intermediateThrowEvent 元素下不加入任何的事件定 义元素&#xff0c;就构成一个空中间抛出事件。它通常用于表示流程中的某个状态&#xff0c;在实际使用的过程中可 以通过添加执行监听器&#xff0c;来表示流程状态…

js原型以及原型链

目录 原型隐式原型显式原型constructornew操作符 重写原型对象原型链继承原型链继承借用构造函数继承组合构造继承 原型继承寄生继承组合寄生继承 原型继承关系 原型 在JavaScript中&#xff0c;每个对象都有一个内置属性[[prototype]]&#xff0c;这个属性指向一个另一个对象…

Nginx实现反向代理和负载均衡

Nginx安装 本文章主要介绍下&#xff0c;如何使用Nginx来实现反向代理和负载均衡&#xff0c;Nginx安装和基础知识&#xff0c;可参考我的这篇文章 Nginx安装。 Nginx实现反向代理 实现反向代理需要准备两台Nginx服务器。一台Nginx服务器A&#xff0c;ip为 192.168.206.140&…

Linux下查找python路径

本地目前装了几个版本的python&#xff0c;这里记录下查找python路径的方法。 1&#xff1a;whereis命令 whereis python2&#xff1a;which命令 which python与whereis相似&#xff0c;但which会返回第一个找到的执行文件的位置。 3&#xff1a;find命令 find命令可以搜索系…

Power BI-云端报表定时刷新--ODBC、MySQL、Oracle等其他本地数据源的刷新(二)

ODBC数据源 一些小众的数据源无法直接连接&#xff0c;需要通过微软系统自带的应用“ODBC数据源”连接。 1.首次使用应安装对应数据库的ODBC驱动程序&#xff0c;Mysql的ODBC驱动需要手动安装 2.在web服务中进行数据源的配置 Mysql数据源 1.Powerbi与Gateway第一次连SQL…

❤️创意网页:创意视觉效果粒子循环的网页动画

✨博主&#xff1a;命运之光 &#x1f338;专栏&#xff1a;Python星辰秘典 &#x1f433;专栏&#xff1a;web开发&#xff08;简单好用又好看&#xff09; ❤️专栏&#xff1a;Java经典程序设计 ☀️博主的其他文章&#xff1a;点击进入博主的主页 前言&#xff1a;欢迎踏入…

【雕爷学编程】MicroPython动手做(15)——掌控板之AB按键2

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

【嵌入式Linux项目】基于Linux的全志H616开发板智能家居项目(语音控制、人脸识别、安卓APP和PC端QT客户端远程操控)有视频功能展示

目录 一、功能需求 二、开发环境 1、硬件&#xff1a; 2、软件&#xff1a; 3、引脚分配&#xff1a; 三、关键点 1、设计模式之工厂模式 2、wiringPi库下的相关硬件操作函数调用 3、语音模块的串口通信 4、线程 5、摄像头的实时监控和拍照功能 6、人脸识别 四、编…

❤️创意网页:炫酷的网页 - 创造华丽粒子动画

✨博主&#xff1a;命运之光 &#x1f338;专栏&#xff1a;Python星辰秘典 &#x1f433;专栏&#xff1a;web开发&#xff08;简单好用又好看&#xff09; ❤️专栏&#xff1a;Java经典程序设计 ☀️博主的其他文章&#xff1a;点击进入博主的主页 前言&#xff1a;欢迎踏入…

操作系统攻击:早期WindowsMS10-046漏洞

目录 概述 漏洞成因 利用过程 漏洞复现 漏洞修复 概述 本次介绍早期的windows高危漏洞——MS10_046_SHORTCUT_ICON_DLLLOADER &#xff0c; 该漏洞可以通过浏览器跳转网络资源的方式利用&#xff0c;结合xss攻击用户的系统 危险性极高。 漏洞成因 漏洞成因&#xff1a; m…

param.grad、requires_grad、grad_fn、grad/梯度为None?

基本概念 1&#xff09;is_leaf 叶子节点和非叶子节点的区别&#xff1a;计算图中的节点分为叶子节点和非叶子节点&#xff0c;叶子节点可以理解成没有其他tensor再利用它进行计算&#xff08;例如b a1&#xff0c;那么b需要a进行计算&#xff0c;那么a就不是叶子结点&…

服务器介绍

本文章转载与b战up主谈三国圈&#xff0c;仅用于学习讨论&#xff0c;如有侵权&#xff0c;请联系博主 机架型服务器 堆出同时服务百万人次机组 刀型服务器 服务器炸了 比如用户访问量暴增 超过机组的峰值处理能力&#xff0c;进而导致卡顿或炸服&#xff0c; 适合企业的塔式…

xilinx FPGA 除法器ip核(divider)的使用(VHDLVivado)

一、创建除法ip核 vivado的除法器ip核有三种类型&#xff0c;跟ISE相比多了一个LuMult类型&#xff0c;总结来说就是 LuMult&#xff1a;使用了DSP切片、块RAM和少量的FPGA逻辑原语&#xff08;寄存器和lut&#xff09;&#xff0c;所以和Radix2相比占用fpga资源更少&#xff…

CS_SAVEBITS 这个样式有什么作用?

简单来说&#xff0c;如果你在创建窗口的时候在窗口类中指定了 CS_SAVEBITS 标志&#xff0c;则窗口管理器会尝试保存此窗口所遮盖的区域的位图数据。 但是&#xff0c;这里比较关键的问题是&#xff1a;为什么要这样做&#xff1f;只有明白了这其中的原理&#xff0c;你才会在…

2023.07.13力扣6题

931. 下降路径最小和 给你一个 n x n 的 方形 整数数组 matrix &#xff0c;请你找出并返回通过 matrix 的下降路径 的 最小和 。 下降路径可以从第一行中的任何元素开始&#xff0c;并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多相隔一列&#xff08;即位…