zoukankan      html  css  js  c++  java
  • MongoDB:文档增删改查

    Document文档

    在MongoDB中文档是指多个键及其关联的值有序地放置在一起就是文档,其实指的就是数据。

    MongoDB中的文档地数据结构和JSON基本一样,所有存储在集合中地数据都是BSON。

    新增文档

    insert

    此方法是插入文档最常用的方法,可以插入单条或多条文档。

    语法格式:

    db.collection.insert(
    <document or documents>,
    {
    	writeConcern:<document>,
    	ordered:<boolean>
    }
    )
    

    参数说明:

    document or documents:一条文档或多条文档

    • 一条:{doc}
    • 多条:[{doc1},{doc2}...]

    writeConcern:可选参数,表示是否使用写入策略,该策略较为复杂,这里暂不讨论

    ordered:是否为有序插入,默认为true

    • true:文档中有一个发生错误,mongodb将不再继续插入后续文档
    • false:当文档有一个发生错误,不会影响后续文档地插入
    db.user.insert(
    [{ 'name':'wj','age':23},{'name':'zhangsan','age':20}]
    )
    

    image-20210110165048522

    save

    save也可以插入一条或多条文档,但是insert方法插入主键相同的文档时会报错,而使用save方法插入主键相同的文档时则会覆盖原文档。

    db.collection.save(
    <document or documents >,
    {
    	writeConcern:<document>
    }
    )
    

    insertOne

    insertOne只能插入一条文档,如果使用该方法插入多条文档,则mongodb只会新增第一条文档。

    db.collection.insertOne(
    <document>,
    {
    	writeConcern:<document>
    }
    )
    

    insertMany

    该方法可以插入多个文档,语法与insert方法一样,插入成功后,会返回插入文档的主键。

    image-20210110165645134

    注意,使用insertMany插入单条文档,也必须用中括号括起来,否则报错。

    image-20210110170041454

    变量定义和使用

    test_user=({ 'name':'wj','age':23})
    db.user.insert(test_user)
    test_user2=([{ 'name':'wj','age':23},{ 'name':'wj2','age':24}])
    db.user.insertMany(test_user2)
    

    image-20210110170615689

    查询文档

    find

    语法格式:

    db.collection.find(<query>,<projection>);
    

    参数说明:

    • 如果不指定参数(参数为空,则查询该集合中所有文档)
    • query:查询条件
    • projection:该参数可以指定查询结果中需要显示的字段,设置为1,表示显示,为0,则不显示。"_id"字段默认显示。当设置"_id"为1时,其他字段必须为1,否则报错。

    image-20210110172614076

    查询name等于zhangsan,age等于20的文档:

    db.user.find({'name':'zhangsan','age':20})
    

    image-20210110172829459

    比较操作符

    • 小于 $lt
    • 小于等于 $lte
    • 大于 $gt
    • 大于等于 $gte
    • 不等于$ne
    • 等于 $eq
    • 包含 $in
    • 不包含 $nin

    查询age小于22的文档

    db.user.find({'age':{'$lt':22}})
    

    查询age大于等于22的文档

    db.user.find({'age':{'$gte':22}})
    

    查询age不等于23的文档:

    db.user.find({'age':{'$ne':23}})
    

    image-20210110173337445

    查询name值为wj或为zhangsan的文档:

    db.user.find({'name':{'$in':['wj','zhangsan']}})
    

    字母比较:

    按照字母顺序比较:查询name第一个字符比x小的文档

    db.user.find({'name':{'$lt':'x'}})
    

    image-20210110173530215

    逻辑操作符

    总共4种,不过多介绍:$and,$nor,$or,$not

    查询name不是wj的文档:

    db.user.find({'name':{'$not':{'$eq':'wj'}}})
    

    findOne

    查询符合条件的第一个文档(自然排序),参数与find方法一样

    db.user.findOne({'name':{'$lt':'x'}})
    

    image-20210110173832597

    pretty格式化

    使用pretty()方法可以格式化查询返回结果,知道有这一个方法就好,我的查询器默认已经格式化了。

    findOne()默认会格式化返回结果,所以无需加上pretty()。

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

    复杂查询条件

    并列条件:查询age大于等于22,小于等于24的文档

    db.user.find({'age':{'$gte':22, '$lte':24}})
    

    或者条件:查询age大于等于22、小于等于24,或者name等于zhangsan的文档

    对于这种,语法格式如下:

    # db.collection.find({'$or':[{},{}...]})
    
    db.user.find({'$or':
        [
            {'name':'zhangsan'}
            ,{'age':{'$gte':22, '$lte':24}}
        ]
    })
    

    $type查询

    根据集合中某个属性的类型查询对应的数据,使用$type指定属性类型

    例如:查询name属性为字符串的文档

    db.user.find({'name':{'$type':'string'}})
    

    在mongodb中,数字类型默认都是double

    db.user.find({'age':{'$type':'double'}})
    

    image-20210110175917040

    $type有效值如下

    type number Alias
    Double 1 double
    String 2 string
    Object 3 object
    Array 4 array
    Binary data 5 binData
    Undefined 6 undefined
    ObjectId 7 objectId
    Boolean 8 bool
    Date 9 date
    Null 10 null
    Regular Expression 11 regex
    DBPointer 12 dbPoint
    JavaScript 13 javascript
    Symbol 14 symbol
    JavaScript(with scope) 15 javascriptWithScope
    32-bit integer 16 int
    Timestamp 17 timestamp
    64-bit integer 18 long
    Decimal128 19 decimal

    正则查询

    简写

    语法:

    db.collection.find({field:/pattern/})
    

    查询name中以z开头的文档

    db.user.find({'name':/^z/})
    

    查询name中以n结尾的文档:

    db.user.find({'name':/n$/})
    

    查询name中以z开头、以n结尾的文档(.* 意为多个任意字符)

    db.user.find({'name':/^z.*n$/})
    

    查询name中包含w字符的文档

    db.user.find({'name':/w/})
    

    查询name中包含w字符(忽略大小写)

    db.user.find({'name':/w/i})
    

    差不多了解以上的正则在实际开发中就够用了,那些需要邮箱正则、手机号正则的场景,为什么不在插入数据之前就做处理呢?

    全写

    语法:

    db.collection.find({field:{$regex:/pattern/,$options:'<options>'}})
    db.collection.find({field:{$regex:/pattern/<options>}})
    

    部分操作符也支持正则表达式

    例如:查询name以z开头,或以n结尾的文档

    db.user.find({'name':{'$in':[/^z/,/n$/]}})
    

    image-20210110183333014

    查询name不以z开头的文档

    db.user.find({'name':{'$not':/^z/}})
    

    分页查询

    结合limit()和skip()方法完成分页

    limit:限制多少条返回

    skip:跳过前多少条,并返回

    查询第一页数据,一页三条(查询三条,跳过零条)

    db.user.find().limit(3).skip(0);
    db.user.find().limit(3);
    

    查询第二页数据,一页三条(查询三条,跳过三条)

    db.user.find().limit(3).skip(3);
    

    不跳过任何数据,只查询前三条

    db.user.find().limit(3);
    

    跳过前三条数据,查询剩余所有数据

    db.user.find().skip(3);
    

    有点像mysql的limit n,m 跳过n行查询m行

    排序查询

    使用sort()方法即可排序

    # age列的升序
    db.user.find().sort({'age':1});
    # age列的降序
    db.user.find().sort({'age':-1});
    # 先age升序,再name降序
    db.user.find().sort({'age':1,'name':-1});
    

    更新文档

    mongodb主要通过save(覆盖)和update(修改)来更新文档。

    save

    save的作用是保存文档,如果文档存在则覆盖,不存在则插入。save对文档的存在判断标准是"_id"是否存在。所以如果想用save去更新文档,则必须带上该字段,且该字段在集合中已经存在。

    db.user.save({"_id" : ObjectId("5ffac1b0a1761355478cf855"),'name':'lisi','age':19});
    

    image-20210110185945394

    使用save,如果文档不存在并新增成功,则nUpserted为1,如果存在并修改成功,则nModified为1

    update

    该方法可以通过特定条件来更新一个或多个文档。

    语法格式(其实后面可以携带更多参数,这里仅简单介绍基本用法):

    db.collection.update(<query>,<update>);
    

    参数说明:

    • query 更新文档的筛选条件
    • update 更新的字段和字段值

    覆盖修改

    把name等于wj的文档,变为age等于23(注意,update默认情况下只覆盖匹配到的第一条文档)

    db.user.update({'name':'wj'},{'age':23})
    

    image-20210110191440806

    上图为覆盖后的结果,name字段丢失了,是因为没有写name字段,直接用{'age':23}覆盖了原来的文档

    表达式更新

    $set

    把name等于wj的文档的age修改为25(这里也修改匹配到的第一条文档)

    db.user.update({'name':'wj'},{'$set':{'age':25}})
    

    这里$set的字段,如果字段存在,则修改字段,如果不存在,则添加字段

    $inc

    将字段增加指定的值

    把name等于wj的文档的age增加10

    db.user.update({'name':'wj'},{'$inc':{'age':10}})
    
    $unset

    把对应的字段删除

    把name等于wj的文档的age删除

    #age字段的值任意写,这里只是一个占位标记
    db.user.update({'name':'wj'},{'$unset':{'age':1}})
    
    $push

    这里先给name等于wj的文档添加一个字段courses课程,该字段是一个数组

    db.user.update({'name':'wj'},{'$set':{'courses':['springboot','springcloud']}})
    

    image-20210110192908650

    现在我想向courses字段中添加一个元素docker

    db.user.update({'name':'wj'},{'$push':{'courses':'docker'}})
    

    image-20210110193150577

    注意:以下的写法不是添加多个元素,而是往courses字段中添加了一个数组,所以push只能往数组中添加一个元素(无论是该元素数组还是其他)

    db.user.update({'name':'wj'},{'$push':{'courses':['jenkins','harbor']}})
    

    image-20210110193311978

    如果push的字段不存在,则会新增一个字段,将元素放在数组中

    db.user.update({'name':'wj'},{'$push':{'course':['springboot','springcloud']}})
    

    image-20210110193719342

    $addToSet

    与push类似,该表达式也会向数组中添加元素,如果该元素存在,则不添加否则添加进入数组。

    元素的匹配大小写敏感。

    db.user.update({'name':'wj'},{'$addToSet':{'courses':'springboot2'}})
    
    $pop

    出栈(删除出来的数据),与push(压栈)相反

    #删除courses数组的最后一个元素
    db.user.update({'name':'wj'},{'$pop':{'courses':1}})
    #删除courses数组的第一个元素
    db.user.update({'name':'wj'},{'$pop':{'courses':-1}})
    
    $pull

    推(删除指定元素)

    #删除courses数组中所有名称为docker的元素
    db.user.update({'name':'wj'},{'$pull':{'courses':'docker'}})
    
    $pullAll

    推(删除多个指定元素)

    db.user.update({'name':'wj'},{'$pullAll':{'courses':['docker','springcloud']}})
    

    执行前:

    image-20210110195451844

    执行后:

    image-20210110195525385

    $rename

    修改字段名

    # 将name=wj的文档中,字段名从name修改为user_name
    db.user.update({'name':'wj'},{'$rename':{'name':'user_name'}})
    

    upset和multi

    db.collection.update(<query>,<update>,<upset:boolean>,<multi:boolean>);
    

    对于update方法,还有两个参数可以选择,upset和multi

    • upset:默认为false,为true时,则表示在更新条件没有匹配时,会插入此文档,为false则不插入。
    • multi:默认为false,为true时,会更新所有匹配到的文档,为false,则会更新匹配到的第1个文档。
    #将所有name=wj的文档的age修改为25
    db.user.update({'name':'wj'},{'$set':{'age':25}},false,true)
    #  db.user.update({'name':'wj'},{'age':23},false,true) 该写法错误,多行操作不支持覆盖修改
    

    删除文档

    remove(不推荐)

    删除所有age大于等于28的文档

    db.user.remove({'age':{'$gte':28}});
    

    删除第一条age大于等于20的文档

    db.user.remove({'age':{'$gte':20}},true);
    

    deleteOne

    该方法只能删除匹配到的第一个文档

    删除第一个age大于等于28的文档

    db.user.deleteOne({'age':{'$gte':28}});
    

    deleteMany

    一次性删除所有匹配到的文档

    删除所有age大于等于28的文档

    db.user.deleteMany({'age':{'$gte':28}});
    
  • 相关阅读:
    事务传播机制,搞懂。
    洛谷 P1553 数字反转(升级版) 题解
    洛谷 P1200 [USACO1.1]你的飞碟在这儿Your Ride Is Here 题解
    洛谷 P1055 ISBN号码 题解
    洛谷 P2141 珠心算测验 题解
    洛谷 P1047 校门外的树 题解
    洛谷 P1980 计数问题 题解
    洛谷 P1008 三连击 题解
    HDU 1013 题解
    HDU 1012 题解
  • 原文地址:https://www.cnblogs.com/wwjj4811/p/14259401.html
Copyright © 2011-2022 走看看