Node.js入门指南(五)

目录

MongoDB

介绍

下载与启动

命令行交互

Mongoose

代码模块化

图形化管理工具


hello,大家好!上一篇文章我们介绍了express框架,这一篇文字主要介绍MongoDB。来对数据进行存储以及操作。

MongoDB

介绍

各位小伙伴应该多多少少都有接触到数据库,比如MySQL、SqlServer或者Oracle等。同样的MongoDB也是一种数据库,相比于其他的数据库,它操作语法与 JavaScript 类似,容易上手,学习成本低。MongoDB 是一个基于分布式文件存储的数据库,官方地址 。

Mongodb 中有三个重要概念需要掌握:

1️⃣数据库(database) 数据库是一个数据仓库,数据库服务下可以创建很多数据库,数据库中可以存放很多集合。

2️⃣集合(collection) 集合类似于 JS 中的数组,在集合中可以存放很多文档。

3️⃣文档(document) 文档是数据库中的最小单位,类似于 JS 中的对象。

{"accounts": [{"id": "3-YLju5f3","title": "买电脑","time": "2023-02-08","type": "-1","account": "5500","remarks": "为了上网课"},{"id": "mRQiD4s3K","title": "发工资","time": "2023-02-19","type": "1","account": "4396","remarks": "终于发工资啦!~~"}],"users":[{"id": 1,"name": "zhangsan","age":18}]
}

大家可以通过 JSON 文件来理解 Mongodb 中的概念 一个JSON 文件 好比是一个数据库 ,一个 Mongodb 服务下可以有 N 个数据库, JSON 文件中的 一级属性的数组值好比是集合, 数组中的对象好比是文档,对象中的属性有时也称之为字段。

下载与启动

那我们一起来安装MongoDB吧!建议选择 zip 类型, 通用性更强。配置步骤如下:

1️⃣将压缩包移动到 C:\Program Files 下,然后解压。

2️⃣创建 C:\data\db 目录,mongodb 会将数据默认保存在这个文件夹。

3️⃣将 bin 目录配置到环境变量 Path 中,为了方便后续方便使用 mongod 命令。

4️⃣以 mongodb 中 bin 目录作为工作目录,启动命令行,运行命令 mongod

若看到的 waiting for connections 则表明服务 已经启动成功。

5️⃣再以 mongodb 中 bin 目录作为工作目录,启动命令行,使用 mongo 命令连接本机的 mongodb 服务。

注意:千万不要选中服务端窗口的内容 ,选中会停止服务,可以敲回车取消选中。

命令行交互

再来介绍一下,MongoDB中的一些命令行交互,包括数据库命令,集合的相关命令以及文档的相关命令。不过在后续用的不多,因此简单体验一下即可。

数据库命令功能
show dbs
显示所有的数据库
use 数据库名
切换到指定的数据库,如果数据库不存在会自动创建数据库
db
显示当前所在的数据库
use 库名
db.dropDatabase()
删除当前数据库
集合命令功能
db . createCollection ( '集合名称' )
创建集合
show collections
显示当前数据库中的所有集合
db. 集合名 .drop()
删除某个集合
db. 集合名 .renameCollection('newName')
重命名集合
文档命令功能
db . 集合名 . insert ( 文档对象 );
插入文档
db. 集合名 .find( 查询条件 )
查询文档
db . 集合名 . update ( 查询条件 , 新的文档 )
db . 集合名 . update ({ name : ' 张三 ' },{ $set :{ age : 19 }})
更新文档
db. 集合名 .remove( 查询条件 )
删除文档

在插入文档对象之后, mongodb会为该对象自动生成的唯一编号,用来唯一标识文档。

Mongoose

我们在前介绍命令行交互的时候都是在命令行窗口中进行与mongodb数据库进行交互,会比较麻烦,因此就引入了Mongoose,它是一个对象文档模型库,官网 http://www.mongoosejs.net/,方便使用代码操作 mongodb 数据库。接下来我们来使用mongoose来进行连接数据库以及进行相应的操作。

首先我们需要先对一个文件夹进行npm init初始化,因此mongoose也是一个包。然后使用npm i mongoose来进行下载Mongoose。然后导入mongoose,并连接mongodb服务,包括域名端口号,端口号默认是27017可写可不写,然后加上数据库的名称。(若数据库不存在,它会自动创建对应的数据库)。然后设置回调来提示连接的状态。

//导入mongoose
const mongoose=require('mongoose');
//连接mongodb服务
mongoose.connect('mongodb://127.0.0.1:27017/bilibili');
//设置连接成功的回调
mongoose.connection.once('open',()=>{console.log('连接成功');});
//设置连接错误的回调
mongoose.connection.on('error',()=>{console.log('连接失败');});
//设置连接关闭的回调
mongoose.connection.on('close',()=>{console.log('连接关闭');});
//关闭mongodb连接
setTimeout(()=>{mongoose.disconnect();
},2000)

数据库连接成功之后,我们使用mongoose向数据库插入文档。首先需要规定文档的结果对象,对象的属性名以及它对应的数值类型,截止创建文档模型对象,最后插入文档。使用.then()以及.catch接受成功以及失败的结果。最后可以use bilibili -> show collections -> db.books.find()。看数据库是否添加成功。插入的文档(对象)会默认添加两个属性,一个为_id,用于唯一表示,一个为_v,表示版本号。

//导入mongoose
const mongoose=require('mongoose');
//连接mongodb服务
mongoose.connect('mongodb://127.0.0.1:27017/bilibili');
//设置连接成功的回调
mongoose.connection.once('open',()=>{console.log('连接成功');//创建文档结构对象let BookSchema=new mongoose.Schema({title:String,author:String,price:Number});//创建文档模型对象let BookModel=mongoose.model('book',BookSchema);//插入文档BookModel.create({title:'西游记',author:'吴承恩',price:19.9}).then(data=>{console.log(data);mongoose.disconnect();}).catch(err=>{console.log(err);})});
//设置连接错误的回调
mongoose.connection.on('error',()=>{console.log('连接失败');});
//设置连接关闭的回调
mongoose.connection.on('close',()=>{console.log('连接关闭');});

接下来介绍一下mongoose的字段类型,上面的例子我们已经使用了String以及Number两种数据类型了。除了上面的两种还有以下的几种数据类型:

类型
描述
String
字符串
Number数字
Boolean布尔值
Array数组,也可以使用 [] 来标识
Date日期
BufferBuffer 对象
Mixed任意类型,需要使用 mongoose.Schema.Types.Mixed 指定
ObjectId对象 ID,需要使用 mongoose.Schema.Types.ObjectId 指定
Decimal128高精度数字,需要使用 mongoose.Schema.Types.Decimal128 指定

Buffer类型主要是接收一些文件的,比如图片视频等。但是一般这些都放在静态资源文件中,比较少地存放在数据库中。一般数据库存放的是对应的文件地址,再通过地址找到对应的文件。这样效率会提高。其他的类型可以自行操作,都比较容易理解。

在我们插入文档数据时,我们还可以设置相应的约束,即字段值验证,Mongoose 有一些内建验证器,可以对字段值进行验证。

required:必填项。该属性如设置为true,是意味这对应的值不能为空。default: 默认值,但某个元素添加的时候没有设置对应的值,那么它就会使用默认的字,若添加时有值,它会使用添加的值。enum: [ ] ,表示枚举值,设置的值必须是数组中的某一个值,不然会报错。unique:表示唯一值,某个属性的值只能添加一次,后面再添加会重复,添加失败。不过在使用该属性时要确保自己的集合是新创建的才有效果。

接下来使用mongoose来实现文档的删除,删除可以是删除一条数据,也可以是实现批量地删除数据。首先我们先向数据库批量地插入数据,然后再有数据来给我们进行删除操作,插入部分演示如何实现批量地插入。上面代码只实现了单条数据的插入。

//1. 安装 mongoose
//2. 导入 mongoose
const mongoose = require('mongoose');//设置 strictQuery 为 true
mongoose.set('strictQuery', true);//3. 连接 mongodb 服务                        数据库的名称
mongoose.connect('mongodb://127.0.0.1:27017/bilibili');//4. 设置回调
// 设置连接成功的回调  once 一次   事件回调函数只执行一次
mongoose.connection.once('open', () => {//5. 创建文档的结构对象//设置集合中文档的属性以及属性值的类型let BookSchema = new mongoose.Schema({name: String,author: String,price: Number,is_hot: Boolean});//6. 创建模型对象  对文档操作的封装对象let BookModel = mongoose.model('novel', BookSchema);//7. 新增BookModel.insertMany([{name: '西游记',author: '吴承恩',price: 19.9,is_hot: true}, {name: '红楼梦',author: '曹雪芹',price: 29.9,is_hot: true}, {name: '三国演义',author: '罗贯中',price: 25.9,is_hot: true}, {name: '水浒传',author: '施耐庵',price: 20.9,is_hot: true}, {name: '活着',author: '余华',price: 19.9,is_hot: true}, {name: '狂飙',author: '徐纪周',price: 68,is_hot: true}, {name: '大魏能臣',author: '黑男爵',price: 9.9,is_hot: false},{name: '知北游',author: '洛水',price: 59,is_hot: false},{name: '道君',author: '跃千愁',price: 59,is_hot: false},{name: '七煞碑',author: '游泳的猫',price: 29,is_hot: false},{name: '独游',author: '酒精过敏',price: 15,is_hot: false},{name: '大泼猴',author: '甲鱼不是龟',price: 26,is_hot: false},{name: '黑暗王者',author: '古羲',price: 39,is_hot: false},{name: '不二大道',author: '文刀手予',price: 89,is_hot: false},{name: '大泼猴',author: '甲鱼不是龟',price: 59,is_hot: false},{name: '长安的荔枝',author: '马伯庸',price: 45,is_hot: true},{name: '命运',author: '蔡崇达',price: 59.8,is_hot: true},{name: '如雪如山',author: '张天翼',price: 58,is_hot: true},{name: '三体',author: '刘慈欣',price: 23,is_hot: true},{name: '秋园',author: '杨本芬',price: 38,is_hot: true},{name: '百年孤独',author: '范晔',price: 39.5,is_hot: true},{name: '在细雨中呼喊',author: '余华',price: 25,is_hot: true},]).then(data=>{console.log(data);mongoose.disconnect();}).catch(err=>{console.log(err);});});// 设置连接错误的回调
mongoose.connection.on('error', () => {console.log('连接失败');
});//设置连接关闭的回调
mongoose.connection.on('close', () => {console.log('连接关闭');
});
//1. 安装 mongoose
//2. 导入 mongoose
const mongoose = require('mongoose');//设置 strictQuery 为 true
mongoose.set('strictQuery', true);//3. 连接 mongodb 服务                        数据库的名称
mongoose.connect('mongodb://127.0.0.1:27017/bilibili');//4. 设置回调
// 设置连接成功的回调  once 一次   事件回调函数只执行一次
mongoose.connection.once('open', () => {//5. 创建文档的结构对象//设置集合中文档的属性以及属性值的类型let BookSchema = new mongoose.Schema({name: String,author: String,price: Number,is_hot: Boolean});//6. 创建模型对象  对文档操作的封装对象let BookModel = mongoose.model('novel', BookSchema);//7.删除一条数据BookModel.deleteOne({_id:'6564996cdf9f7cab75d5e263'}).then(data=>{console.log(data);}).catch(err=>{console.log(err);})//批量删除
BookModel.deleteMany({is_hot:false}).then(data=>{console.log(data);}).catch(err=>{console.log(err);})});// 设置连接错误的回调
mongoose.connection.on('error', () => {console.log('连接失败');
});//设置连接关闭的回调
mongoose.connection.on('close', () => {console.log('连接关闭');
});

介绍了新增以及删除,接下来介绍如何实现数据的更新以及查询操作。数据的更新同样包括单条数据的更新以及数据的批量更新。更新的方法需要接受一个查询的条件以及需要修改的内容。

  //7.更新一条数据BookModel.updateOne({name:'红楼梦'},{price:9.9}).then(data=>{console.log(data);}).catch(err=>{console.log(err);})//批量更新
BookModel.updateMany({author:'余华'},{is_hot:false}).then(data=>{console.log(data);}).catch(err=>{console.log(err);})

查询同样可以单条查询以及批量查询,还可以通过id来进行查询。当批量查询不传入参数时,会返回所有的数据。

//更新一条数据BookModel.findOne({name:'狂飙'}).then(data=>{console.log(data);}).catch(err=>{console.log(err);})
//根据 id 查询数据
BookModel.findById('6564996cdf9f7cab75d5e265').then(data=>{console.log(data);}).catch(err=>{console.log(err);})
//批量查询带条件BookModel.find({author:'余华'}).then(data=>{console.log(data);}).catch(err=>{console.log(err);})
//批量查询不带条件
BookModel.find().then(data=>{console.log(data);}).catch(err=>{console.log(err);})

当我们的查询不是简单的查询而是需要更加复杂的条件时,我们就需要使用到运算符,逻辑运算以及正则来进行条件的控制。

条件写法
>$gt
<$lt
>=$gte
<=$lte
!==$ne
$or
$and
正则 模糊查询
/要匹配的字符串/ 
//价格小于20的图书BookModel.find({price:{$lt:20}}).then(data=>{console.log(data);}).catch(err=>{console.log(err);})//曹雪芹或者余华的书
BookModel.find({$or:[{author:'曹雪芹'},{author:'余华'}]}).then(data=>{console.log(data);}).catch(err=>{console.log(err);})//价格大于30 且小于70
BookModel.find({$and:[{price:{$gt:30}},{price:{$lt:70}}]}).then(data=>{console.log(data);}).catch(err=>{console.log(err);})//正则,搜素带有三的书名
BookModel.find({name:/三/}).then(data=>{console.log(data);}).catch(err=>{console.log(err);})BookModel.find({name:new RegExp('三')}).then(data=>{console.log(data);}).catch(err=>{console.log(err);})

对于我们查询出来的数据并不都是我们真正想要的效果,因此我们可以对数据进行个性化读取。那下面以字段筛选、数据排序以及数据截取三种方式来进行介绍。

//设置字段 0:不要的字段  1:要的字段BookModel.find().select({name:1,author:1,_id:0}).exec().then(data=>{console.log(data);}).catch(err=>{console.log(err);})//数据排序 1:升序  -1:倒序
BookModel.find().select({name:1,price:1,_id:0}).sort({price:1}).exec().then(data=>{console.log(data);}).catch(err=>{console.log(err);})//数据截取 skip 跳过 limit 限定
BookModel.find().select({name:1,price:1,_id:0}).sort({price:1}).skip(3).limit(3).exec().then(data=>{console.log(data);}).catch(err=>{console.log(err);})

代码模块化

在实际的项目开发中,需要对代码进行模块化,让后期的维护更加地方便。思路就是将相同的可复用的代码单独地放置在一个文件中,并对其进行暴露,在需要用到的地方进行引入使用。将导入mongoose,连接mongodb服务,设置连接成功,失败以及关闭的回调,单独地放置在一个文件中。

module.exports = function (success, error) {//导入配置文件const {DBHOST,DBPOST,DBNAME}=require('../config/config');//导入mongooseconst mongoose = require('mongoose');//连接mongodb服务mongoose.connect(`mongodb://${DBHOST}:${DBPOST}/${DBNAME}`);mongoose.connection.once('open', () => {success();})//设置连接错误的回调mongoose.connection.on('error', () => {error();});//设置连接关闭的回调mongoose.connection.on('close', () => {console.log('连接关闭');});
}

创建文档结构对象,创建文档模型对象也单独地放置在一个文件中。

const mongoose=require('mongoose');
//创建文档结构对象
let BookSchema = new mongoose.Schema({title: String,author: String,price: Number
});
//创建文档模型对象
let BookModel = mongoose.model('book', BookSchema);
//暴露模型对象
module.exports=BookModel;

同时也可以将连接服务的地址单独地放置在一个文件中,后续只需要修改该文件即可修改相应的域名端口号以及数据库名。

module.exports={DBHOST:'127.0.0.1',DBPOST:27017,DBNAME:'bilibili'
}

主文件进行导入即可。

//导入db文件
const db=require('./db/db');
//导入BookModel
const BookModel = require('./models/BookModel');db(()=>{//插入文档BookModel.create({title:'西游记',author:'吴承恩',price:92}).then(data=>{console.log(data);// mongoose.disconnect();}).catch(err=>{console.log(err);})},()=>{console.log('连接失败')
})

图形化管理工具

我们可以使用图形化的管理工具来对 Mongodb 进行交互,不需要再通过命令的方式来检查自己操作的数据是否生效,主要可以使用以下的两个工具,对应的下载地址如下:

Robo 3T 免费 https://github.com/Studio3T/robomongo/releases

Navicat 收费 https://www.navicat.com.cn/​​​​​​​

好啦,本文就先到这啦!感谢阅读,持续更新~~

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

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

相关文章

uniapp基础-教程之HBuilderX基础常识篇03

该内容为了大家更好的理解&#xff0c;将每个页面进行分离&#xff0c;单独创建项目&#xff0c;如在index中之写只写了一个搜索框&#xff0c;将其他页面分别放在HBuilderX目录中的components中&#xff0c;没有的可自行创建。 然后在components中创建轮播图新建一个swiper.v…

正则化与正则剪枝

写在前面&#xff1a;本博客仅作记录学习之用&#xff0c;部分图片来自网络&#xff0c;如需引用请注明出处&#xff0c;同时如有侵犯您的权益&#xff0c;请联系删除&#xff01; 文章目录 引言正则化为什么会过拟合拉格朗日与正则化梯度衰减与正则化 应用解决过拟合网络剪枝 …

Linux篇:文件管理

一、共识原理&#xff1a; 1. 文件内容属性&#xff0c;内容与属性都是数据&#xff0c;都要在磁盘中保存。 2. 文件分为打开的文件和没打开的文件。 3. 研究打开的文件&#xff1a;本质是研究进程和文件的关系&#xff0c;因为是进程负责打开文件。 4. 没打开的文件在存储介质…

红黑树(万字图文详解)

红黑树 1. 红黑树的概念2. 红黑树的性质3. 红黑树节点的定义4. 红黑树结构5. 红黑树的插入操作5.1 按照二叉搜索的树规则插入新节点5.2 检测新节点插入后&#xff0c;红黑树的性质是否造到破坏5.2.1 情况一: cur为红&#xff0c;p为红&#xff0c;g为黑&#xff0c;u存在且为红…

智能优化算法应用:基于蜻蜓算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于蜻蜓算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于蜻蜓算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.蜻蜓算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…

【springboot】宝塔简单部署springboot 配置https

宝塔简单部署springboot配置https 需求步骤1. springboot通过maven组件打成jar包2. 将jar包部署到宝塔上3. 下载安装nginx并创建网站节点4. 设置域名或者IP5. 设置反向代理:代理后端服务的ip和端口7. 配置SSL/TLS 需求 宝塔部署springboot项目,用nginx反向代理后端IP端口&…

深度学习黎明时期的LeNet:揭开卷积神经网络的序幕

在深度学习的历史长河中&#xff0c;Yann LeCun 的 LeNet 是一个里程碑式的研究成果&#xff0c;它为后来的卷积神经网络&#xff08;Convolutional Neural Networks&#xff0c;CNN&#xff09;的发展奠定了基础。LeNet 的诞生标志着深度学习黎明时期的到来&#xff0c;为人工…

【已解决】在windows下,gitlab修改了密码导致remote: HTTP Basic: Access denied

背景 网上好多答案遇到此问题都是修改凭证,故写此文。 在控制面板》用户账户》凭据管理器》管理windows凭据》普通凭据 --找到对应的git地址&#xff0c;编辑用户名和密码 本文解决方案适用于windows下没有凭证的情况&#xff0c;因修改密码导致下拉代码出错的情况。 Git是常…

Scrapy框架内置管道之图片视频和文件(一篇文章齐全)

1、Scrapy框架初识&#xff08;点击前往查阅&#xff09; 2、Scrapy框架持久化存储&#xff08;点击前往查阅&#xff09; 3、Scrapy框架内置管道 4、Scrapy框架中间件&#xff08;点击前往查阅&#xff09; Scrapy 是一个开源的、基于Python的爬虫框架&#xff0c;它提供了…

JAVA配置jdk17 Graa1VM

按照网上内容下载好对应的jdk17版本的Graa1VM&#xff0c; 解压后&#xff0c;修改环境变量中的JAVA_HOME为当前的目录&#xff0c;例如 D:\ruanjian\jdk\gra_jdk17\graalvm-ce-java17-22.3.0 。 然后在命令行中输入java -version的时候&#xff0c; 返回的并不是 Graa1VM 相关…

文件权限中 chmod、u+x、u、r、w、x分别代表什么

Linux系统中的每个文件和目录都有访问许可权限&#xff0c;如下面所示&#xff1a; 要说清楚问题&#xff0c;我们截取一些内容&#xff1a; ypyubuntu:~$ ls -l drwxr-xr-- 2 ypy ypy 4096 Nov 30 18:33 Desktop/ drwxr-xr-- 2 ypy ypy 4096 Nov 30 18:33 Documen…

【扩散模型】DDIM从原理到实战

DDIM从原理到实战 1. DDIM简介2. 实战DDIM2.1 载入一个预训练过的pipeline2.2 DDIM采样2.3 反转&#xff08;invert&#xff09; 3. 组合封装参考资料 DDPM过程的一个问题是在训练后生成图像的速度。当然&#xff0c;我们可能能够生成令人惊叹的图像&#xff0c;但生成一张图像…

本地训练,立等可取,30秒音频素材复刻霉霉讲中文音色基于Bert-VITS2V2.0.2

之前我们使用Bert-VITS2V2.0.2版本对现有的原神数据集进行了本地训练&#xff0c;但如果克隆对象脱离了原神角色&#xff0c;我们就需要自己构建数据集了&#xff0c;事实上&#xff0c;深度学习模型的性能和泛化能力都依托于所使用的数据集的质量和多样性&#xff0c;本次我们…

【密码学引论】序列密码

第五章 序列密码 1、序列密码 定义&#xff1a; 加密过程&#xff1a;把明文与密钥序列进行异或运算得到密文解密过程&#xff1a;把密文与密钥序列进行异或运算得到明文以字/字节为单位加解密密钥&#xff1a;采用一个比特流发生器随机产生二进制比特流 2、序列密码和分组密…

【docker】docker安装与优化

目录 一、安装Docker 1、关闭防火墙 2、安装依赖包 3、设置阿里云镜像源 4、安装Docker-CE社区版并设置为开机自启动 5、查看Docker信息 二、设置镜像加速 1、申请加速地址 2、实现加速操作 三、网络优化 1、如何网络优化 2、具体操作 四、docker-server端配置文件…

汇编实验2-2 查找匹配字符串笔记

一、数据段 1.字符串结尾&#xff1a;13,10&#xff0c;$ 2.设置格式控制字符串(这样就不用再写clrf函数了) 3.设置存关键字和句子的地址标签&#xff0c;以关键字为例 二、代码段 1.输入字符串 2.字符串比较 2.1 每次的比较长度&#xff0c;KLEN->CL 2.2 设置目标串起始…

【Linux系统编程】操作系统详解(什么是操作系统?为什么会存在操作系统?设计操作系统的目的是什么?)

目录 一、前言 二、 什么是操作系统 &#x1f4a6;操作系统的引入 &#x1f4a6;操作系统的概念理解 &#x1f4a6;操作系统设计的目的与定位 &#x1f4a6;总结 二、操作系统之上之下分别有什么 三、深度理解操作系统的“管理” &#x1f4a6;场景理解 &#x1f4a6;操…

2023信息技术应用创新论坛|云轴科技ZStack分享云原生超融合在智慧交通的应用

11月25日&#xff0c;2023信息技术应用创新论坛在常州开幕。江苏省工业和信息化厅副厅长池宇、中国电子工业标准化技术协会理事长胡燕、常州市常务副市长李林等领导出席论坛并致辞。中国工程院院士郑纬民出席并作主题报告。来自产学研用金等各界的千余名代表参加本次论坛。 在“…

GitHub上8个强烈推荐的 Python 项目

文章目录 前言1. Manim2. DeepFaceLab3. Airflow4. GPT-25. XSStrike6. 谷歌图片下载7. Gensim8. SocialMapper总结关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③…

【刷题笔记】加油站||符合思维方式

加油站 文章目录 加油站1 题目描述2 思路3 解题方法 1 题目描述 https://leetcode.cn/problems/gas-station/ 在一条环路上有 n 个加油站&#xff0c;其中第 i 个加油站有汽油 gas[i] 升。 你有一辆油箱容量无限的的汽车&#xff0c;从第 i 个加油站开往第 i1 个加油站需要消…