一、读取文档
读取文档命令
db.<collection>.find({<query>,<projection>}) 复制代码
- :定义读取操作时筛选文档的条件
- :定义了对读取结果进行投射 这两个条件都不是必填的
// 查询所有文档 db.accounts.find() 复制代码
// 查询所有文档,优化显示格式 db.accounts.find().pretty() 复制代码
匹配查询
// 查询name为banner的文档 db.accounts.find({name: "banner"}) // 查询name为banner、balance为1000的文档 db.accounts.find({name: "banner", balance: 1000}) 复制代码
使用复合主键进行匹配查询
使用比较操作符查询
db.<collection>.find({<field>: {$<operator>: <value>}}) 复制代码
- :比较的字段
- $:比较操作符
- :比较的值
比较操作符主要有
- $eq:匹配字段值相等的文档
- $ne:匹配字段值不等的文档
- $gt:匹配字段值大于查询值的文档
- $gte:匹配字段值大于等于查询值的文档
- $lt:匹配字段值小于查询值的文档
- $lte:匹配字段值小于等于查询值的文档
// 读取name等与banner的文档 db.accounts.find({ name: {$eq: "banner"} }) 复制代码
plus:使用$eq可以与之前使用匹配查询达到相同的想过
// 读取name不等与banner的文档 db.accounts.find({ name: {$ne: "banner"} }); // 读取balance不等于100的文档 db.accounts.find({ balance: {$ne: 1000} }); 复制代码
plus:$ne也会筛选出不包含查询字段的文档
// 读取balance大于100的文档 db.accounts.find({ balance: {$gt: 100} }); // 读取name在ban之后的文档 db.accounts.find({ name: {$gt: "ban"} }); 复制代码
- $in:匹配字段值与任意查询值相等的文档
- $nin:匹配字段值与任何查询值都不想等的文档
db.<collection>.find({<field>: {$in或者$nin: [<value1>,<value2>,<value3>...]}}) 复制代码
// 读取name为banner、strange、peter的文档 db.accounts.find({ name: {$in: ["banner", "strange", "peter"]} }) // 读取name为banner、peter之前的其他文档 db.accounts.find({ name: {$nin: ["banner", "peter"]} }) 复制代码
plus:$nin会筛选出并不包含查询字段的文档
使用逻辑操作符查询
db.<collection>.find(<field>: {$<operator>: {<operator-expression>}}) 复制代码
- :比较的字段
- $:逻辑操作符
- :逻辑表达式
逻辑操作符主要有
- $not:匹配筛选条件不成立的文档
- $and:匹配筛选条件全部成立的文档
- $or:匹配至少一个筛选条件成立的文档
- $not:匹配多个筛选条件全都不成立的文档
// 查询余额不小于500的文档 db.accounts.find({balance: {$not: {$lt: 100}}}) 复制代码
$not也会筛选出不包含查询字段的文档
// 查询_id.type不是saving的文档 db.accounts.find({"_id.type": {$not: {$eq: "saving"}}}) 复制代码
$and操作符后可以是一个条件的数组
db.<collection>.find({$and: [{<operator-expression1>}, <operator-expression2>}, <operator-expression3>}, .... ]}) 复制代码
// 查询余额大于100并且用户姓名排在banner之后的文档 db.accounts.find({ $and:[ {"balance": {$gt: 100}}, {"name": {$gt: "banner"}} ] }) 复制代码
不管是在同一字段还是不同字段,$and操作符可以省略
db.accounts.find({ balance: {$lt: 50000, $gt: 100} }) db.accounts.find({ balance: {$gt: 100}, name: {$gt: "banner"} }) 复制代码
// 查询name等与banner或者balance小于1000的文档 db.accounts.find({ $or: [ {name: {$eq: "banner"}}, {balance: {$lt: 1000}} ] }); // 查询balance大于500或者小于1000的文档 db.accounts.find({ $or: [ {balance: {$gt: 500}}, {balance: {$lt: 1000}} ] }); 复制代码
plus:当筛选条件使用的都是$eq操作符时,$or和$in是相同的效果
$nor操作符后可以是一个条件的数组
db.<collection>.find({$nor: [{<operator-expression1>}, <operator-expression2>}, <operator-expression3>}, .... ]}) 复制代码
// 查询name不是banner和peter且balance不为1000的文档 db.accounts.find({ $nor: [ {name: "banner"}, {name: "peter"}, {balance: 1000} ] }) 复制代码
plus:$nor也会筛选出不包含查询字段的文档
使用字段操作符查询
db.<collection>.find({ <field>: {$exists: <boolean>} }) 复制代码
- $exists:匹配包含查询字段的文档
- $type:匹配字段类型符合查询值的文档
// 查询文档主键存在type字段的文档 db.accounts.find({ "_id.type": {$exists: true} }); // 查询文档主键中type不是checking的文档,结果中会包含主键没有type字段的文档 db.accounts.find({ "_id.type": {$ne: "checking"} }); // 查询文档主键中type字段不是checking,但是type字段存在的文档 db.accounts.find({ "_id.type": {$ne: "checking", $exists: true} }) 复制代码
db.<collection>.find({ <field>: {$type: <BSON type>} }) 复制代码
// 查询id的type为string的文档 db.accounts.find({ "_id": {$type: "string"} }); 复制代码
使用数组操作符查询
db.<collection>.find({ <field>: {$all: [<val1>,<val2>,<val3>]} }) 复制代码
- $all:匹配数组字段中包含所有查询值的文档
- $elemMatch:匹配数组字段中至少存在一个值满足筛选条件的文档
先插入包含数组和嵌套数组的文档
// 查找contract地址为CHN Shanghai的文档 db.accounts.find({ contact:{$all: ["CHN","Shanghai"]} }) 复制代码
db.<collection>.find({ <field>: {$elemMath: {<query1>,<query2>,<query3>...}} }) 复制代码
// 查询联系电话范围为1000000至200000000之间的文档 db.accounts.find({ contact: {$elemMathc: {$gt: "10000000", $lt: "200000000"}} }) 复制代码
// 查询一个在100000000至200000000和一个在200000000至300000000之间的联系电话的文档 db.accounts.find({ contact: {$all: [ {$elemMath: {$gt: "100000000", $lt: "200000000"}}, {$elemMath: {$gt: "200000000", $lt: "300000000"}} ]} }) 复制代码
使用运算操作符查询
db.<collection>.find({ <field>: {: /pattern/, : '<options>'} }) 复制代码
db.<collection>.find({ <field>: {: /pattern/<options> } }) 复制代码
在和$in操作符一起使用时只能使用/pattern/
// 查询name以j和c开头的文档 db.accounts.find({ name: {$in: [/^c/,/^j/]} }) 复制代码
// 查询name包含NNER的文档,忽略大小写 db.accounts.find({ name: {$regex: /NNER/, $options: 'i'} }) 复制代码
$options:i 表示不区分大小写
文档游标
查询文档操作会返回结果游标,利用游标的迭代可以进行排序和计数等操作
在不迭代游标的情况下,只列出前20个文档
var myCursor = db.accounts.find(); // 列出前20个文档 myCursor 复制代码
可以使用游标的下标访问文档集合中的某一个文档
游历完游标中的所有文档或者在10分钟后,游标会自动关闭。如果想要游标一直有效可以使用noCursorTimeout()函数来保持游标一直有效,但是需要调用close()函数主动关闭游标
除了noCursorTimeout()和close()函数外有,游标还有以下这些函数可以调用
- hasNext():是否有含有下一个文档,返回布尔值,可以作为while循环的条件
- next():获取游标指向的下一个文档,与hasNext()搭配使用
- forEach():遍历游标
- limit():指定输出数量
- skip():指定跳过的数量
- count():输出文档总数
- sort():对文档集合进行排序
hasNext() 与 next()
var myCursor = db.accounts.find( { name: "strange" } ); // 判断是否含有下一个文档 while(myCursor.hasNext()){ // 打印出游标调用next()函数获取的文档 printjson(myCursor.next()) } 复制代码
forEach()
var myCursor = db.accounts.find( { name: "strange" } ); myCursor.forEach(printjson) 复制代码
limit() 与 skip()
cursor.limit(<number>) cursor.skip(<offset>) 复制代码
limit传入0表示不会对游标进行任何的操作,效果相当于不使用limit函数
count()
默认情况下为false,即cursor.account不会考虑skip()和limit()的效果,设置为true,则会根据limit()和skip()的效果来输出数量
不提供筛选条件时,count()函数会从集合的元数据Metadata中获取结果
sort()
定义了排序的要求,1表示从小到大的正序排列,-1则表示逆序排列
// 对balance按照正序排列,余额相同的情况下按照name逆序排列 db.accounts.find().sort({balance: 1, name: -1}) 复制代码
输出balance的最大值和最小值
skip()的优先级高于limit()
返回文档数量为5,说明先执行的skip后执行的limit(),如果先执行的limit后执行skip(),最终输出的文档数量应该为2而不是5
sort()在skip()和limit()之前执行