• MongoDB文档操作


    MongoDB 文档操作

    文档的数据结构和 JSON 基本一样。

    所有存储在集合中的数据都是 BSON 格式。

    BSON 是一种类似 JSON 的二进制形式的存储格式,是 Binary JSON 的简称。

    插入文档

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

    db.COLLECTION_NAME.insert(document)
    或
    db.COLLECTION_NAME.save(document)
    
    • save():如果 _id 主键存在则更新数据,如果不存在就插入数据。该方法新版本中已废弃,可以使用 db.collection.insertOne()db.collection.replaceOne() 来代替。
    • insert(): 若插入的数据主键已经存在,则会抛 org.springframework.dao.DuplicateKeyException 异常,提示主键重复,不保存当前数据。

    3.2 版本之后新增了 db.collection.insertOne() 和 db.collection.insertMany()。

    db.collection.insertOne() 用于向集合插入一个新文档,语法格式如下:

    db.collection.insertOne(
       <document>,
       {
          writeConcern: <document>
       }
    )
    
    db.test.iusertone( { item: "card", qty: 15 } );
    

    db.collection.insertMany() 用于向集合插入一个多个文档,语法格式如下:

    db.collection.insertMany(
       [ <document 1> , <document 2>, ... ],
       {
          writeConcern: <document>,
          ordered: <boolean>
       }
    )
    
    db.test.insertMany([
        { item: "card", qty: 15 },
        { item: "envelope", qty: 20 },
        { item: "stamps", qty:30 }
    ]);
    

    参数说明:

    • document:要写入的文档。
    • writeConcern:写入策略,默认为 1,即要求确认写操作,0 是不要求。
    • ordered:指定是否按顺序写入,默认 true,按顺序写入。
      • 如果为 true,在数组中执行文档的有序插入,并且如果其中一个文档发生错误,MongoDB 将返回而不处理数组中的其余文档;
      • 如果为 false,则执行无序插入,若其中一个文档发生错误,则忽略错误,继续处理数组中的其余文档。

    实例

    以下文档可以存储在 MongoDB 的 student 数据库 的 col 集合中:

    >db.col.insert({name: 'xxx', 
        description: '天资聪颖,好学',
        age: 15,
        sex: '男',
        hobbies: ['小说', '篮球', '游泳']
    })
    

    以上实例中 col 是我们的集合名,如果该集合不在该数据库中, MongoDB 会自动创建该集合并插入文档。

    插入不指定 _id 字段,mongod 将创建 _id 字段并为其分配唯一的 Objectld 值。

    查看已插入文档:

    > db.col.find()
    { "_id" : ObjectId("56064886ade2f21f36b03134"), "name" : "xxx", "description" : "天资聪颖,好学", "age" : 15, "sex" : "男" , "hobbies" : ['小说', '篮球', '游泳'] }
    > 
    

    我们也可以将数据定义为一个变量,如下所示:

    > document=({name: 'xxx', 
        description: '天资聪颖,好学',
        age: 15,
        sex: '男',
        hobbies: ['小说', '篮球', '游泳'],
    });
    > db.col.insert(document)
    WriteResult({ "nInserted" : 1 })
    > 
    

    插入指定 _id 字段的文档,值 _id 必须在集合中唯一,以避免重复键错误,代码如下:

    > db.col.insert(
        { _id: 10, item: "box", qty: 20 }
    )
    > db.col.find()
    { "_id" : 10, "item" : "box" , "qty": 20 }
    

    有序地插入多条文档:

    > db.col.insert([
            {_id:10, item:"pen", price:"20" },
            {_id:12, item:"redpen", price: "30" },
            {_id:11, item:"bluepen", price: "40" }
        ],
        {ordered:true}
    )
    

    在设置 ordered:true 时,插入的数据是有序的,如果存在某条待插入文档和集合的某文档 _id 相同的情况,_id 相同的文档与后续文档都将不再插入。在设置 ordered:false 时,除了出错记录(包括 _id 重复)外其他的记录继续插入。

    插入文档你也可以使用 db.col.save(document) 命令。如果不指定 _id 字段 save() 方法类似于 insert() 方法。如果指定 _id 字段,则会更新该 _id 的数据。

    更新文档

    MongoDB 使用 update()save() 方法来更新集合中的文档。接下来让我们详细来看下两个函数的应用及其区别。


    update() 方法

    update() 方法用于更新已存在的文档。语法格式如下:

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

    参数说明:

    • query : update的查询条件,类似sql update查询内where后面的。
    • update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
    • upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入这个新的文档,true为插入,默认是false,不插入。
    • multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
    • writeConcern :可选,抛出异常的级别。
    • collation:指定语言。

    实例

    我们在集合 col 中插入如下数据:

    >db.col.insert({name: 'xxx', 
        description: '天资聪颖,好学',
        age: 15,
        sex: '男',
        hobbies: ['小说', '篮球', '游泳']
    })
    

    接着我们通过 update() 方法来更新姓名(name):

    >db.col.update({'name':'xxx'},{$set:{'name':'lili'}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })   # 输出信息
    > db.col.find().pretty()
    {
            "_id" : ObjectId("56064f89ade2f21f36b03136"),
            "title" : "lili",
            "description" : "天资聪颖,好学",
            "age" : 15,
            "sex" : "男",
            "hobbies" : [
                    "小说",
                    "篮球",
                    "游泳"
            ]
    }
    >
    

    以上语句只会修改第一条发现的文档,如果你要修改多条相同的文档,则需要设置 multi 参数为 true。

    >db.col.update({'name':'xxx'},{$set:{'name':'lili'}},{multi:true})
    

    save() 方法

    save() 方法通过传入的文档来替换已有文档,_id 主键存在就更新,不存在就插入。语法格式如下:

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

    参数说明:

    • document : 文档数据。
    • writeConcern :可选,抛出异常的级别。

    实例

    以下实例中我们替换了 _id 为 56064f89ade2f21f36b03136 的文档数据:

    >db.col.save({
        "_id" : ObjectId("56064f89ade2f21f36b03136"),
        "name" : "tom",
        "description" : "tom 很调皮",
        "age" : 13,
        "sex" : "男",
        "hobbies" : [
                "游戏",
                "游泳"
        ]
    })
    

    替换成功后,我们可以通过 find() 命令来查看替换后的数据

    >db.col.find().pretty()
    {
            "_id" : ObjectId("56064f89ade2f21f36b03136"),
            "name" : "tom",
            "description" : "tom 很调皮",
            "age" : 13,
            "sex" : "男",
            "hobbies" : [
                    "游戏",
                    "游泳"
            ]
    }
    > 
    

    如果使用 insert 插入记录,若新增数据的主键已经存在,则会抛出 DuplicateKeyException 异常提示主键重复,不保存当前数据。


    更多实例

    只更新第一条记录:

    db.col.update( { "count" : { $gt : 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 );

    删除文档

    remove() 方法

    语法

    remove() 方法的基本语法格式如下所示:

    db.collection.remove(
       <query>,
       <justOne>
    )
    

    如果你的 MongoDB 是 2.6 版本以后的,语法格式如下:

    db.collection.remove(
       <query>,
       {
         justOne: <boolean>,
         writeConcern: <document>
       }
    )
    

    参数说明:

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

    实例

    以下文档我们执行两次插入操作:

    >db.col.insert({name: 'xxx', 
        description: '天资聪颖,好学',
        age: 15,
        sex: '男',
        hobbies: ['小说', '篮球', '游泳']
    })
    

    使用 find() 函数查询数据:

    > db.col.find()
    { "_id" : ObjectId("56066169ade2f21f36b03137"), "name" : "xxx", "description" : "天资聪颖,好学", "age" : 15, "sex" : "男", "hobbies" : ['小说', '篮球', '游泳'] }
    { "_id" : ObjectId("5606616dade2f21f36b03138"), "name" : "xxx", "description" : "天资聪颖,好学", "age" : 15, "sex" : "男", "hobbies" : ['小说', '篮球', '游泳'] }
    

    接下来我们移除 name 为 'xxx' 的文档:

    >db.col.remove({'name':'xxx'})
    WriteResult({ "nRemoved" : 2 })           # 删除了两条数据
    >db.col.find()
    ……                                        # 没有数据
    

    如果你只想删除第一条找到的记录可以设置 justOne 为 1,如下所示:

    >db.COLLECTION_NAME.remove(DELETION_CRITERIA,1)
    

    如果你想删除所有数据,可以使用以下方式(类似常规 SQL 的 truncate 命令):

    >db.col.remove({})
    >db.col.find()
    >
    

    delete() 方法

    官方推荐使用 deleteOne() 和 deleteMany() 方法删除文档,语法格式如下:

    db.collection.deleteMany ({})
    db.collection.deleteMany ({ status : "A" })
    db.collection.delete.One ({ status : "D" })
    

    第一条语句删除集合下所有的文档,第二条语句删除 status 等于 A 的全部文档,第三条语句删除 status 等于 D 的一个文档。

    查询文档

    find() 简介

    MongoDB 查询数据的语法格式如下:

    db.collection.find(query, projection)
    
    • query :可选,使用查询操作符指定查询条件
    • projection :可选,表示使用投影操作符指定返回的字段,如果忽略此选项则返回所有字段。(默认省略)。

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

    >db.col.find().pretty()
    

    pretty() 方法以格式化的方式来显示所有文档。

    实例

    以下实例我们查询了集合 col 中的数据:

    > db.col.find().pretty()
    {
            "_id" : ObjectId("56063f17ade2f21f36b03133"),
            "name" : "xxx",
            "description" : "天资聪颖,好学",
            "age" : 15,
            "sex" : "男",
            "hobbies" : [
                    "小说",
                    "篮球",
                    "游泳"
            ]
    }
    

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


    查询条件

    ​ MongoDB 与 RDBMS 的查询比较

    操作符 格式 实例 与 RDBMS where 语句比较
    等于(=) { : {}} db.test.find( {price : 24} ) where price = 24
    大于(>) { : {$gt : }} db.test.find( {price : {$gt : 24}} ) where price > 24
    小于(<) { : {$lt : }} db.test.find( {price : {$lt : 24}} ) where price < 24
    大于等于(>=) { : {$gte : }} db.test.find( {price : {$gte : 24}} ) where price >= 24
    小于等于(<=) { : {$lte : }} db.test.find( {price : {$lte : 24}} ) where price <= 24
    不等于(!=) { : {$ne : }} db.test.find( {price : {$ne : 24}} ) where price != 24
    与(and) {key01 : value01, key02 : value02, ...} db.test.find( {name : "《MongoDB 入门教程》", price : 24} ) where name = "《MongoDB 入门教程》" and price = 24
    或(or) {$or : [{key01 : value01}, {key02 : value02}, ...]} db.test.find( {$or:[{name : "《MongoDB 入门教程》"},{price : 24}]} ) where name = "《MongoDB 入门教程》" or price = 24

    MongoDB AND 条件

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

    语法格式如下:

    >db.col.find({key1:value1, key2:value2}).pretty()
    

    实例

    > db.col.find({"name":"xxx", "age":15}).pretty()
    {
            "_id" : ObjectId("56063f17ade2f21f36b03133"),
            "name" : "xxx",
            "description" : "天资聪颖,好学",
            "age" : 15,
            "sex" : "男",
            "hobbies" : [
                    "小说",
                    "篮球",
                    "游泳"
            ]
    }
    

    以上实例中类似于 WHERE 语句:WHERE name='xxx' AND age=15


    MongoDB OR 条件

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

    >db.col.find(
       {
          $or: [
             {key1: value1}, {key2:value2}
          ]
       }
    ).pretty()
    

    实例

    >db.col.find({$or:[{"name":"xxx"},{"age": 16}]}).pretty()
    {
            "_id" : ObjectId("56063f17ade2f21f36b03133"),
            "name" : "xxx",
            "description" : "天资聪颖,好学",
            "age" : 15,
            "sex" : "男",
            "hobbies" : [
                    "小说",
                    "篮球",
                    "游泳"
            ]
    }
    >
    

    AND 和 OR 联合使用

    AND 和 OR 联合使用,类似常规 SQL 语句为: 'where age=15 AND (name= 'xxx' OR sex= '男')'

    >db.col.find({"age": 15, $or: [{"name": "xxx"},{"sex": "男"}]}).pretty()
    {
            "_id" : ObjectId("56063f17ade2f21f36b03133"),
            "name" : "xxx",
            "description" : "天资聪颖,好学",
            "age" : 15,
            "sex" : "男",
            "hobbies" : [
                    "小说",
                    "篮球",
                    "游泳"
            ]
    }
    

    特定类型查询

    以 test 集合中以下文档为基础:

    > db.test.find()
        {"_id" : Objectld("5ba7342c7f9318ea62161351"), "name" : "《MongoDB教程》", "price" : 24, "tags" : [ "MongoDB", "NoSQL", "database" ]}
        {"_id" : Objectld("5ba747bd7f9318ea62161352"), "name" : "ava 教程", "price" : 36, "tags" : ["编程语言", "Java语言", "面向对象程序设计语言"]}
        {"_id" : Objectld("5ba75a057f9318ea62161356"), "name" : "王二", "age" : null }
    

    查询 age 为 null 的字段的语法格式如下:

    > db.test.find({age:null})
    

    此语句不仅匹配出 age 为 null 的文档,其他不同类型的文档也会被查出。这是因为 null 不仅会匹配某个键值为 null 的文档,而且还会匹配不包含这个键的文档。

    查询数组:

    > db.test.find(
    {
        tags:['MongoDB', 'NoSQL', 'database']
    }
    )
    {"_id" : ObjectId("5ba7342c7f9318ea62161351"), "name": "《MongoDB教程》", "price" : 24, "tags" : [ "MongoDB", "NoSQL", "database"]}
    

    查询有 3 个元素的数组:

    > db.test.find(
    {
        tags:{$size:3}
    }
    )
    {"_id" : Objectld("5baf9b6663ba0fb3ccccle77"), "name" : "《MongoDB 教程》", ''price" : 24, "tags" : ["MongoDB","NoSQL", "database"]}
    {"_id" : Objectld ("5baf 9bc763ba0fk>3ccccle78"), "name" : "《Java 教程》", "price" : 36, "tags" : ["编程语言", "Java语言", "面向对象程序设计语言"]}
    

    查询数组里的某一个值:

    > db.test.find(
    {
        tags: "MongoDB"
    }
    )
    {"_id" : Objectld("5baf9b6663ba0fb3ccccle77"), "name" : "《MongoDB 教程》", ''price" : 24, "tags" : ["MongoDB","NoSQL", "database"]}
    

    limit() 、skip()、sort() 、$regex

    1. limit()

      用于限制查询结果的个数,若匹配的结果不到 限制 个数,则返回匹配数量的结果

      db.test.find().limit(3)
      
    2. skip()

      用于略过指定个数的文档

      >db.test.find().skip(1)
      
    3. sort()

      用于对查询结果进行排序,1 是升序,-1 是降序

      >db.test.find().sort({"price" : 1})
      
    4. $regex

      正则表达式,不同于全文检索,使用正则表达式无须进行任何配置

      > db.test.find({tags:{$regex:"MongoDB"}})
      {"_id" : Objectld("5baf9b6663ba0fb3ccccle77"), "name" : "《MongoDB 教程》", ''price" : 24, "tags" : ["MongoDB","NoSQL", "database"]}
      

    游标

    游标是指对数据一行一行地进行操作,在 MongoDB 数据库中对游标的控制非常简单,只需使用 firid() 函数就可以返回游标。

    方法名 作用
    hasNext 判断是否有更多的文档
    next 用来获取下一条文档
    toArray 将查询结构放到数组中
    count 查询的结果为文档的总数量
    limit 限制查询结果返回数量
    skip 跳过指定数目的文档
    sort 对查询结果进行排序
    objsLeftlnBatch 查看当前批次剩余的未被迭代的文档数量
    addOption 为游标设置辅助选项,修改游标的默认行为
    hint 为查询强制使用指定索引
    explain 用于获取查询执行过程报告
    snapshot 对查询结果使用快照

    使用游标时,需要注意下面 4 个问题。

    1. 当调用 find() 函数时,Shell 并不立即查询数据库,而是等真正开始获取结果时才发送查询请求。

    2. 游标对象的每个方法几乎都会返回游标对象本身,这样可以方便进行链式函数的调用。

    3. 在 MongoDB Shell 中使用游标输出文档包含两种情况,如果不将 find() 函数返回的游标赋值给一个局部变量进行保存,在默认情况下游标会自动迭代 20 次。如果将 find() 函数返回的游标赋值给一个局部变量,则可以使用游标对象提供的函数进行手动迭代。

    4. 使用清空后的游标,进行迭代输出时,显示的内容为空。

    游标从创建到被销毁的整个过程存在的时间,被称为游标的生命周期,包括游标的创建、使用及销毁三个阶段。当客户端使用 find() 函数向服务器端发起一次查询请求时,会在服务器端创建一个游标,然后就可以使用游标函数来操作查询结果。

    以下三种情况会让游标被销毁。

    • 客户端保存的游标变量不在作用域内。
    • 游标遍历完成后,或者客户端主动发送终止消息。
    • 在服务器端 10 分钟内未对游标进行操作。

    以下语句显示使用游标查找所有文档:

    >var cursor = db.test.find()
    >while (cursor.hasNext()){
        var doc = cursor.next();
        print(doc.name);  //把每一条数据都单独拿出来进行逐行的控制
        print(doc);  //将游标数据取出来后,其实每行数据返回的都是一个[object BSON]型的内容
        printjson(doc);  //将游标获取的集合以JSON的形式显示
    }
    
  • 相关阅读:
    STL中set底层实现方式? 为什么不用hash?
    main 主函数执行完毕后,是否可能会再执行一段代码?(转载)
    计算机网络(转载)
    2014! 的末尾有多少个0
    最常见的http错误
    内存分配(转载)
    delphi中指针操作符^的使用
    虚拟方法virtual的用法
    调用父类方法
    指针
  • 原文地址:https://www.cnblogs.com/chenwenyin/p/13553167.html
Copyright © 2020-2023  润新知