zoukankan      html  css  js  c++  java
  • nodejs操作MongoDB数据库 MongoDB增、删、改、查

    nodejs、MongoDB相关介绍请自行了解。

    使用环境

    • "node": "^10.16.0"
    • "mongodb": "^3.6.0"

    操作流程

    其实很简单,如果想对数据库进行操作,肯定要先连接数据库吧,连接完数据库肯定要找要操作的数据表吧,找到数据表了,是不是就可以对数据表进行增、删、改、查了!更全的英文文档请访问mongodb.com

    具体操作

    安装MongoDB

    安装MongoDB

    npm install mongodb --save
    
    

    引入 mongodb下面的连接模块MongoClient

    // 引入MongoDB 连接模块
    const MongoClient = MongoDB.MongoClient;
    

    连接数据库

    // 数据库地址
    let url = "mongodb://localhost:27017/";
    MongoClient.connect(url,(err,client)=>{
      if(err){
        console.log(err);
        return false;
      }
    
    });
    
    

    关闭连接数据库

    MongoClient.connect(url, function (err, client) {
      // 执行数据库操作
      ...code
    
      // 关闭连接数据库
      client.close();
    });
    

    创建集合实例

    如果你对数据库和集合的概念不理解的话,电脑上的Excel文件用过吧,一个Excel文件里是不是有多个sheet表,对应的一个数据库里也可以有多个集合(MySQL里面叫表,MongoDB里叫集合)。

    mongodb当集合不存在时,会自动创建集合,因此,可以不用特意的进行集合的创建操作

    const MongoClient = require("mongodb").MongoClient;
    const url = "xxxxxxxx";
    MongoClient.connect(url, function (err, client) {
      client
        .db("example")   // 连接example数据库
        .createCollection("table1")   // 创建一个table1集合实例,如果集合不存在,会自动创建集合
        .then(
          function (result) {},
          function (err) {
            console.log(err.message);
          }
        );
    });
    

    Node.js中创建一个Collection对象实例的方法:

    var MongoClient = require('mongodb').MongoClient;
    MongoClient.connect("mongodb://localhost:27017",function(err,db){
    	dbo = db.db("test");
    	collectionIns = dbo.collection("products");
    	console.log(collectionIns);
    	db.close();
    });
    

    其中 collectionIns是一个collection对象实例,Collection对象实例有很非常多的方法可以使用,下文举例一些实例方法。

    获取所有集合

    const MongoClient = require("mongodb").MongoClient;
    const url = "";
    MongoClient.connect(url, function (err, client) {
        client.db("example").listCollections().toArray().then(function (tables) {
            tables.forEach(function (value, index, ts) {
                console.log(value.name);
            })
        }, function (err) {
            console.log(err.message);
        })
    });
    

    包装ID

    通过id对数据操作的时候需要用到此方法,MongoDB里面查询_id ,把字符串转换成对象,MongoDB数据库里的_id是自动生成的,通过dind方法查询结果可以看到形式如: {"_id": ObjectId("5aad299bc166236421c99d229")},直接传入5aad299bc166236421c99d229,是查询不到结果的,所以需要包装一下

    
    // 引入MongoDB 模块
    const MongoDB = require("mongodb");
    // 引入MongoDB 连接模块
    const MongoClient = MongoDB.MongoClient;
    // 引入MongoDB ObjectID模块
    const ObjectID = MongoDB.ObjectID;
    
    let _id = new ObjectID("5bcae50ed1f2c2f5e4e1a76a");
    db.collection('xxx').find({
     "_id": _id
    }).forEach(function (item) {
     console.log(item)
    })
    

    向集合中插入一条数据

    insertOne(json):插入一条数据json格式

    MongoClient.connect(url, function (err, client) {
      client
        .db("example")
        .collection("table1")
        .insertOne({ name: "张三丰11" })
        .then(
          function (result) {},
          function (err) {
            console.log(err.message);
          }
        );
    });
    
    

    向集合中批量插入一组数据,数组里的每一个对象都是一条数据,会有各自的_id索引

    insertMany(array):插入一组数据array格式

    MongoClient.connect(url, function (err, client) {
      client
        .db("example")
        .collection("table1")
        .insertMany([
          { name: "张红2" },
          { name: "张红3" },
          { name: "张红4" },
          { name: "张红5" },
        ])
        .then(
          function (result) {},
          function (err) {
            console.log(err.message);
          }
        );
    });
    
    

    向集合中删除一条数据

    removeOne(json):插入一组数据json格式

    如果集合中有多个name是张三丰的,默认只会删除第一条数据。

    MongoClient.connect(url, function (err, client) {
      client
        .db("example")
        .collection("table1")
        .removeOne({ name: "张三丰" })
        .then(
          function (result) {},
          function (err) {
            console.log(err.message);
          }
        );
    });
    
    

    向集合中批量删除一组数据

    deleteMany(json):插入一组数据json格式,符合条件的都会被删除。

    MongoClient.connect(url, function (err, client) {
      client
        .db("example")
        .collection("table1")
        .deleteMany({ name: "张三丰" })
        .then(
          function (result) {},
          function (err) {
            console.log(err.message);
          }
        );
    });
    
    

    向集合中修改一条数据

    updateOne(json, { $set: newJson }): json需要更新数据的条件,newJson新数据的内容

    如果集合中有多个name是张三丰的,默认只会删除第一条数据。

    MongoClient.connect(url, function (err, client) {
      client
        .db("example")
        .collection("table1")
        .updateOne({ name: "张三丰" }, {
                $set: { name: "小鱼儿"},
              })
        .then(
          function (result) {},
          function (err) {
            console.log(err.message);
          }
        );
    });
    
    

    .updata方法针对不同的数据有不同的运算符可以直接使用,方便快捷。

    字段更新运算符

    字段更新运算符:

    • $inc : 增加指定字段的值
    • $mul : 将字段的值乘以数字
    • $rename : 更新一个字段的名称
    • $setOnInsert : 插入数据默认值
    • $set : 设置一个字段的值
    • $unset : 删除某个字段
    • $min : 赋值最小值
    • $max : 赋值最大值
    • $currentDate : 日期操作

    详情请访问英文官网

    $inc 增加指定字段的值

    例如:
    有这样一个数据

    {
      _id: 1,
      sku: "abc123",
      quantity: 10,
      metrics: {
        orders: 2,
        ratings: 3.5
      }
    }
    

    以下updateOne()操作使用 $inc运算符将quantity字段减小2 (即增加-2),并将metrics.orders字段增大1:

    db.products.updateOne(
       { sku: "abc123" },
       { $inc: { quantity: -2, "metrics.orders": 1 } }
    )
    

    更新后的文档类似于:

    {
       "_id" : 1,
       "sku" : "abc123",
       "quantity" : 8,
       "metrics" : {
          "orders" : 3,
          "ratings" : 3.5
       }
    }
    
    $mul 将字段的值乘以数字

    例如:
    有这样一个数据

    { _id: 1, item: "ABC", price: 10.99 }
    

    以下updateOne()操作使用 $mul运算符将price字段乘以1.25

    db.products.updateOne(
       { _id: 1 },
       { $mul: { price: 1.25 } }
    )
    

    更新后的文档类似于:

    { _id: 1, item: "ABC", price: 13.7375 }
    
    $rename 更新一个字段的名称

    例如:

    有这样一个数据

    {
      "_id": 1,
      "alias": [ "The American Cincinnatus", "The American Fabius" ],
      "mobile": "555-555-5555",
      "nmae": { "first" : "george", "last" : "washington" }
    }
    
    {
      "_id": 2,
      "alias": [ "My dearest friend" ],
      "mobile": "222-222-2222",
      "nmae": { "first" : "abigail", "last" : "adams" }
    }
    
    {
      "_id": 3,
      "alias": [ "Amazing grace" ],
      "mobile": "111-111-1111",
      "nmae": { "first" : "grace", "last" : "hopper" }
    }
    

    此操作将字段重命名nmaename

    db.students.updateMany( {}, { $rename: { "nmae": "name" } } )
    

    如果属性是一个对象里面的属性,使用对象属性的写法,如:db.students.update( { _id: 1 }, { $rename: { "name.first": "name.fname" } } )
    更新后的文档类似于:

    {
      "_id": 1,
      "alias": [ "The American Cincinnatus", "The American Fabius" ],
      "mobile": "555-555-5555",
      "name": { "first" : "george", "last" : "washington" }
    }
    
    {
       "_id" : 2,
       "alias" : [ "My dearest friend" ],
       "mobile" : "222-222-2222",
       "name" : { "first" : "abigail", "last" : "adams" }
    }
    
    { "_id" : 3,
      "alias" : [ "Amazing grace" ],
      "mobile" : "111-111-1111",
      "name" : { "first" : "grace", "last" : "hopper" } }
    
    $setOnInsert 插入数据默认值

    如果upsert:true的时候,更新操作导致的是新插入的文档,之前没有过这个数据的,则$setOnInsert将指定的值分配给文档中的字段,也就是$setOnInsert才会生效。如果更新操作没有导致插入新文档,也就是在旧的数据上进行修改,则$setOnInsert不执行任何操作。
    upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
    multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
    例如:

    以下updateOne()操作使用 $setOnInsert更新

    db.products.updateOne(
      { _id: 1 },
      {
         $set: { item: "apple" },
         $setOnInsert: { defaultQty: 100 }
      },
      { upsert: true }
    )
    
    

    更新后的文档类似于:

    { "_id" : 1, "item" : "apple", "defaultQty" : 100 }
    
    $set 设置一个字段的值

    例如:
    有这样一个数据

    {
      _id: 100,
      sku: "abc123",
      quantity: 250,
      instock: true,
      reorder: false,
      details: { model: "14Q2", make: "xyz" },
      tags: [ "apparel", "clothing" ],
      ratings: [ { by: "ijk", rating: 4 } ]
    }
    

    对于符合_id等于的条件的文档100,以下操作将使用$set运算符来更新quantity字段,details字段和tags 字段的值。

    db.products.updateOne(
       { _id: 100 },
       { $set:
          {
            quantity: 500,
            details: { model: "14Q3", make: "xyz" },
            tags: [ "coats", "outerwear", "clothing" ]
          }
       }
    )
    

    该操作将以下值替换为:quantityto 500; 该 details字段到一个新的嵌入的文档,并且tags字段到一个新的数组。

    $unset 删除某个字段,如果字段不存在,则不会影响操作

    例如:

    以下updateOne()操作使用 $unset 删除quantity和instock两个字段

    db.products.updateOne(
       { sku: "unknown" },
       { $unset: { quantity: "", instock: "" } }
    )
    
    $min 赋值最小数

    如果指定的值小于字段的当前值,(min会将该字段的值更新为指定值。)min运算符可以使用BSON比较顺序比较不同类型的值。
    简单的说就是如果新值比旧值小的时候才会生效,否则不会更新。
    例如:
    原数据

    { _id: 1, highScore: 800, lowScore: 200 }
    

    以下updateOne()操作使用 $min 更新lowScore的值为150,只有新值比旧值小的时候才会生效,否则不会更新

    db.products.updateOne(
       { _id: 1 }, { $min: { lowScore: 150 } }
    )
    
    $max 赋值最大数

    如果指定的值大于字段的当前值,(max会将该字段的值更新为指定值。)max运算符可以使用BSON比较顺序比较不同类型的值。
    简单的说就是如果新值比旧值大的时候才会生效,否则不会更新。
    例如:
    原数据

    { _id: 1, highScore: 800, lowScore: 200 }
    

    以下updateOne()操作使用 $max 更新highScore的值为950,只有新值比旧值大的时候才会生效,否则不会更新

    db.products.updateOne(
       { _id: 1 }, { $max: { highScore: 950 } }
    )
    

    数组更新运算符

    数组更新运算符:

    • $
    • $addToSet
    • $pop
    • $pullAll
    • $pull
    • $pushAll
    • $push
    • $each
    • $slice
    • $sort
    • $position
    $
    $addToSet
    $pop
    $pullAll
    $pull
    $pushAll
    $push
    $each
    $slice
    $sort
    $position

    向集合中批量修改一组数据

    updateMany(json, { $set: newJson }): json需要更新数据的条件,newJson新数据的内容。只要符合条件的数据都会被修改更新。

    MongoClient.connect(url, function (err, client) {
      client
        .db("example")
        .collection("table1")
        .updateMany({ name: "张三丰" }, {
                $set: { name: "小鱼儿"},
              })
        .then(
          function (result) {},
          function (err) {
            console.log(err.message);
          }
        );
    });
    
    

    获取集合中的一组数据

    find(json,projection): json是需要更新数据的条件。只要符合条件的数据都会被返回,{}是返回所有数据,projection是可选项,指定匹配数据中返回哪些字段,{ projection: { article_id: 1, name: 0 }, 1true是显示字段,0false是不显示,。

    注意:find({}, { projection: { article_id: 1 }})要这样写,官网都没有写成{ projection: {xxxx}}这样,所以一直没有生效,有可能是MongoDB版本问题吧

    MongoClient.connect(url, function (err, client) {
      client
        .db("example")
        .collection("table1")
        .find({ name: "张三丰" })
        .toArray()
        .then(
          function (result) {
            result.forEach(function (value, index, arr) {
              console.log(value);
            });
          },
          function (err) {
            console.log(err.message);
          }
        );
    });
    
    
    db.集合名.count():指定集合文档数量 
    db.集合名.find().count() : 根据条件查找数量
    db.集合名.find({userName:/张/}):模糊查找。查找名字当中包含常
    db.集合名.find({age:{$gt:12}}):查找年龄大于12
        $gt:大于
        $gte:大于等于
        $lt:小于
        $lte:小于等于
        $ne:不等于
    db.集合名.find({age:{$ne:12},sex:"女"}):多条件,年龄不等于12,性别为女
    或
    db.集合名.find({$or:[{sex:"女"},{age:12}]}):查找性别为女,或年龄为12的记录
    db.集合名.find().skip(2):跳指指定的文档数(跳过前两行文档)
    db.集合名.find().limit(3):取指定的文档数(取前三行文档)
    db.集合名.find().sort({age:-1}):按照年龄的倒序。1正序,-1倒序
    db.集合名.find().sort({age:-1,"score.yuwen":1}):按照年龄的倒序,如果年龄相同,按照语文的正序
    db.集合名.findAndModify(query,sort,update,[options],callback)
    对于query参数匹配的文档进行修改。sort参数确定哪些对象先被修改。update参数指定要在文档上进行的更改,回调函数接收err,res
    db.集合名.findAndRemove(query,sort,[options],callback)
    删除与query匹配的字符串,sort决定哪些字符串先被修改,callback接收err和res
    db.集合名.distinct(key,[query],callback)
    在集合中为一个特定的文档key创建不同的值的列表。如果指定query参数那么只有与query匹配的文档在内。回调函数接受error,values
    db.集合名.count([query],callback)
    计算集合中文档的数量,
    db.集合名.drop(callback) 
    删除当前集合
    db.集合名.stats(callback)
    获取集合的统计信息,包括条目数量,在磁盘上的大小,平均对象大小,以及更多的信息。
    
    
    
    

    分页操作

        已知:
            1、pageIndex:指定的页数
            2、count:文档数量
            3、pageSum:总页数      pageSum = Math.ceil(count/pageNum)
            4、pageNum:每页显示的条数
        求:
            每页要显示的内容。
        问:总条数9,每页2条,每一页的内容如何求
            skip = (pageIndex-1)*pageNum;
            1、 db.score.find().sort({age:-1}).skip(0).limit(2)
            2、 db.score.find().sort({age:-1}).skip(2).limit(2)
            3、 db.score.find().sort({age:-1}).skip(4).limit(2)
            4、 db.score.find().sort({age:-1}).skip(6).limit(2)
            4、 db.score.find().sort({age:-1}).skip(8).limit(2)
    
    

    获取集合中的全部数据

    find(json): json需要更新数据的条件。只要符合条件的数据都会被返回。

    只要传入的json是个空对象,就会返回所有数据了

    MongoClient.connect(url, function (err, client) {
      client
        .db("example")
        .collection("table1")
        .find({})
        .toArray()
        .then(
          function (result) {
            result.forEach(function (value, index, arr) {
              console.log(value);
            });
          },
          function (err) {
            console.log(err.message);
          }
        );
    });
    
    

    读取大于100条数据的时候会出现报错官网解释,可以尝试用forEach代替

    MongoClient.connect(url, function (err, client) {
      client
        .db("example")
        .collection("table1")
        .find({})
        .forEach()
        .then(
          function (result) {
            result.forEach(function (value, index, arr) {
              console.log(value);
            });
          },
          function (err) {
            console.log(err.message);
          }
        );
    });
    

    封装的操作MongoDB库

    /* 
     封装DB库操作
     */
    
    // 引入MongoDB 模块
    const MongoDB = require("mongodb");
    // 引入MongoDB 连接模块
    const MongoClient = MongoDB.MongoClient;
    // 引入MongoDB ObjectID模块
    const ObjectID = MongoDB.ObjectID;
    // 引入配置文件
    const Config = require("./MongoDB.config.js");
    
    class Db {
      // 单例模式,解决多次实例化时候每次创建连接对象不共享的问题,实现共享连接数据库状态
      static getInstance() {
        if (!Db.instance) {
          Db.instance = new Db();
        }
        return Db.instance;
      }
      constructor() {
        // 属性 存放db对象
        this.dbClient = "";
        // 实例化的时候就连接数据库,增加连接数据库速度
        this.connect();
      }
      // 连接数据库
      connect() {
        return new Promise((resolve, reject) => {
          // 解决数据库多次连接的问题,要不然每次操作数据都会进行一次连接数据库的操作,比较慢
          if (!this.dbClient) {
            // 第一次的时候连接数据库
            MongoClient.connect(Config.dbUrl, (err, client) => {
              if (err) {
                reject(err);
              } else {
                // 将连接数据库的状态赋值给属性,保持长连接状态
                this.dbClient = client.db(Config.dbName);
                resolve(this.dbClient);
              }
            });
          } else {
            // 第二次之后直接返回dbClient
            resolve(this.dbClient);
          }
        });
      }
    
      /**
       * 查询数据库
       * 使用方法: let result = await DB.find('user',{});
       * @param {String} collectionName 集合名称、数据表名
       * @param {Object} json 查询的条件
       */
      find(collectionName, json) {
        return new Promise((resolve, reject) => {
          this.connect().then((db) => {
            // 操作db库里的某一个表,返回符合条件的内容,json查找的条件
            let result = db.collection(collectionName).find(json);
            result.toArray(function (err, docs) {
              if (err) {
                reject(err);
                return;
              }
              resolve(docs);
            });
          });
        });
      }
    
      /**
       * 更新数据库,多个符合条件的只会更新第一条数据
       * 使用方法: let result = await DB.update('user',{'username':'lisi'},{'username':'李四'});
       * @param {String} collectionName 集合名称、数据表名
       * @param {Object} json1 需要更新数据的条件
       * @param {Object} json2 新数据的内容
       */
      update(collectionName, json1, json2) {
        return new Promise((resolve, reject) => {
          this.connect().then((db) => {
            // 操作db库里的某一个表,更新一条数据,json1查找的内容,json2更新的新内容,回调函数
            db.collection(collectionName).updateOne(
              json1,
              {
                $set: json2,
              },
              (err, result) => {
                if (err) {
                  reject(err);
                } else {
                  resolve(result);
                }
              }
            );
          });
        });
      }
    
      /**
       * 更新数据库,所有符合条件的都会被更新
       * 使用方法: let result = await DB.updateMany('user',{'username':'lisi'},{'username':'李四'});
       * @param {String} collectionName 集合名称、数据表名
       * @param {Object} json1 需要更新数据的条件
       * @param {Object} json2 新数据的内容
       */
      updateMany(collectionName, json1, json2) {
        return new Promise((resolve, reject) => {
          this.connect().then((db) => {
            // 操作db库里的某一个表,更新一条数据,json1查找的内容,json2更新的新内容,回调函数
            db.collection(collectionName).updateMany(
              json1,
              {
                $set: json2,
              },
              (err, result) => {
                if (err) {
                  reject(err);
                } else {
                  resolve(result);
                }
              }
            );
          });
        });
      }
    
      /**
       * 插入数据库
       * 使用方法: let result = await DB.insert('user',{'username':'赵六666','age':30,'sex':'女','status':'2'});
       * @param {String} collectionName 集合名称、数据表名
       * @param {Object} json 插入的新数据
       */
      insert(collectionName, json) {
        return new Promise((resolve, reject) => {
          this.connect().then((db) => {
            // 操作db库里的某一个表,插入一条数据,json插入的新内容,回调函数
            db.collection(collectionName).insertOne(json, (err, result) => {
              if (err) {
                reject(err);
              } else {
                resolve(result);
              }
            });
          });
        });
      }
    
      /**
       * 批量插入数据库,数组里的每一个对象都是一条数据,会有各自的_id索引
       * 使用方法: let result = await DB.insertMany('user',[{'username':'赵六666','age':30,'sex':'女','status':'2'},{'username':'赵六666','age':30,'sex':'女','status':'2'},{'username':'赵六666','age':30,'sex':'女','status':'2'}...]);
       * @param {String} collectionName 集合名称、数据表名
       * @param {Array} json 批量插入的新数据
       */
      insertMany(collectionName, arr) {
        return new Promise((resolve, reject) => {
          this.connect().then((db) => {
            // 操作db库里的某一个表,批量插入一组数据,arr批量插入的新内容,回调函数
            db.collection(collectionName).insertMany(arr, (err, result) => {
              if (err) {
                reject(err);
              } else {
                resolve(result);
              }
            });
          });
        });
      }
    
      /**
       * 删除数据,多个符合条件的只会删除第一条数据
       * 使用方法: let result = await DB.remove('user',{'username':'李四'});
       * @param {String} collectionName 集合名称、数据表名
       * @param {Object} json 删除数据的条件
       */
      remove(collectionName, json) {
        return new Promise((resolve, reject) => {
          this.connect().then((db) => {
            db.collection(collectionName).removeOne(json, (err, result) => {
              if (err) {
                reject(err);
              } else {
                resolve(result);
              }
            });
          });
        });
      }
    
      /**
       * 批量删除一组数据,多个符合条件的都会被删除
       * 使用方法: let result = await DB.deleteMany('user',{'username':'李四'});
       * @param {String} collectionName 集合名称、数据表名
       * @param {Object} json 删除数据的条件
       */
      deleteMany(collectionName, json) {
        return new Promise((resolve, reject) => {
          this.connect().then((db) => {
            db.collection(collectionName).deleteMany(json, (err, result) => {
              if (err) {
                reject(err);
              } else {
                resolve(result);
              }
            });
          });
        });
      }
    
      /**
       * 通过id查询数据时候需要用到此方法,MongoDB里面查询_id ,把字符串转换成对象
       * MongoDB数据库里的_id是自动生成的,通过dind方法查询结果可以看到形式如: {"_id": ObjectId("5aad299bc166236421c99d229")},直接传入5aad299bc166236421c99d229,是查询不到结果的,所以需要包装一下
       * 使用方法: let result = await DB.find('user',{'_id': DB.getObjectID(xxxxx)});
       * @param {String} id 要查询的id
       */
      getObjectID(id) {
        return new ObjectID(id);
      }
    }
    module.exports = Db.getInstance();
    
    
    
  • 相关阅读:
    浅谈值对象
    循环一个节点列表(NodeList)或者数组,并且绑定事件处理函数引发对闭包的理解
    当前窗口和Iframe之间的相互访问(图片上传成功后立刻显示在当前页面上)
    网页动态加载图片 通过JS和jquery实现。
    javascript拖动层函数封装
    javascript中变量声明提升(Hoisting)
    运动框架必备的运动算法 留着用!
    CSS3特性之改变在浏览器上选中文字时,默认的背景颜色和文字颜色
    仿淘宝商品图片放大镜效果(鼠标移动上去会出现放大的图片,并且可以移动)
    与PHP交互中文编码的几个函数 decodeURIComponent,encodeURIComponent,encodeURI,decodeURI
  • 原文地址:https://www.cnblogs.com/jiaoshou/p/13940421.html
Copyright © 2011-2022 走看看