1. find 读取文档
db.<collection>.find(<query>,<projection>)
- query : 定义了读取操作时筛选文档的条件
- projection : 定义了对读取结果进行的投射,也就是只返回某些字段
1.1 读取文档
不进行筛选和投射
> db.user.find()
{ "_id" : "1", "money" : 1000, "name" : "刘一" }
{ "_id" : "2", "money" : 1000, "name" : "陈二" }
{ "_id" : "3", "money" : 1000, "name" : "张三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
{ "_id" : "5", "money" : 1000, "name" : "王五" }
{ "_id" : "6", "money" : 1000, "name" : "赵六" }
{ "_id" : "7", "money" : 1000, "name" : "孙七" }
{ "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "money" : 1000, "name" : "周八" }
{ "_id" : { "age" : 18, "gender" : "男" }, "money" : 1000, "name" : "吴九" }
>
查询 name 为 张三的文档
> db.user.find({"name":"张三"})
{ "_id" : "3", "money" : 1000, "name" : "张三" }
>
1.2 pretty 格式化显示文档
> db.user.find().pretty()
{ "_id" : "1", "money" : 1000, "name" : "刘一" }
{ "_id" : "2", "money" : 1000, "name" : "陈二" }
{ "_id" : "3", "money" : 1000, "name" : "张三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
{ "_id" : "5", "money" : 1000, "name" : "王五" }
{ "_id" : "6", "money" : 1000, "name" : "赵六" }
{ "_id" : "7", "money" : 1000, "name" : "孙七" }
{
"_id" : ObjectId("5fff6a78025e5d9ea86e18cc"),
"money" : 1000,
"name" : "周八"
}
{
"_id" : {
"age" : 18,
"gender" : "男"
},
"money" : 1000,
"name" : "吴九"
}
>
1.3 筛选文档:比较操作符
{<field>:{$<operator>:<value>}}
比较操作符 $<operator>
:
- $eq : 匹配字段值相等的文档
- $ne : 匹配字段值不相等的文档
- $gt : 匹配字段值大于查询值的文档
- $gte : 匹配字段值大于或等于查询值的文档
- $lt : 匹配字段值小于查询值的文档
- $lte : 匹配字段值小于或等于查询值的文档
- KaTeX parse error: Expected 'EOF', got '匹' at position 6: in : 匹̲配字段值与任一查询值相等的文档…in:[,…]}}`
- KaTeX parse error: Expected 'EOF', got '匹' at position 7: nin : 匹̲配字段值与任一查询值不相等的文…nin:[,…]}}`
查询 money 等于 1000的文档,和查询 money 大于 1000的文档
# 查询 money 等于 1000的文档
> db.user.find({"money":{$eq: 1000}})
{ "_id" : "1", "money" : 1000, "name" : "刘一" }
{ "_id" : "2", "money" : 1000, "name" : "陈二" }
{ "_id" : "3", "money" : 1000, "name" : "张三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
{ "_id" : "5", "money" : 1000, "name" : "王五" }
{ "_id" : "6", "money" : 1000, "name" : "赵六" }
{ "_id" : "7", "money" : 1000, "name" : "孙七" }
{ "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "money" : 1000, "name" : "周八" }
{ "_id" : { "age" : 18, "gender" : "男" }, "money" : 1000, "name" : "吴九" }
# 查询 money 大于 1000的文档
> db.user.find({"money":{$gt: 1000}})
>
查询 name 为 张三或者赵六的文档
> db.user.find({"name":{$in: ["张三","赵六"]}})
{ "_id" : "3", "money" : 1000, "name" : "张三" }
{ "_id" : "6", "money" : 1000, "name" : "赵六" }
>
1.3 筛选文档:逻辑操作符
逻辑操作符 $<operator>
:
- $not 匹配筛选条件不成立的文档
- $and 匹配多个筛选条件全部成立的文档
- $or 匹配至少一个筛选条件成立的文档
- $nor 匹配多个筛选条件全部不成立的文档
1.3.1 $and 匹配多个筛选条件全部成立的文档
{$and: [{<expression1>},{<expression2>},...,{<expressionN>}]}
查询 money<2000 , name = 张三 的文档
> db.user.find({$and: [{"money":{$lt:2000}},{"name":"张三"}]})
{ "_id" : "3", "money" : 1000, "name" : "张三" }
>
字段名可以用双引号引起来,也可以不用双引号。
当筛选条件应用在不同的字段上时,可以省略 $and 操作符
查询 money<2000 , name = 张三 的文档,省略 $and
> db.user.find({money:{$lt:2000},name:"张三"})
{ "_id" : "3", "money" : 1000, "name" : "张三" }
>
当筛选条件应用在同一个字段上时,也可以简化命令
查询 money > 500 且 money < 2000 的文档
> db.user.find({money:{$gt:500, $lt:2000}})
{ "_id" : "1", "money" : 1000, "name" : "刘一" }
{ "_id" : "2", "money" : 1000, "name" : "陈二" }
{ "_id" : "3", "money" : 1000, "name" : "张三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
{ "_id" : "5", "money" : 1000, "name" : "王五" }
{ "_id" : "6", "money" : 1000, "name" : "赵六" }
{ "_id" : "7", "money" : 1000, "name" : "孙七" }
{ "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "money" : 1000, "name" : "周八" }
{ "_id" : { "age" : 18, "gender" : "男" }, "money" : 1000, "name" : "吴九" }
>
1.3.2 $or 匹配至少一个筛选条件成立的文档
{$or: [{<expression1>},{<expression2>},...,{<expressionN>}]}
查询 name 为 张三 或者 李四 的文档
> db.user.find({$or: [{"name":"张三"},{"name":"李四"}]})
{ "_id" : "3", "money" : 1000, "name" : "张三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
>
上面的操作等同于
> db.user.find({name:{$in:["张三","李四"]}})
{ "_id" : "3", "money" : 1000, "name" : "张三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
>
1.3.3 $nor 匹配多个筛选条件全部不成立的文档
{$nor: [{<expression1>},{<expression2>},...,{<expressionN>}]}
查询 name 不为 张三 和 李四 的文档
> db.user.find({$nor: [{"name":"张三"},{"name":"李四"}]})
{ "_id" : "1", "money" : 1000, "name" : "刘一" }
{ "_id" : "2", "money" : 1000, "name" : "陈二" }
{ "_id" : "5", "money" : 1000, "name" : "王五" }
{ "_id" : "6", "money" : 1000, "name" : "赵六" }
{ "_id" : "7", "money" : 1000, "name" : "孙七" }
{ "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "money" : 1000, "name" : "周八" }
{ "_id" : { "age" : 18, "gender" : "男" }, "money" : 1000, "name" : "吴九" }
>
1.4 字段操作符
1.4.1 $exists 匹配包含查询字段的文档
{field: {$exists: <boolean>}}
查询包含 name 字段的文档
> db.user.find({name: {$exists: true}})
{ "_id" : "1", "money" : 1000, "name" : "刘一" }
{ "_id" : "2", "money" : 1000, "name" : "陈二" }
{ "_id" : "3", "money" : 1000, "name" : "张三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
{ "_id" : "5", "money" : 1000, "name" : "王五" }
{ "_id" : "6", "money" : 1000, "name" : "赵六" }
{ "_id" : "7", "money" : 1000, "name" : "孙七" }
{ "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "money" : 1000, "name" : "周八" }
{ "_id" : { "age" : 18, "gender" : "男" }, "money" : 1000, "name" : "吴九" }
查询包含 phone 字段的文档
> db.user.find({phone: {$exists: true}})
>
1.4.2 $type 匹配字段类型符合查询值的文档
查询 _id 为 string 类型的文档
> db.user.find({_id: {$type: "string"}})
{ "_id" : "1", "money" : 1000, "name" : "刘一" }
{ "_id" : "2", "money" : 1000, "name" : "陈二" }
{ "_id" : "3", "money" : 1000, "name" : "张三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
{ "_id" : "5", "money" : 1000, "name" : "王五" }
{ "_id" : "6", "money" : 1000, "name" : "赵六" }
{ "_id" : "7", "money" : 1000, "name" : "孙七" }
>
查询 _id 不为 string 类型的文档
> db.user.find({_id: {$not:{$type: "string"}}})
{ "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "money" : 1000, "name" : "周八" }
{ "_id" : { "age" : 18, "gender" : "男" }, "money" : 1000, "name" : "吴九" }
>
1.5 数组操作
1.5.1 $all 匹配数组字段中包含所有查询值的文档
{field: {$all: [<value1>,<value2>,..,<valueN>]}}
插入一条包含数组字段 addr 的文档,并进行 $all 匹配
# 插入一条包含数组字段 addr 的文档
> db.user.insert({"money":3000,"name":"广东人", addr: ["广州","深圳"]})
WriteResult({ "nInserted" : 1 })
# 匹配 addr 字段中包含 "广州","深圳" 的 文档
> db.user.find({addr: {$all:["广州","深圳"]}})
{ "_id" : ObjectId("5fff8fe79dbe959b53a603b6"), "money" : 3000, "name" : "广东人", "addr" : [ "广州", "深圳" ] }
# 匹配 addr 字段中包含 "广州" 的 文档
> db.user.find({addr: {$all:["广州"]}})
{ "_id" : ObjectId("5fff8fe79dbe959b53a603b6"), "money" : 3000, "name" : "广东人", "addr" : [ "广州", "深圳" ] }
# 匹配 addr 字段中包含 "广州","北京" 的 文档
> db.user.find({addr: {$all:["广州","北京"]}})
>
1.5.2 $elemMatch 匹配数组字段中至少存在一个值满足筛选条件的文档
{field: {$elemMatch: [<query1>,<query2>,..,<queryN>]}}
查询 addr 数组字段的任意一个item 匹配是 “广州”的文档
> db.user.find({addr: {$elemMatch: {$eq: "广州"}}})
{ "_id" : ObjectId("5fff8fe79dbe959b53a603b6"), "money" : 3000, "name" : "广东人", "addr" : [ "广州", "深圳" ] }
>
1.6 正则匹配
{field: {$regex:/pattern/, $options: "options"}}
数据准备
> db.user.insert({"money":2000,"name":"zhangsan", addr: ["广州","北京"]})
WriteResult({ "nInserted" : 1 })
> db.user.insert({"money":2000,"name":"ZHANG", addr: ["三亚","北京"]})
WriteResult({ "nInserted" : 1 })
> db.user.find()
{ "_id" : "1", "money" : 1000, "name" : "刘一" }
{ "_id" : "2", "money" : 1000, "name" : "陈二" }
{ "_id" : "3", "money" : 1000, "name" : "张三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
{ "_id" : "5", "money" : 1000, "name" : "王五" }
{ "_id" : "6", "money" : 1000, "name" : "赵六" }
{ "_id" : "7", "money" : 1000, "name" : "孙七" }
{ "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "money" : 1000, "name" : "周八" }
{ "_id" : { "age" : 18, "gender" : "男" }, "money" : 1000, "name" : "吴九" }
{ "_id" : ObjectId("5fff8fe79dbe959b53a603b6"), "money" : 3000, "name" : "广东人", "addr" : [ "广州", "深圳" ] }
{ "_id" : ObjectId("5fff955d3f6d5ed2fcce4132"), "money" : 2000, "name" : "zhangsan", "addr" : [ "广州", "北京" ] }
{ "_id" : ObjectId("5fff95783f6d5ed2fcce4133"), "money" : 2000, "name" : "ZHANG", "addr" : [ "三亚", "北京" ] }
>
查询 name 以 zhang 开头的文档
> db.user.find({name: {$regex: /^zhang/}})
{ "_id" : ObjectId("5fff955d3f6d5ed2fcce4132"), "money" : 2000, "name" : "zhangsan", "addr" : [ "广州", "北京" ] }
>
查询 name 以 zhang 开头的文档,并忽略大小写
> db.user.find({name: {$regex: /^zhang/, $options: "i"}})
{ "_id" : ObjectId("5fff955d3f6d5ed2fcce4132"), "money" : 2000, "name" : "zhangsan", "addr" : [ "广州", "北京" ] }
{ "_id" : ObjectId("5fff95783f6d5ed2fcce4133"), "money" : 2000, "name" : "ZHANG", "addr" : [ "三亚", "北京" ] }
>
2. 文档游标
db.collection.find()
返回一个文档集合游标(cursor)。
游标常用函数有:
- cursor.limit()
- cursor.skip()
- cursor.count()
- cursor.sort()
2.1 cursor.limit(<number>) 限制返回结果的最大数量
只返回前3条记录
> db.user.find().limit(3)
{ "_id" : "1", "money" : 1000, "name" : "刘一" }
{ "_id" : "2", "money" : 1000, "name" : "陈二" }
{ "_id" : "3", "money" : 1000, "name" : "张三" }
>
limit(0) 不做数量限制,返回所有
> db.user.find().limit(0)
{ "_id" : "1", "money" : 1000, "name" : "刘一" }
{ "_id" : "2", "money" : 1000, "name" : "陈二" }
{ "_id" : "3", "money" : 1000, "name" : "张三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
{ "_id" : "5", "money" : 1000, "name" : "王五" }
{ "_id" : "6", "money" : 1000, "name" : "赵六" }
{ "_id" : "7", "money" : 1000, "name" : "孙七" }
{ "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "money" : 1000, "name" : "周八" }
{ "_id" : { "age" : 18, "gender" : "男" }, "money" : 1000, "name" : "吴九" }
{ "_id" : ObjectId("5fff8fe79dbe959b53a603b6"), "money" : 3000, "name" : "广东人", "addr" : [ "广州", "深圳" ] }
{ "_id" : ObjectId("5fff955d3f6d5ed2fcce4132"), "money" : 2000, "name" : "zhangsan", "addr" : [ "广州", "北京" ] }
{ "_id" : ObjectId("5fff95783f6d5ed2fcce4133"), "money" : 2000, "name" : "ZHANG", "addr" : [ "三亚", "北京" ] }
>
2.2 cursor.skip(<offset>) 跳过前面几条记录
跳过前3条记录
> db.user.find().skip(3)
{ "_id" : "4", "money" : 1000, "name" : "李四" }
{ "_id" : "5", "money" : 1000, "name" : "王五" }
{ "_id" : "6", "money" : 1000, "name" : "赵六" }
{ "_id" : "7", "money" : 1000, "name" : "孙七" }
{ "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "money" : 1000, "name" : "周八" }
{ "_id" : { "age" : 18, "gender" : "男" }, "money" : 1000, "name" : "吴九" }
{ "_id" : ObjectId("5fff8fe79dbe959b53a603b6"), "money" : 3000, "name" : "广东人", "addr" : [ "广州", "深圳" ] }
{ "_id" : ObjectId("5fff955d3f6d5ed2fcce4132"), "money" : 2000, "name" : "zhangsan", "addr" : [ "广州", "北京" ] }
{ "_id" : ObjectId("5fff95783f6d5ed2fcce4133"), "money" : 2000, "name" : "ZHANG", "addr" : [ "三亚", "北京" ] }
>
2.3 cursor.count(<applySkipLimit>) 统计数量
默认情况下,<applySkipLimit>为false,即 cursor.count() 不会考虑 cursor.skip() 和 cursor.limit() 的效果
默认情况下,<applySkipLimit>为false
limit(3),查看 <applySkipLimit>为false和true,count() 的结果
# 默认情况下,applySkipLimit = false
> db.user.find().limit(3).count()
12
# applySkipLimit = true
> db.user.find().limit(3).count(true)
3
# applySkipLimit = false
> db.user.find().limit(3).count(false)
12
>
在不提供筛选条件时,cursor.count() 会从集合的元数据 Metadata中取得结果。
当数据库分布式结构较为复杂时,元数据中的文档数量可能不准确,在这种情况下,应该避免应用不提供筛选条件的 cursor.count() 函数,而是用聚合管道来计算文档数量。
2.4 cursor.sort() 排序
cursor.sort(<document>)
这里的 <document> 定义了排序的要求{field: ordering}
- 1 : 表示由小到大的正向排序
- -1 : 表示逆向排序
按照 money 逆向排序从大到小,name 按字母正向排序的方式排列
> db.user.find().sort({money: -1,name: 1})
{ "_id" : ObjectId("5fff8fe79dbe959b53a603b6"), "money" : 3000, "name" : "广东人", "addr" : [ "广州", "深圳" ] }
{ "_id" : ObjectId("5fff95783f6d5ed2fcce4133"), "money" : 2000, "name" : "ZHANG", "addr" : [ "三亚", "北京" ] }
{ "_id" : ObjectId("5fff955d3f6d5ed2fcce4132"), "money" : 2000, "name" : "zhangsan", "addr" : [ "广州", "北京" ] }
{ "_id" : "1", "money" : 1000, "name" : "刘一" }
{ "_id" : { "age" : 18, "gender" : "男" }, "money" : 1000, "name" : "吴九" }
{ "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "money" : 1000, "name" : "周八" }
{ "_id" : "7", "money" : 1000, "name" : "孙七" }
{ "_id" : "3", "money" : 1000, "name" : "张三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
{ "_id" : "5", "money" : 1000, "name" : "王五" }
{ "_id" : "6", "money" : 1000, "name" : "赵六" }
{ "_id" : "2", "money" : 1000, "name" : "陈二" }
>
2.5 cursor.sort()、cursor.skip()、cursor.limit()执行顺序
cursor.skip()在cursor.limit()之前执行
无论如何调换 skip() 和 limit() 的顺序,都是先执行 skip,再执行 limit
> db.user.find().limit(3).skip(1)
{ "_id" : "2", "money" : 1000, "name" : "陈二" }
{ "_id" : "3", "money" : 1000, "name" : "张三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
> db.user.find().skip(1).limit(3)
{ "_id" : "2", "money" : 1000, "name" : "陈二" }
{ "_id" : "3", "money" : 1000, "name" : "张三" }
{ "_id" : "4", "money" : 1000, "name" : "李四" }
>
cursor.sort()在cursor.skip()和cursor.limit()之前执行
> db.user.find().limit(4).skip(1).sort({money: -1,_id: 1})
{ "_id" : ObjectId("5fff955d3f6d5ed2fcce4132"), "money" : 2000, "name" : "zhangsan", "addr" : [ "广州", "北京" ] }
{ "_id" : ObjectId("5fff95783f6d5ed2fcce4133"), "money" : 2000, "name" : "ZHANG", "addr" : [ "三亚", "北京" ] }
{ "_id" : "1", "money" : 1000, "name" : "刘一" }
{ "_id" : "2", "money" : 1000, "name" : "陈二" }
>
3. 文档投影
db.collection.find(<query>,<projection>)
不使用投影时,db.collection.find() 返回符合筛选条件的完整文档,而使用投影可以有选择性地返回文档中的部分字段
{field: inclusion}
- 1 : 表示返回字段,
- 0 : 表示不返回字段
只返回 name 字段,默认情况下 _id 字段都会返回
> db.user.find({},{name: 1})
{ "_id" : "1", "name" : "刘一" }
{ "_id" : "2", "name" : "陈二" }
{ "_id" : "3", "name" : "张三" }
{ "_id" : "4", "name" : "李四" }
{ "_id" : "5", "name" : "王五" }
{ "_id" : "6", "name" : "赵六" }
{ "_id" : "7", "name" : "孙七" }
{ "_id" : ObjectId("5fff6a78025e5d9ea86e18cc"), "name" : "周八" }
{ "_id" : { "age" : 18, "gender" : "男" }, "name" : "吴九" }
{ "_id" : ObjectId("5fff8fe79dbe959b53a603b6"), "name" : "广东人" }
{ "_id" : ObjectId("5fff955d3f6d5ed2fcce4132"), "name" : "zhangsan" }
{ "_id" : ObjectId("5fff95783f6d5ed2fcce4133"), "name" : "ZHANG" }
>
只返回 name 字段,不包含 _id 字段
> db.user.find({},{name: 1,_id: 0})
{ "name" : "刘一" }
{ "name" : "陈二" }
{ "name" : "张三" }
{ "name" : "李四" }
{ "name" : "王五" }
{ "name" : "赵六" }
{ "name" : "孙七" }
{ "name" : "周八" }
{ "name" : "吴九" }
{ "name" : "广东人" }
{ "name" : "zhangsan" }
{ "name" : "ZHANG" }
>
除了文档主键外,不可以在投影文档中混合使用包含和不包含两种投影操作
> db.user.find({},{name: 1,_id: 0,money: 0})
Error: error: {
"ok" : 0,
"errmsg" : "Cannot do exclusion on field money in inclusion projection",
"code" : 31254,
"codeName" : "Location31254"
}
> db.user.find({},{name: 1,_id: 0,money: 1})
{ "money" : 1000, "name" : "刘一" }
{ "money" : 1000, "name" : "陈二" }
{ "money" : 1000, "name" : "张三" }
{ "money" : 1000, "name" : "李四" }
{ "money" : 1000, "name" : "王五" }
{ "money" : 1000, "name" : "赵六" }
{ "money" : 1000, "name" : "孙七" }
{ "money" : 1000, "name" : "周八" }
{ "money" : 1000, "name" : "吴九" }
{ "money" : 3000, "name" : "广东人" }
{ "money" : 2000, "name" : "zhangsan" }
{ "money" : 2000, "name" : "ZHANG" }
>
共同学习,写下你的评论
评论加载中...
作者其他优质文章