【后端开发实习】用MongoDB实现仓库管理的出库入库实战
用MongoDB实现仓库管理的出库入库
- MongoDB
- 什么是MongoDB
- MongoDB安装以及开始运行
- 配置启动以及mongosh
- mongodb的基础使用命令
- 启动和使用MongoDB服务
- 数据库操作
- 集合操作
- 文档操作
- 项目部署
- 在数据库中创建一张商品信息表
- 提供信息表的增删改查操作接口
MongoDB
什么是MongoDB
Mongodb是一种比较常见的NoSQL类型数据库,所谓NoSQL就是Not only SQL,非关系型数据库,数据在MongoDB中的存储相比MySQL而言比较松散,并没有特定的数据结构,存储方式类似JSON,采用了一种二进制的BSON来进行数据存储。但是MongoDB由于以下的几个优势在互联网需要处理海量数据场景下有独特的优势,比较经典的应用场景有微信和Twitter每天数以TB甚至PB级别的数据量。
- 高性能
- 高可用
- 高扩展
- 丰富的查询支持
MongoDB安装以及开始运行
安装成功运行会看到上面这张结果图。
配置启动以及mongosh
在命令行中输入如下命令:
sudo vim /etc/systemd/system/mongodb.service
在打开的mongodb.service文件中填入以下内容:
[Unit]
Description=High-performance, schema-free document-oriented database
After=network.target[Service]
User=mongodb
ExecStart=/usr/bin/mongod --quiet --config /etc/mongod.conf[Install]
WantedBy=multi-user.target
配置成功以后输入mongo就可以与数据库连接上并进行相关操作。
mongodb的基础使用命令
启动和使用MongoDB服务
# 重新加载配置,并启动mongodb
sudo systemctl daemon-reload
sudo systemctl start mongod# 查看运行状态
sudo systemctl status mongod
# 如果mongodb状态为stop,则运行 sudo systemctl enable mongod# 停止mongodb
sudo systemctl stop mongod# 重启mongodb
sudo systemctl restart mongod
数据库操作
# 创建和切换数据库,命名规范:全部小写
use dbname
# 删除数据库,主要是用来删除已经从内存持久化到磁盘中的数据库
db.dropDatabse()
# 显示已经创建的数据库
show dbs
集合操作
# 创建集合
db.createCollection("collectionname")
# 删除集合
db.collectionname.drop()
# 显示已经创建的数据库
show dbs
!注:这里还有一个是集合的隐式创建,通过在文档操作的时候insert操作如果没有匹配到现有数据库,就创建一个。
文档操作
# 创建文档
db.collectionname.insert({BSON格式数据})
# 文档数据查询
db.collectionname.find()
# 文档数据更新,直接使用是覆盖更新
db.collectionname.update(query, update, options)
# 局部更新,使用$set修改器
db.collectionname.update({userId:"1001"},{$set:{username="张三"}})
# 批量更新,在option选项中增加multi:true
db.collectionname.update({userId:"1001"},{$set:{username="张三"}})
# 文档删除,如果没有带条件就是“删库跑路”
db.collectionname.remove(query)
! 注:mongodb中默认的是浮点类型的数据,因此想使用整型变量的时候需要用NumberInt函数进行转换。
项目部署
在数据库中创建一张商品信息表
由于已经有MongoCampass这个图形化的工具,在创建的时候可以使用这个提高效率而不用一行一行输入数据。
创建好集合以后就可以向集合中插入文档数据,编辑好一行以后按加号继续编辑下一行。
提供信息表的增删改查操作接口
这个部分的内容有一位大佬总结的很好了,这里贴出他的博客,非常建议学习,他总结的关于Schema和Collection还有Document之间的关系使我茅塞顿开。
//引入mongodb数据库 => MongoClient mongo =>客户端
const {MongoClient} = require("mongodb");// mongo连接网址
const url = 'mongodb://127.0.0.1:27017';//mongo连接 数据库名称
const dbName = 'Shop';async function connect() {
// 注意点:由于 MongoClient.connect() 返回的是一个promise对象 因此可以使用async 和 await
// console.log(MongoClient.connect(url)); //(MongoClient.connect(url) 返回一个Promise对象)const client = await MongoClient.connect(url); //链接数据库const db = client.db(dbName); //匹配数据库return {client,db}
}//数据库操作之 增函数 参数1:集合 参数2:data数据(增的数据)
async function insert(colName, data) {
//1:链接数据库 并且把db 和 client在链接数据库中导出 let {db,client} = await connect()//2:匹配数据库集合const collection = db.collection(colName);
//3:需要判断传入的数据 是一条还是多条 一条就是insertOne 多条就是insertMany 在集合之中插入数据 const result = await collection[Array.isArray(data) ? "insertMany" : "insertOne"](data);
//3:关闭数据库连接client.close();return result;
}//数据库之 改
// `db.集合的名称.updateOne( {name:"ppp",age:10 } , { $set : { name:"嘿嘿",age:20} } );`
//根据id来修改 数据库中的data
async function update(colName, query, newData) { //newData{$set:{price:200,qty:2},$inc:{view:1}}let {db,client} = await connect();let collection = db.collection(colName);//根据id删除 数据if (query._id && typeof query._id === 'string') {query._id = ObjectId(query._id);}let result = await collection.updateOne(query, newData);console.log("result" + result);return result;}//数据库之 删
// `db.集合的名称.deleteMany({name:"ppp"})`
async function remove(colName, query) {//1:链接数据库let {db,client} = await connect()//根据id删除 数据if (query._id && typeof query._id === 'string') {query._id = ObjectId(query._id);}//2:匹配集合let collection = db.collection(colName);//判断是删除一条还是多条let result = await collection.deleteMany(query);client.close();return result;}
// //查 函数
// 操作数据库的前提是:引入数据库,还有连接网址,连接数据库名称,数据库的链接
// 方法里面:数据库的链接(里面有着:链接数据库 匹配数据库集合,最后根据所选的集合 操作数据库) 最后关闭数据库!
async function find(colName, query = {}, options = {}) { //参数1:数据库中的集合(表) 参数2:操作的数据库语句 参数3:配置参数 //1:链接数据库let {db,client} = await connect();//2:匹配数据库集合 let collection = db.collection(colName);//3:最后根据所选的集合 操作数据库 查询操作let result = collection.find(query);//分页功能 需要的参数:页数 限制显示的多少页 跳过的数据条数 eg: 1页-0~5-0条 2页-5~10条-5条 3页-10~15-10条//01:查询跳过的记录if (options.skip) {result = result.skip(options.skip) //result.skip()方法 设置跳过记录 }//02:设置显示的条数if (options.limit) {result = result.limit(options.limit)}//排序的功能if (options.sort) { //前端传来的之 ["price"] 或者["price","1"] 第一种为默认的降序 第二种为升序let key, val;key = options.sort[0]; //拿到key值 if (options.sort.length > 1) {val = options.sort[1] * 1;} else {val = -1;}result = result.sort({ //对象[字符串] [key]: val})}result = await result.toArray(); //返回的是一个数组的形式!给与前端!//最后 客户端关闭数据库 client.close();return result; //返回查询结果 一个promise对象}//把增删改查 到出 在引入这个工具函数时候 调用!module.exports = {insert,find,update,remove}
调用接口:
const express = require("express");
const router = express.Router();const mongo = require("./mongo");
const { ObjectId } = require("mongodb");const colc_name = "goods"
//post 方式 增加数据
router.post("/insert", async (req, res) => {// `db.集合的名称.insertMany([{name:"名称",age:11},{name:"www",age:20}])`// insert() 参数1:数据库集合 参数2:插入的数据 插入一条数据的话 直接一个对象 插入多条数据的话 [{},{}] 对象里面书写插入的参数!// let result = await mongo.insert("goods2", {// "name": "ppp",// "purchase": "1件起购",// "oldprice": 12345.00,// });let result = await mongo.insert(colc_name, [{"name": "ppp","purchase": "1件起购","oldprice": 222,}, {"name": "lll","purchase": "1件起购","oldprice": 111,}]);res.send("插入成功"+result);
})
//查询
router.get("/search", async (req, res) => {//分页效果!//设置默认显示的条数还有第几页 并且获取到前端发来的请求参数!let {//page 第一页 size为显示条数大小为10 sort默认的排序(降) 根据nowPrice排序 注意点:nowPrice一定是数值型! 不带""page = 1, size = 10, sort = "oldprice"} = req.query;//设置skip跳过的记录 还有限制显示的那些数据条数let skip = (page - 1) * size;let limit = size * 1;//排序的参数处理sort = sort.split(","); //参数传递:price,1等等! ['price'],['price','-1']//find()参数:参数1:数据库中的集合(表) 参数2:操作的数据库语句 参数3:配置参数 let result = await mongo.find(colc_name, {}, {skip,limit,sort});res.send(result);
})
//删除数据
router.delete('/:id', async (req, res) => {// router.delete('/:name', async (req, res) => {const {id// name} = req.params;// console.log("name" + name);var objectId = new ObjectId(id)try {const result = await mongo.remove(colc_name, {_id: id})// const result = await mongo.remove('goods2', {// name: name// })res.send('success')return result;} catch (err) {res.send(err);}})
//修改数据router.put("/:id", async (req, res) => {let {id} = req.params;console.log("id" + id);// let whereDate = {// name: "ooo"// }let whereDate = {_id: id}let updataDate = {$set: {name: "zzz",oldPrice: 200,},$inc: {view: 1}}console.log(whereDate, updataDate); //oktry {let result = await mongo.updata(colc_name, whereDate, updataDate);res.send("success");} catch (err) {res.send("fail")}})
module.exports = router;
在定义了所有的接口以后统一导出,然后就能通过router中的url来访问了。
相关文章:

【后端开发实习】用MongoDB实现仓库管理的出库入库实战
用MongoDB实现仓库管理的出库入库 MongoDB什么是MongoDBMongoDB安装以及开始运行配置启动以及mongoshmongodb的基础使用命令启动和使用MongoDB服务数据库操作集合操作文档操作 项目部署在数据库中创建一张商品信息表提供信息表的增删改查操作接口 MongoDB 什么是MongoDB Mong…...

内网信息收集——用户凭据窃取
文章目录 一、获取域内单机密码和hash1.1 在线读取lsass进程内存1.2 离线读取lsass.exe进程内存1.3 在线读取本地SAM文件1.4 离线读取本地SAM文件 二、域hash获取三、windows凭据导出 一、获取域内单机密码和hash 在windows中,SAM文件是windows用户的账户数据库&am…...

组串式逆变器散热分析
1 引言 组串式逆变器散热方式主要有强制风冷和自然冷却两种,针对两种散热方式的实际效果,笔者抽取了不同厂家不同散热方式的两款组串式逆变器进行实验对比,发现在同样的环境温度下,强制风冷的逆变器内部环境温度及核心器件温升比…...

WEB07Vue+Ajax
1. Vue概述 Vue(读音 /vjuː/, 类似于 view),是一款用于构建用户界面的渐进式的JavaScript框架(官方网站:https://cn.vuejs.org)。 在上面的这句话中呢,出现了三个词,分别是&#x…...

uniapp打包成Android时,使用uni.chooseLocation在App端显示的地址列表是空白?一直转圈的解决办法
问题描述: uniapp打包后的测试版app在ios里可以显示高德地图的定位列表,但是安卓手机却不显示定位列表,一直在转圈圈,怎么回事?之前的功能在正式版都能用,真机运行也能用,为什么测试版的安卓手…...
删除矩阵中0所在行 matlab
%for验证 new[]; for i1:size(old,1)if old(i,4)~0 %assume 0所在列在第4列new(end1,:)old(i,:);end enda(a(:,2)0,:)[]参考: 两种方式...
JavaWeb---HTML
一 HTML入门 1.1 HTML&CSS&JavaScript的作用 HTML 主要用于网页主体结构的搭建 CSS 主要用于页面元素美化 JavaScript 主要用于页面元素的动态处理 1.2 什么是HTML HTML是Hyper Text Markup Language的缩写。意思是超文本标记语言。它的作用是搭建网页结构,…...

Apache Doris:下一代实时数据仓库
Apache Doris:下一代实时数据仓库 概念架构设计快速的原因——其性能的架构设计、特性和机制基于成本的优化器面向列的数据库的快速点查询数据摄取数据更新服务可用性和数据可靠性跨集群复制多租户管理便于使用半结构化数据分析据仓一体分层存储 词条诞生技术概述适…...

t-SNE降维可视化并生成excel文件使用其他画图软件美化
t-sne t-SNE(t-分布随机邻域嵌入,t-distributed Stochastic Neighbor Embedding)是由 Laurens van der Maaten 和 Geoffrey Hinton 于 2008 年提出的一种非线性降维技术。它特别适合用于高维数据的可视化。t-SNE 的主要目标是将高维数据映射…...
End-to-End Object Detection with Transformers【方法详细解读】
摘要 我们提出了一种新的方法,将目标检测视为一个直接的集合预测问题。我们的方法简化了检测流程,有效地消除了许多手工设计的组件,如非极大值抑制程序或锚生成,这些组件显式编码了我们关于任务的先验知识。新框架的主要成分,称为DEtection TRansformer或DETR,是一个基于…...

SQLite数据库与ROOM数据库
目录 1、SQLite数据库 目的: 基本操作: 缺点: 解决: 2、ROOM持久性库 目的: 优点: 导入依赖: 主要组件: 编辑 使用步骤: a.定义数据实体 b.定义数据访问对象(接…...

vue实现动态图片(gif)
目录 1. 背景 2. 分析 3. 代码实现 1. 背景 最近在项目中发现一个有意思的小需求,鼠标移入一个盒子里,然后盒子里的图就开始动起来,就像一个gif一样,然后鼠标移出,再按照原来的变化变回去,就像变形金刚…...
win11系统设置允许无密码远程桌面连接
在windows11系统中设置允许无密码远程桌面连接,可以通过以下步骤进行操作: 1、启用远程桌面功能:首先,确保您的Windows 11是专业版,因为家庭版默认不支持远程桌面功能。您可以通过“设置” -> “系统” -&…...

使用 PyAMF / Django 实现 Flex 类映射
1、问题背景 PyAMF 是一个用于在 Flex 和 Python 之间进行通信的库,在使用 PyAMF 与 Flex 应用进行通信时,经常会遇到错误。例如,在发送一个 Flex Investor 对象到 Python 时,会得到一个 ‘KeyError: first_name’ 的错误。这是因…...

算法思想总结:字符串
一、最长公共前缀 . - 力扣(LeetCode) 思路1:两两比较 时间复杂度mn 实现findcomon返回两两比较后的公共前缀 class Solution { public:string longestCommonPrefix(vector<string>& strs) {//两两比较 string retstrs[0];size…...

滑块拼图验证码识别
通常滑块验证码都是横向滑动,今天看到一个比较特别的滑块拼图验证码,他不仅能在横向上滑动,还需要进行纵向滑动。如下图所示: 他的滑块在背景图片的左上角,需要鼠标拖动左上角的滑块,移动到背景图的缺口位置…...

Activity启动流程
1 冷启动与热启动 应用启动分为冷启动和热启动。 冷启动:点击桌面图标,手机系统不存在该应用进程,这时系统会重新fork一个子进程来加载Application并启动Activity,这个启动方式就是冷启动。 热启动:应用的热启动比冷…...

PHP转Go系列 | ThinkPHP与Gin框架之OpenApi授权设计实践
大家好,我是码农先森。 我之前待过一个做 ToB 业务的公司,主要是研发以会员为中心的 SaaS 平台,其中涉及的子系统有会员系统、积分系统、营销系统等。在这个 SaaS 平台中有一个重要的角色「租户」,这个租户可以拥有一个或多个子系…...
使用SOAP与TrinityCore交互(待定)
原文:SOAP with TrinityCore | TrinityCore MMo Project Wiki 如何使用SOAP与TC交互 SOAP代表简单对象访问协议,是一种类似于REST的基于标准的web服务访问协议的旧形式。只要必要的配置到位,您就可以利用SOAP向TrinityCore服务器发送命令。 …...

QQ频道导航退出
若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/140413538 长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...

Ubuntu系统多网卡多相机IP设置方法
目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机,交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息,系统版本:Ubuntu22.04.5 LTS;内核版本…...

何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡
何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡 背景 我们以建设星云智控官网来做AI编程实践,很多人以为AI已经强大到不需要程序员了,其实不是,AI更加需要程序员,普通人…...

链式法则中 复合函数的推导路径 多变量“信息传递路径”
非常好,我们将之前关于偏导数链式法则中不能“约掉”偏导符号的问题,统一使用 二重复合函数: z f ( u ( x , y ) , v ( x , y ) ) \boxed{z f(u(x,y),\ v(x,y))} zf(u(x,y), v(x,y)) 来全面说明。我们会展示其全微分形式(偏导…...

leetcode73-矩阵置零
leetcode 73 思路 记录 0 元素的位置:遍历整个矩阵,找出所有值为 0 的元素,并将它们的坐标记录在数组zeroPosition中置零操作:遍历记录的所有 0 元素位置,将每个位置对应的行和列的所有元素置为 0 具体步骤 初始化…...

PydanticAI快速入门示例
参考链接:https://ai.pydantic.dev/#why-use-pydanticai 示例代码 from pydantic_ai import Agent from pydantic_ai.models.openai import OpenAIModel from pydantic_ai.providers.openai import OpenAIProvider# 配置使用阿里云通义千问模型 model OpenAIMode…...
【深尚想】TPS54618CQRTERQ1汽车级同步降压转换器电源芯片全面解析
1. 元器件定义与技术特点 TPS54618CQRTERQ1 是德州仪器(TI)推出的一款 汽车级同步降压转换器(DC-DC开关稳压器),属于高性能电源管理芯片。核心特性包括: 输入电压范围:2.95V–6V,输…...