Skip to content

Latest commit

 

History

History
563 lines (430 loc) · 19.2 KB

增删改查.md

File metadata and controls

563 lines (430 loc) · 19.2 KB

Mongodb(版本 3.6)

数据库基础操作命令

  1. 使用use关键字创建数据库 use foobar

  2. 查看全部数据 show dbs

  3. 查询数据库中的文档 show collections

  4. 删除集合 db.persons.drop()

  5. 删除数据库 db.dropDatabase()

插入

  1. 插入单条数据 也可以 批量插入

     db.persons.insert({"name":"用户名","sex":"男","phone":"18335187448","level":"等级"})
  2. save操作

    • 如果_id 相同会变成更新操作, 而insert是有插入错误的提示
    db.persons.save({"_id":"0001","name":"用户昵称"})
  3. 插入校验

    插入数据时,MongoDB只对数据进行最基本的检查;检查文档的基本结构,如果没有_id字段。就自动增加一个。检查大小就是其中一项基本结构检查;所有的文档都必须小于16MB。

    //可以使用如下命令查看一个对象的大小
    > var obj = {"title":"这是测试标题","vlaue":"这是测试值"};
    > Object.bsonsize(obj);
    62

删除

  1. 删除列表中所有数据

    remove() 方法已经过时了,现在官方推荐使用 deleteOne() 和 deleteMany() 方法。
    如删除集合下全部文档:
      db.inventory.deleteMany({})
    删除 status 等于 A 的全部文档:
      db.inventory.deleteMany({ status : "A" })
    删除 status 等于 D 的一个文档:
      db.inventory.deleteOne( { status: "D" })
  2. 删除指定条件的数据

    db.persons.remove({"_id":1})
  3. 删除较大数据量的数据, 直接删除该集合并且重新建立索引的办法比直接使用remove的效率高

     db.persons.drop()

更新

注意事项

增加、修改或者删除键时,应该使用$修改器 , 下面的做法实际上会将整个文档用 {"username":"mcyu"} 替换掉。慎之,慎之

db.user.update({"_id":1},{"username":"mcyu"});

update()

  1. db.collection.update(query, update, options)

    详细介绍官网地址 : https://docs.mongodb.com/manual/reference/method/db.collection.update/

    db.collection.update(
       <query>,
       <update>,
       {
         upsert: <boolean>, 	
         multi: <boolean>,
         writeConcern: <document>,
         collation: <document>,
         arrayFilters: [ <filterdocument1>, ... ]
       }
    )
  2. db.documentName.updated({查询器},{修改器},true) 如果存在就更新, 如果不存在就插入

    db.persons.update({"_id":5},{"name":"ceshi","_id":5},true)

更新器

  1. $set 更新器

    如果该字段不存在,$set则会添加具有指定值的新字段,前提是新字段不违反类型约束。如果为不存在的字段指定虚线路径,$set则将根据需要创建嵌入的文档。

    • 如果存在就更新,不存在就创建

      db.users.update({"_id":ObjectId("5b334834c543a54bfe94656b")},{"$set":{"username":"myname"}});
    • 批量更新

      db.persons.update({"name":"ceshi"},{"$set":{"name":"ceshi4"}},false,true);

      20180603111546

    • 修改内嵌文档

      //数据结构
      { "_id" : ObjectId("5b334834c543a54bfe94656b"), "age" : 20, "username" : "machunyu", "books" : { "web" : "css", "server"
       : "PHP" } }
      //执行修改
      db.users.update({"_id":ObjectId("5b334834c543a54bfe94656b")},{"$set":{"books.web":"css"}});
  2. $inc 修改器 $inc 可以对文档的某个值为数字型(只能为满足要求的数字)的键进行增减的操作。 对于更新分析数据,投票或者其他有变化数值的地方。

    • id的自动增长
    增加
        > db.persons.update({"_id":5},{$inc:{"age":1}})
        WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
        > db.persons.find();
        { "_id" : "1", "name" : "码处", "value" : "测试" }
        { "_id" : "2", "name" : "码处2", "value" : "测试2" }
        { "_id" : "3", "name" : "码处3", "value" : "测试3" }
        { "_id" : 4, "name" : "ceshi5" }
        { "_id" : 5, "name" : "ceshi5", "age" : 11 }
        >
    减少
    	> db.persons.update({"_id":5},{$inc:{"age":-2}})
        WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
        > db.persons.find();
        { "_id" : "1", "name" : "码处", "value" : "测试" }
        { "_id" : "2", "name" : "码处2", "value" : "测试2" }
        { "_id" : "3", "name" : "码处3", "value" : "测试3" }
        { "_id" : 4, "name" : "ceshi5" }
        { "_id" : 5, "name" : "ceshi5", "age" : 9 }
        >
  3. $unset 主要是用来删除键。

    > db.persons.update({"_id":5},{$unset:{"age":1}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.persons.find()
    { "_id" : "1", "name" : "码处", "value" : "测试" }
    { "_id" : "2", "name" : "码处2", "value" : "测试2" }
    { "_id" : "3", "name" : "码处3", "value" : "测试3" }
    { "_id" : 4, "name" : "ceshi5" }
    { "_id" : 5, "name" : "ceshi5" }
  4. $push 数组修改器

    • 如果指定的键是数组, 则追加新的数组

      追加新的数组    
      	> db.persons.insert({"_id":6,"books":[]})
          WriteResult({ "nInserted" : 1 })
          > db.persons.find();
          { "_id" : 6, "books" : [ ] }
          > db.persons.update({"_id":6},{$push:{"books":"js"}})
          WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
      
          > db.persons.find();
          { "_id" : 6, "books" : [ "js" ] }
      
          > db.persons.update({"_id":6},{$push:{"books":"php"}})
          WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
      
          > db.persons.find();
          { "_id" : 6, "books" : [ "js", "php" ] }
    • 如果指定的键不是数组则中断当前操作

    • 如果不存在指定的键, 则创建数组类型的键值对

      不存在则新加
      	> db.persons.update({"_id":6},{$push:{"class":"01"}})
          WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
      
          > db.persons.find()
          { "_id" : 6, "books" : [ "js", "php" ], "class" : [ "01" ] }
    • 批量添加数组数据

      批量添加数据
      db.persons.update(
      		{"_id":6},
      		{$push:{class:{$each:[2,3,4]}}}
      	)
    • 如果希望数组的最大长度是固定的,那么可以将 $slice$push 组合在一起使用,这样就可以保证数组不会超出设定好的最大长度,这实际上就得到了一个最多包含N个元素的数组;

      //这个操作会将最先添加的那个给删除掉,限制 10 个
      db.movies.update(
      	{"genre":"horror"},
      	{"$push":{"top10":{"$each":["Nightmare on Elm Stree","Saw"],"$slice":-10}}});
      //这样就可以控制删除那个元素
      db.movies.update(
      	{"genre":"horror"},
      	{"$push":{"top10":{"$each":[{"name":"Nightmare on Elm Stree","rating":6.6},{"name":"Saw","rating":7.0}],"$slice":-10},"$sort":{"rating":-1}}});
      //从第4条开始显示两条数据
      db.shop_msg.find({"_id":ObjectId("5b6bb700b08d0d3fa0766e4e")},{"reply":{"$slice":[4,2]}}).pretty();
      //显示最新的3条。
      db.shop_msg.find({"_id":ObjectId("5b6bb700b08d0d3fa0766e4e")},{"reply":{"$slice":-3}}).pretty();
  5. $addToSet操作符为数组添加一个值,如果该值已经存在$ addToSet对该数组不做任何操作。

    db.persons.update({"_id":6},{$addToSet:{"class":js}})
    • 可以实现如果存在js,就不会写入js了, 只会将db写入, 批量判断式的导入

      db.persons.update({"_id":6},{$addToSet:{class:{$each:["js","db"]}}})
    • $addToSet$each 组合起来可以实现一次性添加多个不同的数据

  6. $pop 操作符删除数组的第一个或最后一个元素。

    //删除数组的第一个元素 
    db.persons.update({"_id":6},{$pop:{"class":-1}}); 
    //删除数组的最后一个元素
     db.persons.update({"_id":6},{$pop:{"class":1}});
  7. $pull 操作符从现有数组中删除与指定条件匹配的一个或多个值

    > db.persons.find();
    { "_id" : "1", "name" : "码处", "value" : "测试" }
    { "_id" : "2", "name" : "码处2", "value" : "测试2" }
    { "_id" : "3", "name" : "码处3", "value" : "测试3" }
    { "_id" : 4, "name" : "ceshi5" }
    { "_id" : 5, "name" : "ceshi5" }
    { "_id" : 6, "books" : [ "php" ], "class" : [ 3, 4, 8, 9 ] }
    > db.persons.update({"_id":6},{$pull:{"class":8}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.persons.find();
    { "_id" : "1", "name" : "码处", "value" : "测试" }
    { "_id" : "2", "name" : "码处2", "value" : "测试2" }
    { "_id" : "3", "name" : "码处3", "value" : "测试3" }
    { "_id" : 4, "name" : "ceshi5" }
    { "_id" : 5, "name" : "ceshi5" }
    { "_id" : 6, "books" : [ "php" ], "class" : [ 3, 4, 9 ] }
  8. $pullAll() 批量删除数据

    > db.persons.find();
    { "_id" : "1", "name" : "码处", "value" : "测试" }
    { "_id" : "2", "name" : "码处2", "value" : "测试2" }
    { "_id" : "3", "name" : "码处3", "value" : "测试3" }
    { "_id" : 4, "name" : "ceshi5" }
    { "_id" : 5, "name" : "ceshi5" }
    { "_id" : 6, "books" : [ "php" ], "class" : [ 3, 4, 9 ] }
    > db.persons.update({"_id":6},{$pullAll:{"class":[3,4]}});
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.persons.find();
    { "_id" : "1", "name" : "码处", "value" : "测试" }
    { "_id" : "2", "name" : "码处2", "value" : "测试2" }
    { "_id" : "3", "name" : "码处3", "value" : "测试3" }
    { "_id" : 4, "name" : "ceshi5" }
    { "_id" : 5, "name" : "ceshi5" }
    { "_id" : 6, "books" : [ "php" ], "class" : [ 9 ] }
    >
  9. $ 用来定位查询文档已经匹配的数组元素,并进行更新。

    {"_id":1,"comments":{
    	{"comment":"good post","author":"john","vote":1},
    	{"comment":"I thought it was too short","author":"Tom","vote":6},
    }}
    
    //想要将这条数据中 author 为 john 的 vote 更新成 2
    db.persons.update({"comments.author":"john"},{$set:{"comments.$.vote":2}});
  10. runCommand() 用来执行数据操作语句

> db.runCommand({
... "findAndModify":"persons",
... "query":{"name" :"码处"},
... "update":{"$set":{"age":100}},
... "new":true   //返回更新前的还是更新后的文档
... })
{
        "lastErrorObject" : {
                "n" : 1,
                "updatedExisting" : true
        },
        "value" : {
                "_id" : "1",
                "name" : "码处",
                "value" : "测试",
                "age" : 100
        },
        "ok" : 1
}
> db.persons.find();
{ "_id" : "1", "name" : "码处", "value" : "测试", "age" : 100 }
{ "_id" : "2", "name" : "码处2", "value" : "测试2" }
{ "_id" : "3", "name" : "码处3", "value" : "测试3" }
{ "_id" : 4, "name" : "ceshi5" }
{ "_id" : 5, "name" : "ceshi5" }
{ "_id" : 6, "books" : [ "php" ], "class" : [ "js", "db" ] }
>

修改器速度

  1. $inc 能就地修改,因为不需要改变文档的大小,只需要将键的值修改一下(对文档大小的改变非常小),所以非常快,而数据修改器可能会改变文档的大小,就会慢一些。
  2. 将文档插入到MongoDB中时, 依次插入的文档在磁盘早上的位置是相邻的。因此,如果一个文档变大,原先的位置就放不下这个文档了,这个文档就会移动到集合中的另一个位置。

upsert

  1. upsert 是一种特殊的更新。要是没有找到符合更新条件的文档,就会以这个条件和更新文档为基础创建一个新的文档。如果找到就正常更新。同一套代码既可以用于创建文档有可以用于更新文档。而且upsert能够保证原子性。

  2. 应用场景

    记录网站页面访问次数,要是没有upsert,就得试着查询 URL,没有找到就得新建一个文档,找到的话就增加访问次数。这就是说如果有人访问页面,我们得先对数据库进行查询,然后选择更新或者插入。要是多个进程同时运行,还会遇到同时对URL插入多个文档这样的竞态条件。

findAndModify函数

  1. 修改并返回单个文档。默认情况下,返回的文档不包括对更新所做的修改。要返回包含对更新所做修改的文档,请使用该new选项。

    db.collection.findAndModify({
        query: <document>,
        sort: <document>,
        remove: <boolean>,
        update: <document>,
        new: <boolean>,
        fields: <document>,
        upsert: <boolean>,
        bypassDocumentValidation: <boolean>,
        writeConcern: <document>,
        collation: <document>,
        arrayFilters: [ <filterdocument1>, ... ]
    });
  2. 参数说明

    query 查询的文档,用于检索文档的条件

    sort 排序结果的条件

    update 修改器文档,用于对匹配的文档进行更新(remove 或者 update 必须指定一个)。

    remove 布尔类型, 表示是否删除文档。

    new 布尔类型 , 表示返回更新前的文档还是更新后的文档。默认是更新前的文档

    fields 文档中需要返回的字段 (可选)

    upsert 布尔类型,如果为true,则findAndModify(): 如果没有文档与查询匹配,则创建一个新文档。

查询

指定返回的键

  1. db.documentName.find({条件},{需要返回的键});

    > db.persons.find({},{"email":1});
    { "_id" : ObjectId("5b13a92ca37be50e60cb406b"), "email" : "[email protected]" }
    { "_id" : ObjectId("5b13a954a37be50e60cb406c"), "email" : "[email protected]" }
    { "_id" : ObjectId("5b13a976a37be50e60cb406d"), "email" : "[email protected]" }
    { "_id" : ObjectId("5b13a9a4a37be50e60cb406e"), "email" : "[email protected]" }
    { "_id" : ObjectId("5b13a9b1a37be50e60cb406f"), "email" : "[email protected]" }
    > db.persons.find({},{"email":1,"_id":0});
    { "email" : "[email protected]" }
    { "email" : "[email protected]" }
    { "email" : "[email protected]" }
    { "email" : "[email protected]" }
    { "email" : "[email protected]" }
  2. 查询用到的 find() 和 findOne() 两种方式。

    db.persons.find()
    { "_id" : ObjectId("5b12ba34ea0972c724e10b5d"), "name" : "测试" }
    
    查看一条数据
    db.persons.findOne()
    { "_id" : ObjectId("5b12ba34ea0972c724e10b5d"), "name" : "测试" }

查询条件

  1. 小于("$lt")、小于等于("$lte")、大于("$gt")、大于等于("$gte")、不等于("$ne") 。

    //查询年龄大于20且小于30的用户  
    db.users.find({"age":{$gt:20,"$lte":23}})
  2. $in$or 。对单一键有多个值与其匹配的话就用"$in",后面跟一个条件数组。

    查询在一个范围
    > db.users.find({"age":{$in:[23,24]}})
    { "_id" : 2, "name" : "brob", "age" : 23, "friends" : 4 }
    { "_id" : 3, "name" : "robin", "age" : 24, "friends" : 23 }
    查询不在一个范围
    > db.users.find({"age":{$nin:[23]}})
    { "_id" : 3, "name" : "robin", "age" : 24, "friends" : 23 }
    查询或者这个或者那个
    > db.users.find({"$or":[{"age":23},{"name":"robin"}]});
    { "_id" : 2, "name" : "brob", "age" : 23, "friends" : 4 }
    { "_id" : 3, "name" : "robin", "age" : 24, "friends" : 23 }
    >
  3. Null的用法

    > db.users.find();
    { "_id" : 2, "name" : "brob", "age" : 23, "friends" : 4, "sex" : "n" }
    { "_id" : 3, "name" : "robin", "age" : 24, "friends" : 23 }
    > db.users.find({"sex":{"$in":[null]}});
    { "_id" : 3, "name" : "robin", "age" : 24, "friends" : 23 }
    >
    
    //结合$exists 获取 字段为null的数据
    db.users.find({"genre":{"$in":[null],"$exists":true}});

数组查询

  1. $all

    查询数组中有PHP  JS 字段的数据
    > db.users.find({booke:{"$all":["JS""PHP"]}});
    { "_id" : 3, "name" : "robin", "age" : 24, "friends" : 23, "booke" : [ "JS", "Mongodb", "PHP" ] }
    { "_id" : 2, "name" : "brob", "age" : 23, "friends" : 4, "sex" : "n", "booke" : [ "JS", "PHP", "JAVA" ] }
  2. 查询数组中第几个值

    查询第一本书是JS的人
    > db.users.find({"booke.0":"JS"},{"booke":1,"_id":0});
    { "booke" : [ "JS", "Mongodb", "PHP" ] }
    { "booke" : [ "JS", "PHP", "JAVA" ] }
    查询用户第二本书是Mongodb的人
    > db.users.find({"booke.1":"Mongodb"},{"booke":1,"_id":0});
    { "booke" : [ "JS", "Mongodb", "PHP" ] }
  3. $size 查询数组中的长度

    这个查询器不能与比较查询符一块使用

    //查询用户的书是4本的
    > db.users.find();
    { "_id" : 3, "name" : "robin", "age" : 24, "friends" : 23, "booke" : [ "JS", "Mongodb", "PHP" ] }
    { "_id" : 2, "name" : "brob", "age" : 23, "friends" : 4, "sex" : "n", "booke" : [ "JS", "PHP", "JAVA", "MySQL" ] }
    
    > db.users.find({"booke":{$size:4}},{"booke":1,"_id":0});
    { "booke" : [ "JS", "PHP", "JAVA", "MySQL" ] }
  4. 查询书籍数量大于3本的学生

    • 第一步添加一个size字段

    • 第二部在每次添加或者删除同时将size字段修改

    • 使用字段size来查询大于或者小于

      > db.users.find();
      { "_id" : 2, "name" : "brob", "age" : 23, "friends" : 4, "sex" : "n", "booke" : [ "JS", "PHP", "JAVA", "MySQL" ], "size" : 4 }
      { "_id" : 3, "name" : "robin", "age" : 24, "friends" : 23, "booke" : [ "JS", "Mongodb", "PHP" ], "size" : 3 }
  5. $slice 操作返回文档中指定数组的内部值

    返回第二本和第三本书
    > db.users.find({"name":"robin"},{"booke":{"$slice":[1,2]},"_id":0})
    { "name" : "robin", "age" : 24, "friends" : 23, "booke" : [ "Mongodb", "PHP" ], "size" : 3 }
    
    返回最后一本书
    > db.users.find({"name":"robin"},{"booke":{"$slice":-1},"_id":0})
    { "name" : "robin", "age" : 24, "friends" : 23, "booke" : [ "PHP" ], "size" : 3 }

对嵌套文档的查询(对象数组查询$elemMatch)

//查找数组中 school 是 k 的并且score 是 A 的;
db.users.find(school:{$elemMatch:{"school":"k","score":"A"}});

分页

//查询一条数据
db.users.find().limit(1)

//查询一条数据 跳过一条数据
> db.users.find().limit(1).skip(1)
{ "_id" : 3, "name" : "robin", "age" : 24, "friends" : 23, "booke" : [ "JS", "Mongodb", "PHP" ], "size" : 3 }

_skip 会有性能问题可以使用前后台多带一个 id 字段。

db.users.find({"_id":{$gt:1}}).limit(3)

排序

正序排序
> db.users.find().limit(2).sort({"age":1});
{ "_id" : 2, "name" : "brob", "age" : 23, "friends" : 4, "sex" : "n", "booke" : [ "JS", "PHP", "JAVA", "MySQL" ], "size" : 4 }
{ "_id" : 3, "name" : "robin", "age" : 24, "friends" : 23, "booke" : [ "JS", "Mongodb", "PHP" ], "size" : 3 }
倒序排序
> db.users.find().limit(2).sort({"age":-1});
{ "_id" : 3, "name" : "robin", "age" : 24, "friends" : 23, "booke" : [ "JS", "Mongodb", "PHP" ], "size" : 3 }
{ "_id" : 2, "name" : "brob", "age" : 23, "friends" : 4, "sex" : "n", "booke" : [ "JS", "PHP", "JAVA", "MySQL" ], "size" : 4 }