SpringBoot使用MongoTemplate详解

1.pom.xml引入Jar包

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

2.MongoDbHelper封装

/**
 * MongoDB Operation class
 * @author HyoJung
 * @date 2024-03-05
 */
public class MongoDbHelper {
    @Autowired
    private MongoTemplate mongoTemplate;
    /**
     * Save Individual Objects
     *
     * @param t 实体类参数
     * @param <T> 实体类
     * @return
     */
    public <T> T save(T t) {
        return mongoTemplate.insert(t);
    }

    /**
     * Store the object to the specified collectionName
     * @param objectToSave
     * @param collectionName 类似SQL数据库的表名
     * @param <T>
     * @return
     */
    public <T> T save(T objectToSave, String collectionName){
        return mongoTemplate.insert(objectToSave,collectionName);
    }

    /**
     * 批量存储
     *
     * @param list
     * @param collectionName
     * @return
     */
    public <T> Collection<T> batchSave(Collection<T> list, String collectionName) {
        return mongoTemplate.insert(list,collectionName);
    }

    /**
     * Query Data
     *
     * @param query
     * @param tClass
     * @param <T>
     * @return
     */
    public <T> List<T> find(Query query, Class<T> tClass) {
        return mongoTemplate.find(query, tClass);
    }

    /**
     * Collection specified by query data
     *
     * @param query
     * @param tClass
     * @param <T>
     * @return
     */
    public <T> List<T> find(Query query, Class<T> tClass, String collectionName) {
        return mongoTemplate.find(query, tClass,collectionName);
    }

    /**
     * 分页查询
     * @param query query criteria
     * @param pageNum Current Page
     * @param pageSize Number of entries per page
     * @param sortField Sorted Field
     * @param sortType 1:asc;0:desc
     * @param tClass to class
     * @param collectionName collection name
     * @param <T>
     * @return
     */
    public <T> MongoPage findByPage(Query query,int pageNum,int pageSize,String sortField,int sortType, Class<T> tClass, String collectionName) {
        int count = (int) mongoTemplate.count(query, tClass, collectionName);
        if(sortType==1){
            query.with(Sort.by(Sort.Order.asc(sortField)));
        }else {
            query.with(Sort.by(Sort.Order.desc(sortField)));
        }
        //Set starting number
        query.skip((pageNum - 1) * pageSize);
        //Set the number of queries
        query.limit(pageSize);
        //Query the current page data set
        List<T> taskList = mongoTemplate.find(query, tClass,collectionName);
        int size=count % pageSize == 0 ? count / pageSize : count / pageSize + 1;
        MongoPage page=new MongoPage();
        page.setTotal(count);
        page.setSize(size);
        page.setData(taskList);
        return page;
    }

    /**
     * 查询前几条数据
     * @param query
     * @param limitNum 前几条
     * @param sortField 排序字段
     * @param sortType 0:倒序;1:正序
     * @param tClass
     * @param collectionName
     * @param <T>
     * @return
     */
    public <T> List<T> findTop(Query query,Integer limitNum,String sortField,int sortType, Class<T> tClass, String collectionName){
        if(sortType==1){
            query.with(Sort.by(Sort.Order.asc(sortField)));
        }else {
            query.with(Sort.by(Sort.Order.desc(sortField)));
        }
        query.limit(limitNum);
        return mongoTemplate.find(query, tClass,collectionName);
    }

    /**
     * 查询一条数据
     * @param query
     * @param sortField
     * @param sortType
     * @param tClass
     * @param collectionName
     * @param <T>
     * @return
     */
    public <T> List<T> findOne(Query query,String sortField,int sortType, Class<T> tClass, String collectionName){
        if(sortType==1){
            query.with(Sort.by(Sort.Order.asc(sortField)));
        }else {
            query.with(Sort.by(Sort.Order.desc(sortField)));
        }
        //Set the number of queries
        query.limit(1);
        //Query the current page data set
        List<T> taskList = mongoTemplate.find(query, tClass,collectionName);
        return taskList;
    }

    /**
     * Query All
     *
     * @param tClass
     * @param <T>
     * @return
     */
    public <T> List<T> findAll(Class<T> tClass) {
        return mongoTemplate.findAll(tClass);
    }

    /**
     * Query all specified collections
     *
     * @param tClass
     * @param collectionName
     * @param <T>
     * @return
     */
    public <T> List<T> findAll(Class<T> tClass,String collectionName) {
        return mongoTemplate.findAll(tClass,collectionName);
    }

    /**
     * create collection
     * @param collName
     * @param indexList
     * @return
     */
    public boolean createCollection(String collName, List<Map<String,Integer>> indexList){
        try {
            if (mongoTemplate.collectionExists(collName)) {
                return true;
            }
            //Index collection to be created
            List<IndexModel> indexModels = new ArrayList<>();
            for (Map<String, Integer> indexMap : indexList) {
                BasicDBObject index = new BasicDBObject();
                for (String key : indexMap.keySet()) {
                    index.put(key, indexMap.get(key));
                }
                indexModels.add(new IndexModel(index));
            }
            mongoTemplate.createCollection(collName).createIndexes(indexModels);
            return true;
        }catch (Exception e){
            return false;
        }
    }

    /**
     * Update the first result set returned by the query
     * @param query
     * @param update
     * @param collectionName
     * @return
     */
    public boolean updateFirst(Query query, Update update, String collectionName){
        try {
            mongoTemplate.updateFirst(query, update, collectionName);
            return true;
        }catch (Exception e){
            return false;
        }
    }

    /**
     * Update all returned result sets
     * @param query
     * @param update
     * @param collectionName
     * @return
     */
    public boolean updateMulti(Query query, Update update, String collectionName){
        try {
            mongoTemplate.updateMulti(query, update, collectionName);
            return true;
        }catch (Exception e){
            return false;
        }
    }

    /**
     * If the update object does not exist, add it
     * @param query
     * @param update
     * @param tClass
     * @param <T>
     * @param collectionName
     * @return
     */
    public <T> boolean upsert(Query query, Update update, Class<T> tClass,String collectionName){
        try {
            mongoTemplate.upsert(query, update, tClass,collectionName);
            return true;
        }catch (Exception e){
            return false;
        }
    }

    /**
     * 存在则更新不存在则创建
     * @param query
     * @param update
     * @param collectionName
     * @return
     */
    public boolean upsert(Query query, Update update, String collectionName){
        try {
            mongoTemplate.upsert(query, update,collectionName);
            return true;
        }catch (Exception e){
            return false;
        }
    }

    /**
     * 汇总查询
     * @param aggregation
     * @param tClass
     * @param collectionName
     * @param <T>
     * @return
     */
    public <T> List<T> groupQuery(Aggregation aggregation,Class<T> tClass,String collectionName){
        AggregationResults<T> maps = mongoTemplate.aggregate(aggregation, collectionName, tClass);
        return maps.getMappedResults();
    }

    /**
     * 查总条数
     * @param query
     * @param collectionName
     * @return
     */
    public long queryCount(Query query, String collectionName){
        return mongoTemplate.count(query, collectionName);
    }

    /**
     * @description: 删除消息数据
     * @param query
     * @param collectionName
     **/
    public long delete(Query query,String collectionName) {
        return this.mongoTemplate.remove(query,collectionName).getDeletedCount();
    }
}

MongoPage实体类

/**
 * MongoDB paged query returns result set
 * @author HyoJung
 * @date 2024-03-05
 */
@Data
public class MongoPage {
    /**
     * Total number of data
     */
    private Integer total;

    /**
     * Page count
     */
    private Integer size;

    /**
     * Data result set per page
     */
    private Object data;
}

3.MongoDB命令说明

3.1.Insert默认集合插入

mongoDB命令:

db.comment.insert({_id:"4",nickname:"ww",content:"这位是谁啊",userId:3,createTime:……})

mongoTemplate对应的方法

mongoTemplate.insert();

我们常用的方法是:

1.将一个实体对象插入指定表中

/**
 * 将一个实体对象存储到指定的表中
 * @param objectToSave
 * @param collectionName 类似SQL数据库的表名
 * @param <T>
 * @return
 */
public <T> T insert(T objectToSave, String collectionName){
    return mongoTemplate.insert(objectToSave,collectionName);
}

2.将一个List批量插入指定表中

/**
 * 将一个集合插入指定的表中
 *
 * @param list 对象集合
 * @param collectionName 表名
 * @return
 */
public <T> Collection<T> batchInsert(Collection<T> list, String collectionName) {
    return mongoTemplate.insert(list,collectionName);
}

3.2.save默认集合插入

mongoDB 命令:

db.comment.save({})

使用save进行插入时会根据id进行判断,如果要插入数据中的id在数据库存在,则会将旧的数据覆盖,如果不存在则插入数据。

mongoTemplate对应的方法

mongoTemplate.save();

方法封装:

/**
 * 将一个实体对象存储到指定的表中
 * @param objectToSave
 * @param collectionName 类似SQL数据库的表名
 * @param <T>
 * @return
 */
public <T> T save(T objectToSave, String collectionName){
    return mongoTemplate.save(objectToSave,collectionName);
}

3.3.insert与save的区别

在MongoTemplate中,save()和insert()方法有以下区别:

save()方法:save()方法用于插入新文档或更新现有文档。如果要保存的文档没有id字段,将插入一个新文档。如果文档具有id字段,MongoDB将尝试使用匹配的id值更新文档。如果找不到具有匹配id的文档,则插入一个新文档。

insert()方法:insert()方法用于向集合中插入新文档。如果要插入的文档已经具有id字段,并且集合中已经存在具有相同id值的文档,则会抛出异常。这确保插入的文档具有唯一的_id值。

总结:save()方法用于插入和更新操作,而insert()方法专门用于插入新文档,并确保_id字段的唯一性。

3.4.修改数据

3.4.1.修改符合条件的第一条数据

mongoDB 命令:

db.comment.update({},{})

mongoTemplate对应的方法

mongoTemplate.updateFirst();

方法封装:

/**
 * 修改符合条件的第一条数据
 * @param query
 * @param update
 * @param collectionName
 * @return
 */
public boolean updateFirst(Query query, Update update, String collectionName){
    try {
        mongoTemplate.updateFirst(query, update, collectionName);
        return true;
    }catch (Exception e){
        return false;
    }
}

3.4.2.修改符合条件的全部数据

mongoDB 命令:

db.comment.update({},{},{multi:true})

mongoTemplate对应的方法

mongoTemplate.updateMulti();

方法封装:

/**
 * 修改符合条件的全部数据
 * @param query
 * @param update
 * @param collectionName
 * @return
 */
public boolean updateMulti(Query query, Update update, String collectionName){
    try {
        mongoTemplate.updateMulti(query, update, collectionName);
        return true;
    }catch (Exception e){
        return false;
    }
}

mongoTemplate对应的方法的返回结果是UpdateResult,也可以通过此结果返回状态进行更深度的判断是否修改成功。

3.5.删除数据

3.5.1.删除满足条件的所有文档

mongoDB 命令:

db.comment.remove({})

mongoTemplate对应的方法:

mongoTemplate.remove();

方法封装:

/**
 * @description: 删除满足条件的所有文档
 * @param query
 * @param collectionName
 **/
public long delete(Query query,String collectionName) {
    return this.mongoTemplate.remove(query,collectionName).getDeletedCount();
}

如果query条件为空时则删除当前集合所有的记录。

方法封装:

/**
 * @description: 删除满足条件的所有文档
 * @param collectionName
 **/
public long delete(String collectionName) {
    return this.mongoTemplate.remove(new Query(),collectionName).getDeletedCount();
}

3.5.2.删除满足条件的单个文档并返回当前删除的数据

mongoTemplate对应的方法

mongoTemplate.findAndRemove();

3.5.3.删除满足条件的所有文档并返回当前删除的数据集合

mongoTemplate对应的方法

mongoTemplate.findAllAndRemove();

3.6.查询数据

3.6.1.查询全部文档

mongoDB 命令:

db.comment.find()

mongoTemplate对应的方法

mongoTemplate.findAll();

3.6.2.查询指定id的文档

mongoDB 命令:

db.comment.find({_id:"id"})

mongoTemplate对应的方法

mongoTemplate.findById();

3.6.3.查询满足条件的一条文档

mongoDB 命令:

db.comment.findOne({})

mongoTemplate对应的方法

mongoTemplate.findOne();

3.6.4.查询满足条件的所有文档

mongoDB 命令:

db.comment.find({})

mongoTemplate对应的方法

mongoTemplate.find();

方法封装:

/**
 * 查询指定文档下符合条件的记录
 *
 * @param query
 * @param tClass
 * @param <T>
 * @return
 */
public <T> List<T> find(Query query, Class<T> tClass, String collectionName) {
    return mongoTemplate.find(query, tClass,collectionName);
}

3.6.5.分页查询方法封装

/**
 * Pagination query
 * @param query query criteria
 * @param pageNum Current Page
 * @param pageSize Number of entries per page
 * @param sortField Sorted Field
 * @param sortType 1:asc;0:desc
 * @param tClass to class
 * @param collectionName collection name
 * @param <T>
 * @return
 */
public <T> MongoPage findByPage(Query query,int pageNum,int pageSize,String sortField,int sortType, Class<T> tClass, String collectionName) {
    int count = (int) mongoTemplate.count(query, tClass, collectionName);
    if(sortType==1){
        query.with(Sort.by(Sort.Order.asc(sortField)));
    }else {
        query.with(Sort.by(Sort.Order.desc(sortField)));
    }
    //Set starting number
    query.skip((pageNum - 1) * pageSize);
    //Set the number of queries
    query.limit(pageSize);
    //Query the current page data set
    List<T> taskList = mongoTemplate.find(query, tClass,collectionName);
    int size=count % pageSize == 0 ? count / pageSize : count / pageSize + 1;
    MongoPage page=new MongoPage();
    page.setTotal(count);
    page.setSize(size);
    page.setData(taskList);
    return page;
}

3.6.6.查询符合条件的前几条数据

/**
 * 查询前几条数据
 * @param query
 * @param limitNum 前几条
 * @param sortField 排序字段
 * @param sortType 0:倒序;1:正序
 * @param tClass
 * @param collectionName
 * @param <T>
 * @return
 */
public <T> List<T> findTop(Query query,Integer limitNum,String sortField,int sortType, Class<T> tClass, String collectionName){
    if(sortType==1){
        query.with(Sort.by(Sort.Order.asc(sortField)));
    }else {
        query.with(Sort.by(Sort.Order.desc(sortField)));
    }
    query.limit(limitNum);
    return mongoTemplate.find(query, tClass,collectionName);
}

3.6.7.查询符合条件的总条数

/**
 * 查总条数
 * @param query
 * @param collectionName
 * @return
 */
public long queryCount(Query query, String collectionName){
    return mongoTemplate.count(query, collectionName);
}

3.6.8.Query的更多用法

is查询

Query query = new Query(); // where...is... 相当于 where ? = ? 
query.addCriteria(Criteria.where("数据库字段名").is("你的参数"));

in查询

ArrayList<String> list = new ArrayList<>();
// list代表你的数据
Query query = Query.query(Criteria.where("数据库字段").in(list));

字符模糊查询

Query query = Query.query(Criteria.where("name").regex("小"));

查询范围

//此示例是查询指定terminalId某个时间段内的数据
Query query = new Query(Criteria.where("terminalId").is(terminalId).and("timestamp").gte(startTimestamp).lte(endTimestamp));

查询指定字段

//查询指定terminalId某个时间段内的数据后,返回指定的字段fields(List<String>)
Query query = new Query(Criteria.where("terminalId").is(terminalId).and("timestamp").gte(startTimestamp).lte(endTimestamp));
Field findFields = query.fields();
if (!CollectionUtils.isEmpty(fields)) {
    fields.forEach(findFields::include);
}

指定字段不返回

query.fields().exclude("field");

3.7.创建一个collection

/**
 * create collection
 * @param collName
 * @param indexList
 * @return
 */
public boolean createCollection(String collName, List<Map<String,Integer>> indexList){
    try {
        if (mongoTemplate.collectionExists(collName)) {
            return true;
        }
        //Index collection to be created
        List<IndexModel> indexModels = new ArrayList<>();
        for (Map<String, Integer> indexMap : indexList) {
            BasicDBObject index = new BasicDBObject();
            for (String key : indexMap.keySet()) {
                index.put(key, indexMap.get(key));
            }
            indexModels.add(new IndexModel(index));
        }
        mongoTemplate.createCollection(collName).createIndexes(indexModels);
        return true;
    }catch (Exception e){
        return false;
    }
}

4.术语介绍

在MongoDB中,有别于常见的关系型数据库,一些术语略有不同,如下表所示:

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

37.云原生之springcloud+k8s+GitOps+istio+安全实践

云原生专栏大纲 文章目录 准备工作项目结构介绍配置安全测试ConfigMapSecret使用Secret中数据的方式Deployment使用Secret配置Secret加密 kustomize部署清单ConfigMap改造SecretSealedSecretDeployment改造Serviceistio相关资源DestinationRuleGatewayVirtualServiceServiceAc…

(3)(3.2) MAVLink2数据包签名(安全)

文章目录 前言 1 配置 2 使用 3 MAVLink协议说明 前言 ArduPilot 和任务计划器能够通过使用加密密钥添加数据包签名&#xff0c;为空中 MAVLink 传输增加安全性。这并不加密数据&#xff0c;只是控制自动驾驶仪是否响应 MAVLink 命令。 当自动驾驶仪处于激活状态时&#x…

未来已来!AI大模型引领科技革命

未来已来&#xff01;AI大模型正以惊人的速度引领着科技革命。随着科技的发展&#xff0c;人工智能在各个领域展现出了非凡的能力和潜力&#xff0c;大模型更是成为了科技领域的明星。从自然语言处理到图像识别&#xff0c;从智能推荐到语音识别&#xff0c;大模型的应用正在改…

python自学3

第一节第六章 数据的列表 列表也是支持嵌套的 列表的下标索引 反向也可以 嵌套也可以 列表的常用操作 什么是列表的方法 学习到的第一个方法&#xff0c;index&#xff0c;查询元素在列表中的下标索引值 index查询方法 修改表功能的方法 插入方法 追加元素 单个元素追加 多…

如何应对IT服务交付中的问题?

如何应对IT服务交付中的问题&#xff1f; 按需交付服务的挑战IT服务体系的复杂性恶性循环的形成学会洞察的重要性书籍简介参与方式 按需交付服务的挑战 一致性、可靠性、安全性、隐私性和成本效益的平衡&#xff1a;成功的按需交付服务需要满足这些要求&#xff0c;这需要服务…

2024年UI排版风格解析,经典模板一键复用!

在UI设计工作中&#xff0c;如何保证版式设计的“美观 合理”是经常需要考虑问题。经过了多年的设计工作后&#xff0c;笔者发现新人设计师的尤其容易陷入对流行趋势的简单模仿&#xff0c;缺失对排版本身的逻辑性认知。在这篇文章中&#xff0c;笔者将盘点10个经典UI排版案例…

PCL中的点云分割模型的部分常用参数含义

PCL中的SacModel类别常用参数含义 1、SACMODEL_PLANE2、SACMODEL_LINE&#xff08;三维直线&#xff09;3、SACMODEL_CIRCLE2D&#xff08;二维圆&#xff09;4、SACMODEL_CIRCLE3D&#xff08;三维圆&#xff09;5、SACMODEL_SPHERE&#xff08;球&#xff09;6、SACMODEL_CYL…

Jenkins 将shell脚本启动方式修改为bash

platform"arm x86" if [[ "$platform" ~ "arm" ]] thenecho "arm" fi最近在调试Jenkins实现的一些功能&#xff0c;发现在本地可以运行的脚本内容到了Jenkins里面就没办法运行了&#xff0c;不是提示unexpected operator就是提示[[ : …

Uni-ControlNet: All-in-One Control toText-to-Image Diffusion Models——【论文笔记】

本文发表于NeurIPS 2023 项目官网&#xff1a;Uni-ControlNet: All-in-One Control to Text-to-Image Diffusion Models 一、Introduction 近两年来&#xff0c;扩散模型在图像合成任务中表现优异&#xff0c;尤其是文本到图像&#xff08;T2I&#xff09;扩散模型已成为合成高…

WebGIS开发0基础必看教程:地图显示——根据地理范围换算出瓦片行列号

2.影像金字塔简介 我们之前反复提到了影像金字塔这个概念&#xff0c;但是没有对其做一个大概的介绍&#xff0c;这里我将这个概念补充一下。 2.1 为什么要出现影像金字塔这个概念 现在&#xff0c;我假设我们的服务器上有一个1G的影像&#xff0c;需要将其在前端进行显示。…

2024全网最全Excel函数与公式应用

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 引言 Excel是一款广泛应用于商业、教育和个人…

hnust 湖南科技大学 2022 数据挖掘课设 完整代码+报告+图源文件+指导书

hnust 湖南科技大学 2022 数据挖掘课设 完整代码报告图源文件指导书 目录 实验一 Apriori算法设计与应用 - 1 - 一、 背景介绍 - 1 - 二、 实验内容 - 1 - 三、 实验结果与分析 - 2 - 四、 小结与心得体会 - 3 - 实验二 KNN算法设计与应用 - 4 - 一、 背景介绍 - 4 - 二、 实…

头条小程序DIY源码系统 带完整的安装代码包以及搭建部署教程

在过去几年中&#xff0c;小程序市场经历了飞速的发展&#xff0c;各种小程序平台如雨后春笋般涌现。作为其中的佼佼者&#xff0c;头条小程序凭借其强大的用户基础和完善的生态体系&#xff0c;吸引了众多开发者的关注。然而&#xff0c;对于许多初学者和中小企业而言&#xf…

C语言qsort函数介绍

前言 学到了函数指针&#xff0c;那这篇博客我们可以根据函数指针&#xff0c;了解一个函数qsort的应用与模拟实现 欢迎关注个人主页&#xff1a;小张同学zkf 若有疑问 评论区见 目录 1.回调函数 2.qsort函数使用 3.qsort模拟实现 1.回调函数 讲这个东西之前我们来认识一下…

春日特惠,爱基百客限时放送,开启您的学术新篇章!

春回大地&#xff0c;万物复苏&#xff0c; 正是探索未知、启发新思的最佳时节。 在这个充满生机的季节里&#xff0c; 我们推出了春季大促活动&#xff0c; 旨在助力每一位科研工作者在新的一年里实现更多突破。 让我们一起迎接科研人的春天&#xff0c; 开启智慧的花朵…

基本设计模式

单例模式 ES5 function Duck1(name:string){this.namenamethis.instancenull }Duck1.prototype.getNamefunction(){console.log(this.name) }Duck1.getInstancefunction(name:string){if(!this.instance){this.instance new Duck1(name)} } const aDuck1.getInstance(a) const…

Jetpack Compose: Hello Android

Jetpack Compose 是一个现代化的工具包&#xff0c;用于使用声明式方法构建原生 Android UI。在本博文中&#xff0c;我们将深入了解一个基本的 “Hello Android” 示例&#xff0c;以帮助您开始使用 Jetpack Compose。我们将探讨所提供代码片段中使用的函数和注解。 入门 在…

C++ //练习 10.31 修改前一题的程序,使其只打印不重复的元素。你的程序应使用unique_copy(参见10.4.1节,第359页)。

C Primer&#xff08;第5版&#xff09; 练习 10.31 练习 10.31 修改前一题的程序&#xff0c;使其只打印不重复的元素。你的程序应使用unique_copy&#xff08;参见10.4.1节&#xff0c;第359页&#xff09;。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09…

基于ERNIR3.0的文本多分类

还在用BERT做文本分类&#xff1f;分享一套基于预训练模型ERNIR3.0的文本多分类全流程实例【文本分类】_ernir 文本分类-CSDN博客 /usr/bin/python3 -m pip install --upgrade pip python3-c"import platform;print(platform.architecture()[0]);print(platform.machine…

深度学习500问——Chapter02:机器学习基础(3)

文章目录 2.10 主成分分析&#xff08;PCA&#xff09; 2.10.1 主成分分析&#xff08;PCA&#xff09;思想总结 2.10.2 图解PCA核心思想 2.10.3 PCA算法推理 2.10.4 PCA算法流程总结 2.10.5 PCA算法主要优缺点 2.10.6 降维的必要性及目的 2.10.7 KPCA与PCA的区别 2.11 模型评估…