CRUD操作


文章目录

  • CRUD操作
  • 一、插入文档
  • 1、insert增加单条数据
  • 2、insert增加多条数据
  • 3、insertOne插入一条数据
  • 4、InsertMany插入多条数据
  • 二、查询文档
  • 1、判断符
  • 2、练习
  • 1、查询status为A的文档
  • 2、查询status为P或D的文档
  • 3、查询status为A并且age小于30的文档
  • 4、查询status为A或者age小于30的文档
  • 5、查询status为A并且要么age小于30要么type为1的文档
  • 6、嵌套文档的精确查询
  • 7、嵌套文档中字段的等于匹配
  • 8、数组中的精确匹配
  • 9、匹配数组中包含某个元素的文档
  • 10、匹配数组指定位置为某个值的元素
  • 11、`$elemMatch`查询数组中至少有一个元素满足所有指定条件的文档
  • 11、元素组合满足查询条件
  • 12、使用数组指定索引匹配嵌入文档中的字段
  • 13、使用数组不指定索引匹配嵌入文档中的字段
  • 14、单个元素满足条件
  • 15、元素组合满足某个条件
  • 3、返回查询的映射字段
  • 1、映射文档
  • 返回匹配文档的所有字段
  • 只返回指定字段和`_id`字段
  • 只返回指定字段
  • 返回排除字段之外的所有字段
  • 返回嵌入文档中的指定字段
  • 排除嵌入文档中的特定字段
  • 映射数组中的嵌入文档
  • 映射返回数组中特定的数组元素(切片)
  • 4、查询值为Null或不存在的字段
  • 相等过滤器
  • 类型筛选
  • 存在性筛选
  • 5、在mongo命令行中迭代游标
  • 手动迭代游标
  • 迭代器索引
  • Cursor Behaviors(游标行为)
  • Cursor Information(光标信息)
  • 三、更新文档
  • 1、更新介绍
  • 2、行为表现
  • 1、原子性
  • 2、_id字段
  • 3、文档大小
  • 4、字段顺序
  • 5、upsert选项
  • 3、更新操作
  • 1、$set——修改指定字段
  • 2、$unset——删除某个列
  • 3、$rename——重命名某个列
  • 4、$inc——增加某个列
  • 5、选项:{upsert:true/false,multi:true/false}
  • 四、删除文档
  • 1、删除的方法
  • 2、删除的行为表现
  • 1、索引
  • 2、原子性
  • 3、删除操作
  • 2、删除的行为表现
  • 1、索引
  • 2、原子性
  • 3、删除操作


一、插入文档

插入文档的方式共有三种,每一种的返回值不同:

  • db.collection.insert()
  • db.collection.insertOne() 3.2新增功能
  • db.collection.insertMany() 3.2新增功能

MongoDB存储的是文档,文档其实就是json对象。存储于集合中的每一个文档都需要一个唯一的_id字段作为primary_key。如果一个插入的文档操作遗漏了_id字段,MongoDB驱动会自动为_id字段生成一个ObjectId。

1、insert增加单条数据
> db.man.insert({name:'youzi'})
WriteResult({ "nInserted" : 1 })
2、insert增加多条数据
> db.man.insert([{name:'zhangsan'},{name:'dachang'}])
BulkWriteResult({
        "writeErrors" : [ ],
        "writeConcernErrors" : [ ],
        "nInserted" : 2,
        "nUpserted" : 0,
        "nMatched" : 0,
        "nModified" : 0,
        "nRemoved" : 0,
        "upserted" : [ ]
})
3、insertOne插入一条数据
> db.man.insertOne({name:'xiaxia'})
{
        "acknowledged" : true,
        "insertedId" : ObjectId("5f0589da25bd42dbbb1469b4")
}
4、InsertMany插入多条数据
> db.man.insertMany([{name:'liuhuan'}])
{
        "acknowledged" : true,
        "insertedIds" : [
                ObjectId("5f0589fe25bd42dbbb1469b5")
        ]
}

二、查询文档

1、判断符

MongoDB中提供了db.collection.find()方法从集合中读取文档。返回指向匹配文档的:doc:cursor</tutorial/iterate-a-cursor>。

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

判断符

含义

name:‘zhangsan’

相等

$gt:10

大于

$lt:10

小于

$gte:10

大于等于

$lte:10

小于等于

$ne:10

不等于

$nin:[1,2]

不在某个范围内

$in:[1,2]


$and:[条件1,条件2]

并且

$or:[条件1,条件2]


$all:[20,30]

指定的数据都要有

db.collection.find({age:{$all:[‘lisi’]}})

$exists

是否存在某一列,1代表存在,0代表不存在。<br db.collection.find({name:{$exists:1}})

count()

统计数量

db.stu.find().count()

limit()

查看指定数量的结果

db.collection.find().limit(4)

skip()

db.collection.find().skip(4)

在相同字段执行等于查询时,建议使用$in而不使用$or

首先插入数据:

db.users.insertMany(
  [
     {
       _id: 1,
       name: "sue",
       age: 19,
       type: 1,
       status: "P",
       favorites: { artist: "Picasso", food: "pizza" },
       finished: [ 17, 3 ],
       badges: [ "blue", "black" ],
       points: [
          { points: 85, bonus: 20 },
          { points: 85, bonus: 10 }
       ]
     },
     {
       _id: 2,
       name: "bob",
       age: 42,
       type: 1,
       status: "A",
       favorites: { artist: "Miro", food: "meringue" },
       finished: [ 11, 25 ],
       badges: [ "green" ],
       points: [
          { points: 85, bonus: 20 },
          { points: 64, bonus: 12 }
       ]
     },
     {
       _id: 3,
       name: "ahn",
       age: 22,
       type: 2,
       status: "A",
       favorites: { artist: "Cassatt", food: "cake" },
       finished: [ 6 ],
       badges: [ "blue", "red" ],
       points: [
          { points: 81, bonus: 8 },
          { points: 55, bonus: 20 }
       ]
     },
     {
       _id: 4,
       name: "xi",
       age: 34,
       type: 2,
       status: "D",
       favorites: { artist: "Chagall", food: "chocolate" },
       finished: [ 5, 11 ],
       badges: [ "red", "black" ],
       points: [
          { points: 53, bonus: 15 },
          { points: 51, bonus: 15 }
       ]
     },
     {
       _id: 5,
       name: "xyz",
       age: 23,
       type: 2,
       status: "D",
       favorites: { artist: "Noguchi", food: "nougat" },
       finished: [ 14, 6 ],
       badges: [ "orange" ],
       points: [
          { points: 71, bonus: 20 }
       ]
     },
     {
       _id: 6,
       name: "abc",
       age: 43,
       type: 1,
       status: "A",
       favorites: { food: "pizza", artist: "Picasso" },
       finished: [ 18, 12 ],
       badges: [ "black", "blue" ],
       points: [
          { points: 78, bonus: 8 },
          { points: 57, bonus: 7 }
       ]
     }
  ]
)
2、练习
1、查询status为A的文档
> db.users.find({status:"A"})
{ "_id" : 2, "name" : "bob", "age" : 42, "type" : 1, "status" : "A", "favorites" : { "artist" : "Miro", "food" : "meringue" }, "finished" : [ 11, 25 ], "badges" : [ "green" ], "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 64, "bonus" : 12 } ] }
{ "_id" : 3, "name" : "ahn", "age" : 22, "type" : 2, "status" : "A", "favorites" : { "artist" : "Cassatt", "food" : "cake" }, "finished" : [ 6 ], "badges" : [ "blue", "red" ], "points" : [ { "points" : 81, "bonus" : 8 }, { "points" : 55, "bonus" : 20 } ] }
{ "_id" : 6, "name" : "abc", "age" : 43, "type" : 1, "status" : "A", "favorites" : { "food" : "pizza", "artist" : "Picasso" }, "finished" : [ 18, 12 ], "badges" : [ "black", "blue" ], "points" : [ { "points" : 78, "bonus" : 8 }, { "points" : 57, "bonus" : 7 } ] }
>
2、查询status为P或D的文档
> db.users.find({status:{$in:["P","D"]}})
{ "_id" : 1, "name" : "sue", "age" : 19, "type" : 1, "status" : "P", "favorites" : { "artist" : "Picasso", "food" : "pizza" }, "finished" : [ 17, 3 ], "badges" : [ "blue", "black" ], "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 85, "bonus" : 10 } ] }
{ "_id" : 4, "name" : "xi", "age" : 34, "type" : 2, "status" : "D", "favorites" : { "artist" : "Chagall", "food" : "chocolate" }, "finished" : [ 5, 11 ], "badges" : [ "red", "black" ], "points" : [ { "points" : 53, "bonus" : 15 }, { "points" : 51, "bonus" : 15 } ] }
{ "_id" : 5, "name" : "xyz", "age" : 23, "type" : 2, "status" : "D", "favorites" : { "artist" : "Noguchi", "food" : "nougat" }, "finished" : [ 14, 6 ], "badges" : [ "orange" ], "points" : [ { "points" : 71, "bonus" : 20 } ] }
3、查询status为A并且age小于30的文档
> db.users.find({status:"A",age:{$lt:30}})
{ "_id" : 3, "name" : "ahn", "age" : 22, "type" : 2, "status" : "A", "favorites" : { "artist" : "Cassatt", "food" : "cake" }, "finished" : [ 6 ], "badges" : [ "blue", "red" ], "points" : [ { "points" : 81, "bonus" : 8 }, { "points" : 55, "bonus" : 20 } ] }
4、查询status为A或者age小于30的文档
> db.users.find({$or:[{status:"A"},{age:{$lt:30}}]})
{ "_id" : 1, "name" : "sue", "age" : 19, "type" : 1, "status" : "P", "favorites" : { "artist" : "Picasso", "food" : "pizza" }, "finished" : [ 17, 3 ], "badges" : [ "blue", "black" ], "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 85, "bonus" : 10 } ] }
{ "_id" : 2, "name" : "bob", "age" : 42, "type" : 1, "status" : "A", "favorites" : { "artist" : "Miro", "food" : "meringue" }, "finished" : [ 11, 25 ], "badges" : [ "green" ], "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 64, "bonus" : 12 } ] }
{ "_id" : 3, "name" : "ahn", "age" : 22, "type" : 2, "status" : "A", "favorites" : { "artist" : "Cassatt", "food" : "cake" }, "finished" : [ 6 ], "badges" : [ "blue", "red" ], "points" : [ { "points" : 81, "bonus" : 8 }, { "points" : 55, "bonus" : 20 } ] }
{ "_id" : 5, "name" : "xyz", "age" : 23, "type" : 2, "status" : "D", "favorites" : { "artist" : "Noguchi", "food" : "nougat" }, "finished" : [ 14, 6 ], "badges" : [ "orange" ], "points" : [ { "points" : 71, "bonus" : 20 } ] }
{ "_id" : 6, "name" : "abc", "age" : 43, "type" : 1, "status" : "A", "favorites" : { "food" : "pizza", "artist" : "Picasso" }, "finished" : [ 18, 12 ], "badges" : [ "black", "blue" ], "points" : [ { "points" : 78, "bonus" : 8 }, { "points" : 57, "bonus" : 7 } ] }
5、查询status为A并且要么age小于30要么type为1的文档
> db.users.find({status:"A",$or:[{age:{$lt:30}},{type:1}]})
{ "_id" : 2, "name" : "bob", "age" : 42, "type" : 1, "status" : "A", "favorites" : { "artist" : "Miro", "food" : "meringue" }, "finished" : [ 11, 25 ], "badges" : [ "green" ], "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 64, "bonus" : 12 } ] }
{ "_id" : 3, "name" : "ahn", "age" : 22, "type" : 2, "status" : "A", "favorites" : { "artist" : "Cassatt", "food" : "cake" }, "finished" : [ 6 ], "badges" : [ "blue", "red" ], "points" : [ { "points" : 81, "bonus" : 8 }, { "points" : 55, "bonus" : 20 } ] }
{ "_id" : 6, "name" : "abc", "age" : 43, "type" : 1, "status" : "A", "favorites" : { "food" : "pizza", "artist" : "Picasso" }, "finished" : [ 18, 12 ], "badges" : [ "black", "blue" ], "points" : [ { "points" : 78, "bonus" : 8 }, { "points" : 57, "bonus" : 7 } ] }
6、嵌套文档的精确查询
> db.users.find( { favorites: { artist: "Picasso", food: "pizza" } } )
{ "_id" : 1, "name" : "sue", "age" : 19, "type" : 1, "status" : "P", "favorites" : { "artist" : "Picasso", "food" : "pizza" }, "finished" : [ 17, 3 ], "badges" : [ "blue", "black" ], "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 85, "bonus" : 10 } ] }
7、嵌套文档中字段的等于匹配
> db.users.find( { "favorites.artist": "Picasso" } )
{ "_id" : 1, "name" : "sue", "age" : 19, "type" : 1, "status" : "P", "favorites" : { "artist" : "Picasso", "food" : "pizza" }, "finished" : [ 17, 3 ], "badges" : [ "blue", "black" ], "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 85, "bonus" : 10 } ] }
{ "_id" : 6, "name" : "abc", "age" : 43, "type" : 1, "status" : "A", "favorites" : { "food" : "pizza", "artist" : "Picasso" }, "finished" : [ 18, 12 ], "badges" : [ "black", "blue" ], "points" : [ { "points" : 78, "bonus" : 8 }, { "points" : 57, "bonus" : 7 } ] }
8、数组中的精确匹配
> db.users.find( { badges: [ "blue", "black" ] } )
{ "_id" : 1, "name" : "sue", "age" : 19, "type" : 1, "status" : "P", "favorites" : { "artist" : "Picasso", "food" : "pizza" }, "finished" : [ 17, 3 ], "badges" : [ "blue", "black" ], "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 85, "bonus" : 10 } ] }
9、匹配数组中包含某个元素的文档
> db.users.find( { badges: "black" } )
{ "_id" : 1, "name" : "sue", "age" : 19, "type" : 1, "status" : "P", "favorites" : { "artist" : "Picasso", "food" : "pizza" }, "finished" : [ 17, 3 ], "badges" : [ "blue", "black" ], "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 85, "bonus" : 10 } ] }
{ "_id" : 4, "name" : "xi", "age" : 34, "type" : 2, "status" : "D", "favorites" : { "artist" : "Chagall", "food" : "chocolate" }, "finished" : [ 5, 11 ], "badges" : [ "red", "black" ], "points" : [ { "points" : 53, "bonus" : 15 }, { "points" : 51, "bonus" : 15 } ] }
{ "_id" : 6, "name" : "abc", "age" : 43, "type" : 1, "status" : "A", "favorites" : { "food" : "pizza", "artist" : "Picasso" }, "finished" : [ 18, 12 ], "badges" : [ "black", "blue" ], "points" : [ { "points" : 78, "bonus" : 8 }, { "points" : 57, "bonus" : 7 } ] }
10、匹配数组指定位置为某个值的元素
> db.users.find( { "badges.0": "black" } )
{ "_id" : 6, "name" : "abc", "age" : 43, "type" : 1, "status" : "A", "favorites" : { "food" : "pizza", "artist" : "Picasso" }, "finished" : [ 18, 12 ], "badges" : [ "black", "blue" ], "points" : [ { "points" : 78, "bonus" : 8 }, { "points" : 57, "bonus" : 7 } ] }
11、$elemMatch查询数组中至少有一个元素满足所有指定条件的文档

至少有一个元素满足小于20并且大于15。

> db.users.find( { finished: { $elemMatch: { $gt: 15, $lt: 20 } } } )
{ "_id" : 1, "name" : "sue", "age" : 19, "type" : 1, "status" : "P", "favorites" : { "artist" : "Picasso", "food" : "pizza" }, "finished" : [ 17, 3 ], "badges" : [ "blue", "black" ], "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 85, "bonus" : 10 } ] }
{ "_id" : 6, "name" : "abc", "age" : 43, "type" : 1, "status" : "A", "favorites" : { "food" : "pizza", "artist" : "Picasso" }, "finished" : [ 18, 12 ], "badges" : [ "black", "blue" ], "points" : [ { "points" : 78, "bonus" : 8 }, { "points" : 57, "bonus" : 7 } ] }
11、元素组合满足查询条件

查询一个元素小于15另一个元素大于20或者某一个元素同时满足这两个条件

> db.users.find( { finished: { $gt: 15, $lt: 20 } } )
{ "_id" : 1, "name" : "sue", "age" : 19, "type" : 1, "status" : "P", "favorites" : { "artist" : "Picasso", "food" : "pizza" }, "finished" : [ 17, 3 ], "badges" : [ "blue", "black" ], "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 85, "bonus" : 10 } ] }
{ "_id" : 2, "name" : "bob", "age" : 42, "type" : 1, "status" : "A", "favorites" : { "artist" : "Miro", "food" : "meringue" }, "finished" : [ 11, 25 ], "badges" : [ "green" ], "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 64, "bonus" : 12 } ] }
{ "_id" : 6, "name" : "abc", "age" : 43, "type" : 1, "status" : "A", "favorites" : { "food" : "pizza", "artist" : "Picasso" }, "finished" : [ 18, 12 ], "badges" : [ "black", "blue" ], "points" : [ { "points" : 78, "bonus" : 8 }, { "points" : 57, "bonus" : 7 } ] }
12、使用数组指定索引匹配嵌入文档中的字段
> db.users.find( { 'points.0.points': { $lte: 55 } } )
{ "_id" : 4, "name" : "xi", "age" : 34, "type" : 2, "status" : "D", "favorites" : { "artist" : "Chagall", "food" : "chocolate" }, "finished" : [ 5, 11 ], "badges" : [ "red", "black" ], "points" : [ { "points" : 53, "bonus" : 15 }, { "points" : 51, "bonus" : 15 } ] }
13、使用数组不指定索引匹配嵌入文档中的字段
> db.users.find( { 'points.points': { $lte: 55 } } )
{ "_id" : 3, "name" : "ahn", "age" : 22, "type" : 2, "status" : "A", "favorites" : { "artist" : "Cassatt", "food" : "cake" }, "finished" : [ 6 ], "badges" : [ "blue", "red" ], "points" : [ { "points" : 81, "bonus" : 8 }, { "points" : 55, "bonus" : 20 } ] }
{ "_id" : 4, "name" : "xi", "age" : 34, "type" : 2, "status" : "D", "favorites" : { "artist" : "Chagall", "food" : "chocolate" }, "finished" : [ 5, 11 ], "badges" : [ "red", "black" ], "points" : [ { "points" : 53, "bonus" : 15 }, { "points" : 51, "bonus" : 15 } ] }
14、单个元素满足条件

使用 $elemMatch操作符为数组元素指定符合条件,以查询数组中至少一个元素满足所有指定条件的文档。

下面的例子查询 points 数组有至少一个包含 points 小于等于 70 并且字段 bonus 等于 20 的内嵌文档的文档。

> db.users.find( { points: { $elemMatch: { points: { $lte: 70 }, bonus: 20 } } } )
{ "_id" : 3, "name" : "ahn", "age" : 22, "type" : 2, "status" : "A", "favorites" : { "artist" : "Cassatt", "food" : "cake" }, "finished" : [ 6 ], "badges" : [ "blue", "red" ], "points" : [ { "points" : 81, "bonus" : 8 }, { "points" : 55, "bonus" : 20 } ] }
15、元素组合满足某个条件
> db.users.find( { "points.points": { $lte: 70 }, "points.bonus": 20 } )
{ "_id" : 2, "name" : "bob", "age" : 42, "type" : 1, "status" : "A", "favorites" : { "artist" : "Miro", "food" : "meringue" }, "finished" : [ 11, 25 ], "badges" : [ "green" ], "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 64, "bonus" : 12 } ] }
{ "_id" : 3, "name" : "ahn", "age" : 22, "type" : 2, "status" : "A", "favorites" : { "artist" : "Cassatt", "food" : "cake" }, "finished" : [ 6 ], "badges" : [ "blue", "red" ], "points" : [ { "points" : 81, "bonus" : 8 }, { "points" : 55, "bonus" : 20 } ] }
3、返回查询的映射字段

插入数据:

db.users.insertMany(
  [
     {
       _id: 1,
       name: "sue",
       age: 19,
       type: 1,
       status: "P",
       favorites: { artist: "Picasso", food: "pizza" },
       finished: [ 17, 3 ],
       badges: [ "blue", "black" ],
       points: [
          { points: 85, bonus: 20 },
          { points: 85, bonus: 10 }
       ]
     },
     {
       _id: 2,
       name: "bob",
       age: 42,
       type: 1,
       status: "A",
       favorites: { artist: "Miro", food: "meringue" },
       finished: [ 11, 25 ],
       badges: [ "green" ],
       points: [
          { points: 85, bonus: 20 },
          { points: 64, bonus: 12 }
       ]
     },
     {
       _id: 3,
       name: "ahn",
       age: 22,
       type: 2,
       status: "A",
       favorites: { artist: "Cassatt", food: "cake" },
       finished: [ 6 ],
       badges: [ "blue", "red" ],
       points: [
          { points: 81, bonus: 8 },
          { points: 55, bonus: 20 }
       ]
     },
     {
       _id: 4,
       name: "xi",
       age: 34,
       type: 2,
       status: "D",
       favorites: { artist: "Chagall", food: "chocolate" },
       finished: [ 5, 11 ],
       badges: [ "red", "black" ],
       points: [
          { points: 53, bonus: 15 },
          { points: 51, bonus: 15 }
       ]
     },
     {
       _id: 5,
       name: "xyz",
       age: 23,
       type: 2,
       status: "D",
       favorites: { artist: "Noguchi", food: "nougat" },
       finished: [ 14, 6 ],
       badges: [ "orange" ],
       points: [
          { points: 71, bonus: 20 }
       ]
     },
     {
       _id: 6,
       name: "abc",
       age: 43,
       type: 1,
       status: "A",
       favorites: { food: "pizza", artist: "Picasso" },
       finished: [ 18, 12 ],
       badges: [ "black", "blue" ],
       points: [
          { points: 78, bonus: 8 },
          { points: 57, bonus: 7 }
       ]
     }
  ]
)
1、映射文档

映射文档限制返回匹配文档的所有字段,映射文档可以指明包括哪些字段或者排除哪些字段,格式为:

{ field1: , field2: }

  • 1或true在返回的文档中包含字段
  • 0或者false排除该字段
  • 使用Projection Operators表达式

其中_id字段为默认显示的,当不想显示时必须设置为0。并且在指定时要么都设置为1,要么都设置为0,不能部分设置为1,部分设置为0.

返回匹配文档的所有字段

如果没有指定映射,db.collection.find()方法将会返回满足查询的所有文档的所有字段。

> db.users.find({status:"P"})
{ "_id" : 1, "name" : "sue", "age" : 19, "type" : 1, "status" : "P", "favorites" : { "artist" : "Picasso", "food" : "pizza" }, "finished" : [ 17, 3 ], "badges" : [ "blue", "black" ], "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 85, "bonus" : 10 } ] }
只返回指定字段和_id字段
> db.users.find({status:"A"},{name:1,status:1})
{ "_id" : 2, "name" : "bob", "status" : "A" }
{ "_id" : 3, "name" : "ahn", "status" : "A" }
{ "_id" : 6, "name" : "abc", "status" : "A" }
只返回指定字段
> db.users.find({status:"A"},{name:1,status:1,_id:0})
{ "name" : "bob", "status" : "A" }
{ "name" : "ahn", "status" : "A" }
{ "name" : "abc", "status" : "A" }
返回排除字段之外的所有字段
> db.users.find({status:"A"},{favorites:0,points:0})
{ "_id" : 2, "name" : "bob", "age" : 42, "type" : 1, "status" : "A", "finished" : [ 11, 25 ], "badges" : [ "green" ] }
{ "_id" : 3, "name" : "ahn", "age" : 22, "type" : 2, "status" : "A", "finished" : [ 6 ], "badges" : [ "blue", "red" ] }
{ "_id" : 6, "name" : "abc", "age" : 43, "type" : 1, "status" : "A", "finished" : [ 18, 12 ], "badges" : [ "black", "blue" ] }
返回嵌入文档中的指定字段

使用dot notation返回嵌入文档中的特定字段

  • 返回favorites文档中的food字段,food字段仍然保持嵌入在favorites文档中。
> db.users.find({status:"A"},{name:1,status:1,'favorites.food':1})
{ "_id" : 2, "name" : "bob", "status" : "A", "favorites" : { "food" : "meringue" } }
{ "_id" : 3, "name" : "ahn", "status" : "A", "favorites" : { "food" : "cake" } }
{ "_id" : 6, "name" : "abc", "status" : "A", "favorites" : { "food" : "pizza" } }
排除嵌入文档中的特定字段

排除favorites中的food,其他的仍然嵌套显示。

> db.users.find({status:"A"},{'favorites.food':0})
{ "_id" : 2, "name" : "bob", "age" : 42, "type" : 1, "status" : "A", "favorites" : { "artist" : "Miro" }, "finished" : [ 11, 25 ], "badges" : [ "green" ], "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 64, "bonus" : 12 } ] }
{ "_id" : 3, "name" : "ahn", "age" : 22, "type" : 2, "status" : "A", "favorites" : { "artist" : "Cassatt" }, "finished" : [ 6 ], "badges" : [ "blue", "red" ], "points" : [ { "points" : 81, "bonus" : 8 }, { "points" : 55, "bonus" : 20 } ] }
{ "_id" : 6, "name" : "abc", "age" : 43, "type" : 1, "status" : "A", "favorites" : { "artist" : "Picasso" }, "finished" : [ 18, 12 ], "badges" : [ "black", "blue" ], "points" : [ { "points" : 78, "bonus" : 8 }, { "points" : 57, "bonus" : 7 } ] }
映射数组中的嵌入文档

使用dot notation映射嵌入数组中文档的特定字段。dot notation映射代表<array>.<index>格式的数据。

> db.users.find({status:"A"},{name:1,status:1,"points.bonus":1})
{ "_id" : 2, "name" : "bob", "status" : "A", "points" : [ { "bonus" : 20 }, { "bonus" : 12 } ] }
{ "_id" : 3, "name" : "ahn", "status" : "A", "points" : [ { "bonus" : 8 }, { "bonus" : 20 } ] }
{ "_id" : 6, "name" : "abc", "status" : "A", "points" : [ { "bonus" : 8 }, { "bonus" : 7 } ] }
映射返回数组中特定的数组元素(切片)

对于包含数组的字段,MongoDB提供了以下的映射操作符:$elemMatch,$slice,以及$

示例返回数组中的最后一个元素

> db.users.find({status:"A"},{name:1,status:1,"points":{$slice:-1}})
{ "_id" : 2, "name" : "bob", "status" : "A", "points" : [ { "points" : 64, "bonus" : 12 } ] }
{ "_id" : 3, "name" : "ahn", "status" : "A", "points" : [ { "points" : 55, "bonus" : 20 } ] }
{ "_id" : 6, "name" : "abc", "status" : "A", "points" : [ { "points" : 57, "bonus" : 7 } ] }

示例返回数组中的第1,2个元素

> db.users.find({status:"A"},{name:1,status:1,"points":{$slice:[0,2]}})
{ "_id" : 2, "name" : "bob", "status" : "A", "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 64, "bonus" : 12 } ] }
{ "_id" : 3, "name" : "ahn", "status" : "A", "points" : [ { "points" : 81, "bonus" : 8 }, { "points" : 55, "bonus" : 20 } ] }
{ "_id" : 6, "name" : "abc", "status" : "A", "points" : [ { "points" : 78, "bonus" : 8 }, { "points" : 57, "bonus" : 7 } ] }
4、查询值为Null或不存在的字段

首先插入数据:

db.users.insert(
   [
      { "_id" : 900, "name" : null },
      { "_id" : 901 }
   ]
)
相等过滤器

使用相等查询,会返回结果为null的或不存在该字段的数据。

> db.users.find({name:null})
{ "_id" : 900, "name" : null }
{ "_id" : 901 }

注意:

如果在查询中使用了sparse(稀疏索引),那么查询将仅仅匹配null值,而不匹配不存在的字段。

稀疏索引:
稀疏索引指存储那些有被索引键的文档的索引项,即使被索引键的值是null也会被索引(译者注:请注意,这里对null的处理和那些特殊索引的默认稀疏特性有细微差别,比如文本索引,2d索引等)。索引会跳过所有不包含被索引键的文档。这个索引之所以称为 “稀疏” 是因为它并不包括集合中的所有文档。与之相反,非稀疏的索引会索引每一篇文档,如果一篇文档不含被索引键则为它存储一个null值。

类型筛选

在BSON类型中null的值为10,所以可以使用以下方式查询Null:

> db.users.find({name:{$type:10}})
{ "_id" : 900, "name" : null }
存在性筛选

存在性筛选可以筛选出那些不存在该字段的数据,1代表存在,0代表不存在。

> db.users.find({name:{$exists:0}})
{ "_id" : 901 }
5、在mongo命令行中迭代游标

首先插入数据:

db.goods.insertMany([{_id:1,type:1},{_id:2,type:2},{_id:3,type:3}])
手动迭代游标

在mongo命令中,当使用var关键字把find()返回的游标赋值给一个变量时,它将不会自动迭代。

在命令行中,可以调用游标变量迭代最多20次并且打印匹配的文档。

> var myCursor = db.goods.find({type:2})
> myCursor
{ "_id" : 2, "type" : 2 }

可以使用游标的next()方法来访问文档:

> var myCursor = db.goods.find( { type: 2 } )
> while(myCursor.hasNext){print(tojson(myCursor.next()))}
{ "_id" : 2, "type" : 2 }
{ "_id" : 4, "type" : 2 }
{ "_id" : 5, "type" : 2 }
2020-07-09T14:52:14.975+0800 E QUERY    [thread1] Error: error hasNext: false :
DBQuery.prototype.next@src/mongo/shell/query.js:305:1
@(shell):1:38
  • 也可以使用printjson()方法替代print(tojson())
> var myCursor = db.goods.find( { type: 2 } )
> while(myCursor.hasNext){printjson(myCursor.next())}
{ "_id" : 2, "type" : 2 }
{ "_id" : 4, "type" : 2 }
{ "_id" : 5, "type" : 2 }
2020-07-09T14:54:01.521+0800 E QUERY    [thread1] Error: error hasNext: false :
DBQuery.prototype.next@src/mongo/shell/query.js:305:1
@(shell):1:35
  • 也可以使用游标方法forEach()来迭代游标并且访问文档。
> var myCursor = db.goods.find( { type: 2 } )
> myCursor.forEach(printjson)
{ "_id" : 2, "type" : 2 }
{ "_id" : 4, "type" : 2 }
{ "_id" : 5, "type" : 2 }
迭代器索引

在mongo命令行中,可以使用:method:’~cursor.toArray()'方法来迭代游标,并且以数组的形式来返回文档。

> var myCursor = db.goods.find({type:2})
> var documentArray = myCursor.toArray()
> var myDocument = documentArray[0]
> myDocument
{ "_id" : 2, "type" : 2 }
> var myDocument = documentArray[3]
> myDocument
>
Cursor Behaviors(游标行为)
  1. 关闭非活动游标
    默认情况下,服务器将在限制10分钟后或客户端用尽光标后自动关闭光标。要覆盖此行为时,可以使用cursor.noCursorTimeout()
var myCursor = db.users.find().noCursorTimeout();

当设置了noCursorTimeout之后,必须要使用cursor.close()关闭游标或者耗尽游标的方式关闭游标。

  1. 光标隔离
    当光标返回文档时,其他操作可能会与查询交错。对于MMAPv1存储引擎来说,对文档进行干预的写操作可能会导致游标返回一个文档(如果该文档已更改)多次。

MMAPv1是MongoDB基于内存映射文件的原始存储引擎。它在大量插入,读取和就地更新的工作负载方面表现出色

从3.2版本开始。MMAPv1不再是默认存储引擎;WiredTige成为默认的存储引擎。

  1. 光标批次
    MongoDB服务器批量返回查询结果。批处理中的数据量将不超过BSON文档的最大大小。可以使用batchSize()和limit()覆盖默认大小。
    3.4新版功能:find(),aggregate(),listIndexes和listCollections类型的操作每批最多返回16兆字节。batchSize()可以强制执行一个较小的限制,但是不能执行较大的限制。

BSON文档最大大小为16MB,嵌套深度级别不超过100

  1. 当遍历游标并到达返回批处理的末尾时,如果有更多结果,cursor.next()将执行getMore操作以检索下一个批处理。要查看迭代游标时批处理中剩余多少文档,可以使用objsLeftIntatch()方法。
> var myCursor = db.goods.find()
> var myFirstDocument =  myCursor.hasNext()?myCursor.next():null
> myCursor.objsLeftInBatch()
5
Cursor Information(光标信息)

db.serverStatus()方法返回的文档,其中包括度量字段,该指标字段包含metrics.cursor以下信息字段:

  • 自上次服务器重新启动以来超时的游标数
  • 设置了选项DBQuery.Option.noTimeout的打开游标的数量, 以防止一段时间不活动后发生超时
  • “固定”打开游标的数量
  • 打开的游标总数
> db.serverStatus().metrics.cursor
{
        "timedOut" : NumberLong(0),
        "open" : {
                "noTimeout" : NumberLong(0),
                "pinned" : NumberLong(0),
                "total" : NumberLong(0)
        }
}
>

三、更新文档

1、更新介绍

MongoDB中提供了如下的集合更新方式:

方法

描述

db.collection.updateOne()

即使可能有多个文档通过过滤条件匹配到,但是也最多也只更新一个文档。3.2新版功能。

db.collection.updateMany()

更新所有通过过滤条件匹配到的文档。3.2新版功能。

db.collection.replaceOne()

即使可能有多个文档通过过滤条件匹配到,但是也最多也只能替换一个文档。3.2新版功能。

db.collection.update()

即使可能有多个文档通过过滤条件匹配到,但是也最多也只更新或替换一个文档。默认情况下,db.collection.update()只更新一个文档。要更新多个文档时,可以使用 multi选项。

语法:db.collection.update(查询表达式,新值,选项)

注意:使用下面语句时,不是更新数据,而是更新文档。更新就是用新文档替换旧文档。

更新方法需要接收以下参数:

  1. 过滤条件:决定更新哪些文档。使用查询表达是过滤内容。
  2. 更新文档——指定要执行的修改或者替换文档——完全替换匹配文档(除了_id字段)
  3. 选项
2、行为表现
1、原子性

MongoDB中所有的写操作在单一文档层级上是原子的。

2、_id字段

一旦设定,不能更新_id字段的值,也不能用有不同_id字段值得替换文档来替换已经存在的文档。

3、文档大小

当执行更新操作增加的文档大小超过了为该文档分配的内存空间时,更新操作会在磁盘上重定位该文档。

4、字段顺序

MongoDB按照文档写入的顺序整理文档字段,除了以下情况:

  • _id字段始终是文档的第一个字段
  • 包括字段名称的renaming操作可能导致文档中的字段重新排序。

在2.6版开始,MongoDB主动尝试保持字段在文档中的顺序。2.6版本之前,MongoDB不会主动保持文档中的字段的顺序。

5、upsert选项

如果 db.collection.update()db.collection.updateOne()db.collection.updateMany()或者 db.collection.replaceOne()包含 upsert : true 并且 没有文档匹配指定的过滤器,那么此操作会创建一个新文档并插入它。如果有匹配的文档,那么此操作修改或替换匹配的单个或多个文档。

3、更新操作

首先插入数据:

db.users.insertMany(
   [
     {
       _id: 1,
       name: "sue",
       age: 19,
       type: 1,
       status: "P",
       favorites: { artist: "Picasso", food: "pizza" },
       finished: [ 17, 3 ],
       badges: [ "blue", "black" ],
       points: [
          { points: 85, bonus: 20 },
          { points: 85, bonus: 10 }
       ]
     },
     {
       _id: 2,
       name: "bob",
       age: 42,
       type: 1,
       status: "A",
       favorites: { artist: "Miro", food: "meringue" },
       finished: [ 11, 25 ],
       badges: [ "green" ],
       points: [
          { points: 85, bonus: 20 },
          { points: 64, bonus: 12 }
       ]
     },
     {
       _id: 3,
       name: "ahn",
       age: 22,
       type: 2,
       status: "A",
       favorites: { artist: "Cassatt", food: "cake" },
       finished: [ 6 ],
       badges: [ "blue", "Picasso" ],
       points: [
          { points: 81, bonus: 8 },
          { points: 55, bonus: 20 }
       ]
     },
     {
       _id: 4,
       name: "xi",
       age: 34,
       type: 2,
       status: "D",
       favorites: { artist: "Chagall", food: "chocolate" },
       finished: [ 5, 11 ],
       badges: [ "Picasso", "black" ],
       points: [
          { points: 53, bonus: 15 },
          { points: 51, bonus: 15 }
       ]
     },
     {
       _id: 5,
       name: "xyz",
       age: 23,
       type: 2,
       status: "D",
       favorites: { artist: "Noguchi", food: "nougat" },
       finished: [ 14, 6 ],
       badges: [ "orange" ],
       points: [
          { points: 71, bonus: 20 }
       ]
     },
     {
       _id: 6,
       name: "abc",
       age: 43,
       type: 1,
       status: "A",
       favorites: { food: "pizza", artist: "Picasso" },
       finished: [ 18, 12 ],
       badges: [ "black", "blue" ],
       points: [
          { points: 78, bonus: 8 },
          { points: 57, bonus: 7 }
       ]
     }
   ]
)
1、$set——修改指定字段

update只能更新查询到的第一个数据。

  • 使用 $set 操作符更新 favorites.food 字段的值为 "pie" 并更新 type 字段的值为 3,
  • 使用 $currentDate 操作符更新 lastModified 字段的值到当前日期。如果 lastModified 字段不存在, $currentDate 会创建该字段。
> db.users.updateOne({"favorates.artist":"Picasso"},{$set:{"favorites.food":"pie",type:3},$currentDate:{lastModified:true}})
{ "acknowledged" : true, "matchedCount" : 0, "modifiedCount" : 0 }
2、$unset——删除某个列
db.collection.update({name:'lisi'},{$unset:{age:30}})
3、$rename——重命名某个列
db.collection.update({name:'wangwu'},{$rename:{'age':'max-age'}})
4、$inc——增加某个列
db.collection.update({name:'hahaha'},{$inc:{age:20}})
5、选项:{upsert:true/false,multi:true/false}

upsert:true/false:默认为false,为true时,不存在则插入,如果存在就更新。

multi:true/false默认为false,为true时,会更新匹配到的所有数据。

四、删除文档

1、删除的方法

方法

描述

db.collection.remove()

删除所有符合条件的数据,不写条件时删除所有

db.collection.deleteOne()

最多删除一个符合条件的文档。3.2 新版功能.

db.collection.deleteMany()

删除所有匹配指定过滤条件的文档.3.2 新版功能.

注意:

1.查询表达式依然是个json对象{age:20}

2.查询表达式匹配的行,将被删除。

3.如果不写查询表达式,collection中的所有文档将被删除。

2、删除的行为表现
1、索引

即使把文档中的所有数据都删除了,索引也不会被删除。

2、原子性

MongoDB所有写操作在单一文档层级上是原子的。如果想要删除集合中的所有数据,可以直接删除集合,然后重新集合和索引,这种方式更为高效。

3、删除操作

db.collection.remove(查询表达式)

{justOne:true/false},是否只删除一行,默认为false。

  1. 删除stu表中sn属性值为’001’的文档
db.stu.remove({sn:'001'})
  1. 删除stu表中gender属性为m的文档,只删除1行
db.stu.remove({gender:'m',true})
  1. 删除第一个status 字段等于 "A" 的文档
db.users.remove( { status: "D" }, 1)

除所有 |
| db.collection.deleteOne() | 最多删除一个符合条件的文档。3.2 新版功能. |
| db.collection.deleteMany() | 删除所有匹配指定过滤条件的文档.3.2 新版功能. |

注意:

1.查询表达式依然是个json对象{age:20}

2.查询表达式匹配的行,将被删除。

3.如果不写查询表达式,collection中的所有文档将被删除。

2、删除的行为表现
1、索引

即使把文档中的所有数据都删除了,索引也不会被删除。

2、原子性

MongoDB所有写操作在单一文档层级上是原子的。如果想要删除集合中的所有数据,可以直接删除集合,然后重新集合和索引,这种方式更为高效。

3、删除操作

db.collection.remove(查询表达式)

{justOne:true/false},是否只删除一行,默认为false。

  1. 删除stu表中sn属性值为’001’的文档
db.stu.remove({sn:'001'})
  1. 删除stu表中gender属性为m的文档,只删除1行
db.stu.remove({gender:'m',true})
  1. 删除第一个status 字段等于 "A" 的文档
db.users.remove( { status: "D" }, 1)