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(游标行为)
- 关闭非活动游标
默认情况下,服务器将在限制10分钟后或客户端用尽光标后自动关闭光标。要覆盖此行为时,可以使用cursor.noCursorTimeout()
。
var myCursor = db.users.find().noCursorTimeout();
当设置了
noCursorTimeout
之后,必须要使用cursor.close()
关闭游标或者耗尽游标的方式关闭游标。
- 光标隔离
当光标返回文档时,其他操作可能会与查询交错。对于MMAPv1存储引擎来说,对文档进行干预的写操作可能会导致游标返回一个文档(如果该文档已更改)多次。
MMAPv1是MongoDB基于内存映射文件的原始存储引擎。它在大量插入,读取和就地更新的工作负载方面表现出色
从3.2版本开始。MMAPv1不再是默认存储引擎;WiredTige成为默认的存储引擎。
- 光标批次
MongoDB服务器批量返回查询结果。批处理中的数据量将不超过BSON文档的最大大小。可以使用batchSize()和limit()覆盖默认大小。
3.4新版功能:find(),aggregate(),listIndexes和listCollections类型的操作每批最多返回16兆字节。batchSize()可以强制执行一个较小的限制,但是不能执行较大的限制。
BSON文档最大大小为16MB,嵌套深度级别不超过100
- 当遍历游标并到达返回批处理的末尾时,如果有更多结果,
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中提供了如下的集合更新方式:
方法 | 描述 |
即使可能有多个文档通过过滤条件匹配到,但是也最多也只更新一个文档。3.2新版功能。 | |
更新所有通过过滤条件匹配到的文档。3.2新版功能。 | |
即使可能有多个文档通过过滤条件匹配到,但是也最多也只能替换一个文档。3.2新版功能。 | |
即使可能有多个文档通过过滤条件匹配到,但是也最多也只更新或替换一个文档。默认情况下,db.collection.update()只更新一个文档。要更新多个文档时,可以使用 multi选项。 |
语法:db.collection.update(查询表达式,新值,选项)
注意:使用下面语句时,不是更新数据,而是更新文档。更新就是用新文档替换旧文档。
更新方法需要接收以下参数:
- 过滤条件:决定更新哪些文档。使用查询表达是过滤内容。
- 更新文档——指定要执行的修改或者替换文档——完全替换匹配文档(除了_id字段)
- 选项
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、删除的方法
方法 | 描述 |
删除所有符合条件的数据,不写条件时删除所有 | |
最多删除一个符合条件的文档。3.2 新版功能. | |
删除所有匹配指定过滤条件的文档.3.2 新版功能. |
注意:
1.查询表达式依然是个json对象{age:20}
2.查询表达式匹配的行,将被删除。
3.如果不写查询表达式,collection中的所有文档将被删除。
2、删除的行为表现
1、索引
即使把文档中的所有数据都删除了,索引也不会被删除。
2、原子性
MongoDB所有写操作在单一文档层级上是原子的。如果想要删除集合中的所有数据,可以直接删除集合,然后重新集合和索引,这种方式更为高效。
3、删除操作
db.collection.remove(查询表达式)
{justOne:true/false},是否只删除一行,默认为false。
- 删除stu表中sn属性值为’001’的文档
db.stu.remove({sn:'001'})
- 删除stu表中gender属性为m的文档,只删除1行
db.stu.remove({gender:'m',true})
- 删除第一个
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。
- 删除stu表中sn属性值为’001’的文档
db.stu.remove({sn:'001'})
- 删除stu表中gender属性为m的文档,只删除1行
db.stu.remove({gender:'m',true})
- 删除第一个
status
字段等于"A"
的文档
db.users.remove( { status: "D" }, 1)