MongoDB简单实用的使用教程

本文介绍了MongoDB的基本概念,如数据库、集合、文档以及SQL与MongoDB术语的区别。涵盖了安装、CRUD操作、文档结构和常用命令,适合初学者快速上手。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

参考文献,菜鸟教程:MongoDB 教程 | 菜鸟教程

MongoDB 是由C++语言编写的非关系性数据库(也叫NoSQL),是一个基于分布式文件存储的开源数据库系统。在高负载的情况下,添加更多的节点,可以保证服务器性能。

NoSQL(NoSQL =Not Only SQL ),意即"不仅仅是SQL"。MongoDB 将数据存储为一个文档,数据结构由键值对(key=>value)集合组成。

MongoDB 是介于关系数据库和非关系数据库之间的产品,是非关系数据库中功能最丰富,最像关系数据库的。

  • 它有关系型数据库中同等的概念,库,表,数据、指令集以及可扩展的结构,但本质完全不同。

  • 关系型数据库中,最重要的是表,所有数据的内外关系 都依赖于表:表结构(行和列)、表连接等

    • Mongo 中 称为集合,它是数据库集合的子集

    • mongo中行 称为文档,它没有结构约束,可以设置为任意的键和值。

      • {a : 1}

      • {b : 2}

      • {a:1, b:2, c:3}

    • Mongo 不支持关联数据表

MongoDB 旨在为WEB应用提供可扩展高性能数据存储解决方案。

概念

在mongodb中基本的概念是数据库集合文档

SQL术语/概念MongoDB术语/概念解释/说明
databasedatabase数据库
tablecollection数据库表/集合
rowdocument数据记录行/文档
column/fieldKey数据字段/域
indexindex索引
table joins表连接,MongoDB不支持
primary keyprimary key主键,MongoDB自动将_id字段设置为主键

img

MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。

mongodb数据库,简单来说,就是一个很大的数据集合:

{
    // 数据库
    "shop" : {
        // 表 在mongo中成为 collection集合
        "goods" : {
            // 数据行 在mongo中 成为 document文档
            "id1" : {
               // mongo 没有表结构,也就没有字段(键)的约束
               // 每一个文档 它里面可以包含不同的字段(键),但实际业务来说 会有结构设计
               gname : '飞利浦',
               price : 9527,
             “
        },
        "orders" : {
            
        },
        // ...
    },
    "test" : {
      
    }
}

安装

MongoDB 提供了 OSX 平台上 64 位的安装包,你可以在官网下载安装包。

下载地址:Try MongoDB Products | MongoDB

在macOS系统中,使用curl命令下载文件:

# 进入 /usr/local
cd /usr/local
​
# 下载
sudo curl -O https://fastdl.mongodb.org/osx/mongodb-osx-ssl-x86_64-4.0.9.tgz
​
# 解压
sudo tar -zxvf mongodb-osx-ssl-x86_64-4.0.9.tgz
​
# 重命名为 mongodb 目录
​
sudo mv mongodb-osx-x86_64-4.0.9/ mongodb

接下来,进入mongodb安装目录下的bin目录,将该地址添加到环境变量,那么你在任意位置都可以执行有关mongo的命令:

$ mongod --version

Mongo 默认使用命令安装位置的根地址 作为数据存放目录,例如c:/data/db,如果要指定数据存放地址可以通过

--dbpath来设置:

无论使用何地址,你必须先创建它:

$ cd /usr/local/mongodb
$ sudo mkdir data
$ sudo mkdir -p log/mongodb

对于类unix系统的用户,最好修改目录权限:

$ cd /usr/local/mongodb
$ sudo chown tinlau data
$ sudo chown tinlau log/mongodb

接下来我们使用以下命令在后台启动 mongodb:

$ mongod --dbpath data --logpath log/mongodb/mongo.log --fork

启动成功命令窗口中打印一些启动信息或者在浏览器中输入http://localhost:27017/即可看到显示信息为:

It looks like you are trying to access MongoDB over HTTP on the native driver port.

如果要关闭服务,则可以选择以下几种方式:

  • 如果以前台方式启动 MongoDB 服务,使用"Crtl+C"服务会关闭,

    这种关闭方式会等待当前进行中的的操作完成,所以依然是干净的关闭方式。

  • 使用mongod命令:

    mongod  --shutdown  --dbpath /usr/local/mongodb/data/

  • 使用数据库命令关闭

    > use admin;
    switched to db admin
    > db.shutdownServer();

启动服务后 就可以使用mongo终端访问mongodb服务:

入门

mongodb用C++高效地实现了底层的数据读写等功能。

对外提供的操作API规则|调用方式,使用了JS来实现,故mongo客户端中使用的命令与JS极度相似。

MongoDB shell 是一个功能完备的JS解释器,可以运行任何JS程序,那它算一个宿主环境吗?

$ var a = 1;
$ a;

数据库

  • show dbs 查看数据库,显示默认安装的数据库

    MongoDB的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中。

    • admin: 从权限的角度来看,这是"root"数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。

    • local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合

    • config: 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。

  • db 查看当前所在数据库,默认test,只有当创建了数据 才会真正启用

    MongoDB的默认数据库为"db",该数据库存储在data目录中。

  • use 切换数据库,如果没有则新建之,

  • db.dropDatabase() 删除当前的数据库

集合

集合就是 MongoDB 文档组,类似于 RDBMS (关系数据库管理系统:Relational Database Management System)中的表格。

集合存在于数据库中,集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性

比如,我们可以将以下不同数据结构的文档插入到集合中:

{"site":"www.baidu.com"}
{"site":"www.google.com","name":"Google"}
{"site":"www.runoob.com","name":"homey","num":5}

当第一个文档插入时,集合就会被创建。

  • 创建集合

    db.createCollection("users");

  • 查看已有集合

    show collections;  # 或者
    show tables;

  • 在 MongoDB 中,你不需要创建集合。当你插入一些文档时,MongoDB 会自动创建集合。

    $ db.users.insert({"name" : "homey"})
    $ WriteResult({ "nInserted" : 1 })

  • 删除集合, 如果成功删除选定集合,则 drop()方法返回 true,否则返回 false。

    db.users.drop();

文档

MongoDB 的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,这样一来,无需多余操作就可以横向扩展。当第一个文档插入时,集合就会被创建。

  1. 文档中的键/值对是==有序==的。

  2. 文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)。

  3. MongoDB区分类型和大小写。

  4. MongoDB的文档不能有重复的键。

  5. 文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。

CURD

插入文档

MongoDB 使用 insert() 或 save() 方法向集合中插入文档,语法如下:

db.user.insert(document)

若插入的数据主键已经存在,则会抛 org.springframework.dao.DuplicateKeyException 异常,提示主键重复,不保存当前数据

db.user.insertOne(document) 
db.user.insertMany([document, document])

如果 _id 主键存在则更新数据,如果不存在就插入数据.

# 插入成功 返回insertedId
{
    "acknowledged" : true,
    "insertedId" : ObjectId("6167cd8755ce3b28b800ea9a")
}

更新文档

db.collection.update(
   <query>,
   <update>,
   {
     upsert: <boolean>,
     multi: <boolean>,
     writeConcern: <document>
   }
)

参数说明:

  • query : update的查询条件,类似sql update查询内where后面的。

  • update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的

  • upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。

  • multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。

  • writeConcern :可选,抛出异常的级别。

db.user.update({name:'lisi'}, {age:18}); // 重置 覆盖
db.user.update({name:'张三'}, {$set : {gender : '男'}}) // 扩展字段

$set为修饰器,类似于sql中的set关键字,主要有:$inc $set $unset $push $pull

只更新第一条记录:

db.col.update( { "count" : { $lt : 1 } } , { $set : { "test2" : "OK"} } );

全部更新:

db.col.update( { "count" : { $gt : 3 } } , { $set : { "test2" : "OK"} },false,true );

只添加第一条:

db.col.update( { "count" : { $gt : 4 } } , { $set : { "test5" : "OK"} },true,false );

全部添加进去:

db.col.update( { "count" : { $gt : 5 } } , { $set : { "test5" : "OK"} },true,true );

全部更新:

db.col.update( { "count" : { $gt : 15 } } , { $inc : { "count" : 1} },false,true );

只更新第一条记录:

db.col.update( { "count" : { $gt : 10 } } , { $inc : { "count" : 1} },false,false );

移除数据

MongoDB remove() 函数是用来移除集合中的数据。

MongoDB 数据更新可以使用 update() 函数。在执行 remove() 函数前先执行 find()命令来判断执行的条件是否正确,这是一个比较好的习惯。

db.collection.remove(
   <query>,
   {
     justOne: <boolean>,
     writeConcern: <document>
   }
)
  • query :(可选)删除的文档的条件。

  • justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。

  • writeConcern :(可选)抛出异常的级别。

db.users.remove({name:'test'}, {justOne:1})

如果不设置条件,即条件为{} 空对象 则==删除所有==.

查询数据

db.collection.find(query, projection)
  • query :可选,使用查询操作符指定查询条件

  • projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。

如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:

db.collection.find().pretty();

除了 find() 方法之外,还有一个 findOne() 方法,它只返回(第)一个文档:

db.collection.findOne(where);

where子句

MongoDB 与 RDBMS Where 语句比较:

如果你熟悉常规的 SQL 数据,通过下表可以更好的理解 MongoDB 的条件语句查询:

操作格式范例RDBMS中的类似语句
等于{<key>:<value>}db.col.find({na me:"homey"}).pretty()where name = 'homey'
小于{<key>:{$lt:<value>}}db.col.find({count:{$lt:50}}).pretty()where count < 50
小于或等于{<key>:{$lte:<value>}}db.col.find({count:{$lte:50}}).pretty()where count <= 50
大于{<key>:{$gt:<value>}}db.col.find({count:{$gt:50}}).pretty()where count > 50
大于或等于{<key>:{$gte:<value>}}db.col.find({count:{$gte:50}}).pretty()where count >= 50
不等于{<key>:{$ne:<value>}}db.col.find({count:{$ne:50}}).pretty()where count != 50

MongoDB AND 条件:

MongoDB 的 find() 方法可以传入多个键(key),每个键(key)以逗号隔开,即常规 SQL 的 AND 条件。

MongoDB OR 条件:

MongoDB OR 条件语句使用了关键字 $or,语法格式如下:

db.col.find({count: {$gt:50}, $or: [{name:"homey"},{name: "gp7"}]}).pretty()

相当于:where count > 50 and (name='homey' or name='gp7')

模型操作

mongodb

npmjs演示文档:mongodb - npm

官方网站地址:MongoDB Node Driver — Node.js

mongoose

mongoose是在mongodb模型基础上扩展而来,

参考地址:Mongoose ODM v6.0.10

// 连接mongodb服务器
mongoose.connect('mongodb://localhost/test');
​
// 创建表模型类 并设置表名,实际会转化成cats,不需要实际存在 当创建了第一条记录 会新建
const Cat = mongoose.model('Cat', { name: String });
​
// 实例化表 - 创建表并初始数据
const kitty = new Cat({ name: 'Zildjian' });
​
// 执行
kitty.save().then(() => console.log('meow'));

Schema架构

虽然,mongodb的结构很灵活,但实际业务时 还是会有一定的规范约束以确保数据的一致性与完整性 避免脏值,因此需要设计表结构。moogse是从代码的层面 来支持你对表创建的约束,例如 字段值类型等。

Mongoose为模型提供了一种直接的,基于scheme结构去定义你的数据模型。它内置数据验证, 查询构建,业务逻辑钩子等,开箱即用。

const mongoose = require("mongoose")
const {model, Schema} = mongoose;
​
// 连接数据库
mongoose.connect("mongodb://localhost/test");
​
// 设计表结构
const userSec = new Schema({
    name : {
        type : String,
        required : true,
    },
    gender : {
        type : String,
        enum : ['m', 'w'],
        required : true,
    },
    age : Number,
})
​
// 创建表模型类
const User = model("User", userSec);
​
// 实例化模型类 用来创建数据对象
const users = new User({name : 'lautin', gender : 'w', age : 18});

接下来,可以使用curd方法进行操作,支持promise与回调函数两种方式:

users.save().then(() => {
    console.log("done.");
}).catch(e => { // 数据验证不通过时 执行onReject
    console.log(e.message);
})

Mongoose 有几个内置的验证器。

如果想要自定义错误提示,则配置规则为一个数组或者对象,例如:

const breakfastSchema = new Schema({
  eggs: {
    type: Number,
    min: [6, 'Must be at least 6, got {VALUE}'], // 
    max: 12
  },
  drink: {
    type: String,
    enum: {
      values: ['Coffee', 'Tea'],
      message: '{VALUE} is not supported'
    }
  }
});
const Breakfast = db.model('Breakfast', breakfastSchema);

crud方法操作

  • 新增:

    // 创建数据对象,用于添加的
    const model = new Model(data);  
    model.save(); // 数据对象.save()

  • 查询:

    // 返回所有符合条件的数据 哪怕就一条也是数组
    Model.find(where, callback);
    // 查找符合条件的数据 返回第一条
    Model.findOne(where, callback)

  • 删除:

    // 删除指定条件的记录
    Model.remove(where, callback)

    [MONGODB DRIVER] Warning: collection.remove is deprecated. Use deleteOne, deleteMany, or bulkWrite instead.

    集合.remove()已经不推荐了,使用deleteOne、deleteMany() 或者bulkWrite等替代。

  • 修改:

    // 按照id查找符合条件的记录 进行修改
    findByIdAndUpdate(id, data, callback)
    // 按照条件查找符合要求的记录 进行修改
    findOneAndUpdate(where, data, callback)

封装业务模型

最后,为不同的业务 配置表模型的结构和验证规则以及扩展增删改查操作,例如 商品信息表模型:

const mongoose = require("mongoose");
​
const {model, Schema} = mongoose;
​
// 连接数据库
mongoose.connect('mongodb://localhost/goods');
​
// 设计表
const goodsSchema = new Schema({
    gname : String,
    gdesc : String,
    price : Number,
    gpic : String,
    created : {
        type : String,
        default : Date.now()
    }
})
​
const GoodsModel = model("Good", goodsSchema);
​
module.exports = {
​
    async add (data) {
        const goods = new GoodsModel(data);
        return await goods.save();
    },
​
​
    async select (where) {
        return await GoodsModel.find(where);
    },
​
​
    async delete(where) {
        return await GoodsModel.remove(where)
    },
​
    async updateById(id, data) {
        return GoodsModel.findByIdAndUpdate(id, data)
    }
​
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值