mongodb数据库的增删改查(有图有demo)

名词注释

下面的截图中,有一些名词需要解释一下,方便理解和应用:

  • cuckoo叫库名,也就是数据库的名字
  • users叫集合名,也就是colloction的名字
  • 右侧带_id的一排排的, 那叫文档
  • _id , username, password这些,叫字段
  • 总结一下:数据库 > 集合 > 文档 > 字段

往collection里增加一条数据

现在collection为users的数据是这样的:
在这里插入图片描述

现在要把他变成下面这样的数据:
在这里插入图片描述

方法:

db.collection('users').insertOne({hello: "world"}, function(err, data) {
	if(err) {
		console.log(err);
	} else {
		console.log(data);
	}
})
// 不需要返回数据的话, function可以不写
往collection里增加多条数据

现在把上面的例子变成这样:
在这里插入图片描述
方法:

db.collection('users')
  .insertMany([{one: '第一条数据'}, {two: '第二条数据'}], (err, data) => {
     if(err) {
       console.log(err);
     } else {
       console.log(data);
     }
   })
 // 同样的, 如果不需要返回数据,后面的err data函数可以不写

注:原有的save()方法已废弃。现在介绍的都是3.2版本以后的新方法


删除单个文档

原始数据:
在这里插入图片描述
现在要把原始数据中的 “第一条数据” 文档删掉,变成这样:
在这里插入图片描述

做法:

db.collection('users')
            .deleteOne({one: "第一条数据"}, (err, data) => {
              if(err) {
                console.log(err);
              }else {
                console.log(data);
              }
            })
同时删除包含某项数据的多条文档

直接写做法:

// 删除所有带有one: "第一条数据"的文档
db.collection('users')
            .deleteMany({one: "第一条数据"}], (err, data) => {
              if(err) {
                console.log(err);
              }else {
                console.log(data);
              }
            })
删除该集合内的所有文档
db.collection('users').deleteMany({});

注意:原有的remove()方法已过时。


改(更新)
  • 介绍操作符
$set: // 更新数据
更新文档中的一条数据

原始数据:
在这里插入图片描述
现在,把文档中的one的值,改为"dilireba" :

db.collection('users').updateOne({one: 'hello'}, {
	$set: {one: "dilireba"}
})
更新文档中的多条数据

现在,把文档中one的值都改为"dilireba" :

db.collection('users').updateMany({one: 'hello'}, {
	$set: {one: "dilireba"}
})
更新文档中的一条数据,并增加数据

现在,把文档中one的值改为"dilireba",同时再增加一条年龄数据"age": 18
在这里插入图片描述

db.collection('users').updateOne({one: 'hello'}, {
	$set: {one: "dilireba", age: 18}
})
更新时删除一条数据

在这里插入图片描述
现在,把two: "world"这条数据删掉:

db.collection('users').update({two: 'world'}, {
	$unset: {two: ''}
})

嵌套数据的更新

嵌套数据的处理,相对要复杂一点, 所以单出。

向嵌套数组内增加数据

原始数据:
在这里插入图片描述
这里的task是一个数组,现在往这里面添加对象和字段。让数据变成这样:
在这里插入图片描述
做法:

db.collection('users').updateOne({username: "222"}, {
	$addToSet: {
		task: {
			date: new Date().getTime(),
			newTask: [],
			onGoing: [],
			finished: [],
			abandoned: []
		}
	}
})

// 注:$addToSet和$push同样是往数组内添加字段
// 前者是有同样的数据,就不添加。没有则添加。
// 后者是不管数组内有没有同样的数据,都会添加。
删除嵌套数组内的数据
db.collection('users').updateOne({username: "222"}, {
	$pull: {
		task: {
			date: new Date().getTime(),
			newTask: [],
			onGoing: [],
			finished: [],
			abandoned: []
		}
	}
})

这里需要说明一下,以免误解:

$pull: { task: {...}}

这里的task就是要操作的数组

task后面的{ ... }数据对象,就是筛选条件。

所以上面的操作意思就是:

在task数组中找到date为new Date().getTime(),其他四个数组内容为[]的对象,

然后删除这个对象。

2022/6/13更新了该条说明


修改数组内数据中的某个字段的值

在这里插入图片描述
现在, 要把newTask的值,更新为['hello', 'world']
在这里插入图片描述
做法:

db.collection('users').updateOne({username: "222", 'task.newTask': []}, {
	$set: {
		{'task.$.newTask': ['hello', 'world']}
	}
})

/*
需要注意两点:
一:查询条件里,必须要写上要被更新的元素。
比如要更新newTask,就要写上'task.newTask': []
二:注意$set里面的写法--'task.$.newTask' 。
这里的$是数组占位符,
task.$ 表示符合前面查找条件'task.newTask': []的元素,
比如经查询,task数组里第三个元素符合条件,那么task.$就代指第三个元素。
如果查询后,有多个元素都满足条件,那么task.$就代指第一个满足条件的元素。
task.$[] 表示task数组里的所有元素
task.$[index] 表示task数组里,下标为index的元素
*/
专门说说占位符$

上面有一段关于$的解释,

我觉得不仔细说下,很容易弄混。

给个原始数据:

[
  {
    _id: ObjectId335546da8fafwegs366,
    nameArr: [
      {
        name: 'dilireba',
        age: 18
      },
      {
        name: 'haha',
        age: 81
      },
      {
        name: 'xiaosan',
        age: 18
      }
    ]
  }
]

现在, 把name: "haha"改成name: “damimi”

db.collection('users').update({'nameArr.name': 'haha'}, {'nameArr.$.name': 'damimi'});
// 首先要清楚一点,$和前面的查询条件相关。
// 很容易看到,根据{'nameArr.name': 'haha'}这个查询条件,只有第二个元素符合条件,
// 这时 nameArr.$就可以理解为该元素:{ name: 'haha', age: 81 }
// 所以{'nameArr.$.name': 'damimi'}就表示把{ name: 'haha', age: 81 }的name值改为'damimi'

原始数据:
在这里插入图片描述

查找一条文档

现在,我们要查找one是"hello"且two是"world"的一条文档,

做法:

db.collection('users').findOne({one: 'hello', two: 'world'}).toArray ((err, data) => {
if(err) {
   console.log(err);
}else {
   console.log(data);
 }
})
// 这里的findOne, 也可以换成find
查找多条文档

现在,我们要查找one是"hello"的所有文档:

db.collection('users').findMany({one: 'hello'}).toArray ((err, data) => {
if(err) {
   console.log(err);
}else {
   console.log(data);
 }
})
查找集合内所有文档
db.collection('users').find({}).toArray ((err, data) => {
if(err) {
   console.log(err);
}else {
   console.log(data);
 }
})
按条件查找

先介绍一下操作符:

$lt: // 小于
$lte: // 小于等于
$gt: // 大于
$gte: // 大于等于
$ne: // 不等于

现在,我们要查找number小于50的文档:

db.collection('users').find({number: [$lt: 50]}).toArray()
  • $or操作符

现在,查找一下{one: ‘hello’} 或者{two: ‘world’}的文档:

db.collection('users').find({$or:[{one: 'hello'},{two: 'world'}]}).toArray()

注意:更新时是要先查找的,所以更新方法中的查找条件,同样可以用来做为查找条件。


参考文档
  • 前端学习(吹水)群:1064534163
  • 菜鸟教程mongodb篇: https://www.runoob.com/mongodb/mongodb-update.html
  • 常用操作符: https://www.cnblogs.com/angongIT/p/11170099.html
  • 内嵌数组的增删改查: https://www.cnblogs.com/KnowEditByW/p/9290593.html
  • 多级文档更新数据: https://www.jb51.net/article/215577.htm
  • 修改嵌套数据指定顺序的字段值: https://qa.1r1g.com/sf/ask/1372247971/
  • $操作符:https://blog.csdn.net/qq_34561892/article/details/113800916
  • $unset操作符用法: https://blog.csdn.net/yaomingyang/article/details/78791297
  • 几种嵌套查询的方法:http://t.zoukankan.com/xibuhaohao-p-12058248.html
  • mongodb中文文档:https://docs.mongoing.com/
  • mongodb查找方法大全:https://www.cnblogs.com/Sky-Ice/p/9429093.html

附赠mongodb的封装
  • 源码可到https://gitee.com/guozia007/cuckoo/tree/master/server/db本项目中查看。
  • 下为封装代码:
// 因为操作数据库最耗时的是连接数据库,所以对数据库进行封装,解决重复连接数据库问题
// 简单封装后存在多个实例化重复调用数据连接的问题,所以在封装时要解决。
const {MongoClient, ObjectId} = require('mongodb'); // 引入数据库
const config_db = require('./config'); // 引入db配置文件

/**
 * 封装db库
 */

class Db {
  // 创建一个静态方法,解决多个实例重复连接数据库的问题
  // 比如实例testDb1已经连接过数据库了,
  // 但是实例testDb2仍然会调用connect方法 去连接数据库,浪费了性能
  // 我们需要的是,当前面有实例连接过数据库时, 
  // 数据库处于连接状态,那么以后的实例都不需要再去连接了
  static getInstance() {
    if(!Db.instance) { // 如果不存在实例
      Db.instance = new Db(); // 就创建实例
    }
    return Db.instance;
  }
  constructor() {
    // 设置一个属性 解决某个实例上多个方法重复调用数据库连接的问题
    // 比如实例testDb已经连接过数据库了,那么在用find查询时,就不要再去重复连接了
    this.dbClient = ''; 

    this.connect(); // 初始化的时候就连接数据库
  }

  connect() { // 连接数据库
    return new Promise((resolve, reject) => {
      if(!this.dbClient) { // 如果dbClient不存在,就说明没调用过
        MongoClient.connect(config_db.dbUrl, (err, client) => {
          if(err) {
            reject(err);
          } else {
            this.dbClient = client.db(config_db.dbName);
            resolve(this.dbClient);
          }
        })
      } else { // 如果已经存在 说明被调用过了
        return resolve(this.dbClient);
      }
    })
  }

  add(collectionName, jsonData) { // 添加数据
    return new Promise((resolve, reject) => {
      this.connect()
      .then(db => {
        db.collection(collectionName)
        .insertOne(jsonData, (err, data) => {
          if(err) {
            reject(err);
          } else {
            resolve(data);
          }
        })
      })
      .catch(err => reject(err));
    })
  }

  addMany(collectionName, jsonArr) { // 添加多条数据
    return new Promise((resolve, reject) => {
      this.connect()
      .then(db => {
        db.collection(collectionName)
        .insertMany(jsonArr, (err, data) => {
          if(err) {
            reject(err);
          } else {
            resolve(data);
          }
        })
      })
      .catch(err => reject(err));
    })
  }

  /**删除 */
  delOne(collectionName, jsonData) {
    return new Promise((resolve, reject) => {
      this.connect()
        .then(db => {
          db.collection(collectionName)
            .deleteOne(jsonData, (err, data) => {
              if(err) {
                reject(err);
              }else {
                resolve(data);
              }
            })
        })
    })
  }

  delMany(collectionName, jsonData) {
    return new Promise((resolve, reject) => {
      this.connect()
        .then(db => {
          db.collection(collectionName)
            .deleteMany(jsonData, (err, data) => {
              if(err) {
                reject(err);
              }else {
                resolve(data);
              }
            })
        })
    })
  }

  update(collectionName, jsonData1, jsonData2) { // 更新一条数据
    return new Promise((resolve, reject) => {
      this.connect()
      .then(db => {
        db.collection(collectionName)
        .updateOne(jsonData1,
          {
            $set: jsonData2,
          },
            (err, data) => {
          if(err) {
            reject(err);
          } else {
            resolve(data);
          }
        })
      })
    })
  }

  update_delOne(collectionName, jsonData1, jsonData2) { // 更新时删除一条数据
    return new Promise((resolve, reject) => {
      this.connect()
      .then(db => {
        db.collection(collectionName)
        .updateOne(jsonData1,
          {
            $unset: jsonData2,
          },
            (err, data) => {
          if(err) {
            reject(err);
          } else {
            resolve(data);
          }
        })
      })
    })
  }

  /**
   * 当天第一次增加任务
   * 需要往task数组里增加对象
   * {
        date: new Date().getTime(),
        newTask: [],
        onGoing: [],
        finished: [],
        abandoned: []
      }
   */
  update_new_task(collectionName,jsonData1, jsonData2) {
    return new Promise((resolve, reject) => {
      this.connect()
        .then(db => {
          db.collection(collectionName)
          .updateOne(jsonData1, {
            $addToSet: {task: jsonData2}
          }, (err, data) => {
            if(err) {
              reject(err);
            } else {
              resolve(data);
            }
          })
        })
    })
  }

  update_$_data(collectionName,jsonData1, jsonData2) { // 更新嵌套数组内某个字段的值
    return new Promise((resolve, reject) => {
      this.connect()
        .then(db => {
          db.collection(collectionName)
            .updateOne(jsonData1, {
              $set: jsonData2
            }, (err, data) => {
              if(err) {
                reject(err);
              } else {
                resolve(data);
              }
            })
        })
    })
  }


  find(collectionName, jsonData) { // 查找数据
    return new Promise((resolve, reject) => {
      this.connect()
      .then(db => {
        db.collection(collectionName).find(jsonData)
        .toArray((err, data) => {
          if(err) {
            reject(err);
          } else {
            resolve(data);
          }
        })
      })
      .catch(err => reject(err));
    })
  }

  getObjectId(id) { // 获取_id,因为查询时用到的_id的值是ObjectId()类型的数据
    return new ObjectId(id);
  }

}

// const testDb = Db.getInstance();

// testDb.add('users', {hello: "world"})
// .then(data => console.log('添加成功', data));
// testDb.addMany('users', [{one: '第一条数据'}, {two: '第二条数据'}]);

// testDb.delOne('users', {one: "第一条数据"});
// testDb.delMany('users', {one: "第一条数据"});

// testDb.update('users', {one: "hello"}, {one: 'dilireba', age: 18})
// .then(data => console.log('更新成功', data));
// testDb.update_delOne('users', {two: 'world'}, {two: ''});

// testDb.find('users', {})
// .then(data => console.log('获取数据', data));

// testDb.update_new_task('users', {username: "222"}, 
// {
//   date: new Date().getTime(),
//   newTask: [],
//   onGoing: [],
//   finished: [],
//   abandoned: []
// })
// testDb.update_$_data('users', {username: "222", 'task.newTask': []}, {
//   'task.$.newTask': ['hello', 'world']
// })

module.exports = Db.getInstance();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值