读取文档
db.collection.find()
- 匹配查询
- 查询操作符
- 游标
- 查询操作返回:结果游标
- 游标的迭代与操作
- 投射
- 只返回部分字段
- 内嵌文档的投射
- 数组的投射
实践
使用mongo shell读取文档
全文档查询:db.collection.find()
## <projection>文档定义了对读取结果进行的投射
db.<collection>.find(<query>, <projection>)
读取全部文档:既不筛选,也不投射
db.<collection>.find()
db.<collection>.find().pretty()
## 例子:
db.accounts.find()
## 更清楚的打印文档
db.accounts.find().pretty()
筛选文档:匹配查询
## 读取alice的银行账户文档
db.accounts.find({name:"alice"})
## 读取银行账户类型为储蓄账户的文档
## 注意:
### 当查询条件中涉及子级内容的需要使用""包起来,如"_id.type"
### 一级条件可以不使用"",如name
### 这里建议都使用""包起来
db.accounts.find({"_id.type":"savings",name:"alice"})
筛选文档:比较操作符
{ <field>: { $<operator>: <value> } }
operator | 含义 |
---|---|
eq | 匹配字段值相等的文档 |
ne | 匹配字段值不等的文档 |
gt | 匹配字段值大于查询值的文档 |
gte | 匹配字段值大于或等于查询值的文档 |
lt | 匹配字段值小于查询值的文档 |
lte | 匹配字段值小于或等于查询值的文档 |
in | 匹配字段值与任何一查询值相等的文档 |
nin | 匹配字段值与任何查询值都不等的文档 |
## 使用$eq查询和匹配查询效果相同
db.accounts.find({"name":{$eq:"alice"}})
## 使用$ne查询
### 注意:$ne也会筛选出并不包含查询字段的文档
db.accounts.find({"name":"alice", "balance":{$ne:"200"}})
## 当使用gt,lt,gte,lte进行字符串的比较的时候,会按照的字母的顺序进行比较
## $in $nin
### 格式:{ <field>: { $in/$nin: [<value1>,<value2>...]}}
### 注意:$nin和$ne一样也会筛选出并不包含查询字段的文档
db.accounts.find({"name":{$in:["alice","joke"]}})
db.accounts.find({"name":{$nin:["alice","joke"]}})
筛选文档:逻辑操作符
operator | 含义 |
---|---|
not | 匹配筛选条件不成立的文档 |
and | 匹配多个筛选条件全部成立的文档 |
or | 匹配至少一个筛选条件成立的文档 |
nor | 匹配多个筛选条件全部不成立的文档 |
## $not
### 格式:{ field: { $not: { <operator-expression} } }
### 注意:$not也会筛选出并不包含查询字段的文档
db.accounts.find({balance: {$not: {$lt:500}}})
## $not
### 格式:{$and:[{<expression1},{expression2},...]}
### $and操作符可以被省略
db.accounts.find({$and:[{"balance":{$gt:100}},{"name":{$gt:"fred"}}]})
db.accounts.find({balance:{$gt:100},name:{$gt:"fred"}})
db.accounts.find({balance:{$gt:50,$lt:100}})
筛选文档:字段操作符
operator | 含义 |
---|---|
exists | 匹配包含查询字段的文档 |
type | 匹配字段类型符合查询值的文档 |
## $exists
### 格式:{<field>:{$exists:<boolean>}}
### 注意:当使用$exists操作符时,查询字段必须存在才会被筛选出来
db.accounts.find({"balance":{$exists:true}})
## $type
### 格式1:{field:{$type:<BSON type>}}
### 格式2:{field:{$type:[<BSON type1>,<BSON type2>,...]}}
db.accounts.find({"_id.type":{$type:"string"}})
db.accounts.find({"_id":{$type:["objectId","object"]}})
筛选文档:数组操作符
operator | 含义 |
---|---|
all | 匹配数组字段中包含所有查询值的文档 |
elemMatch | 匹配数组字段中至少存在一个值满足筛选条件的文档 |
## $all
### 格式:{<field>:{$all:[<value1>,<value2>,...]}}
db.accounts.find({contact:{$all:["Beijing","China"]}})
## $elemMatch
### 格式:{<field>:{$elemMatch:{<query1>,<query2>,...}}}
db.accounts.find({"contact":{$elemMatch:{$gt:"100000",$lt:"200000"}})
筛选文档:运算操作符
operator | 含义 |
---|---|
regex | 匹配满足正则表达式的文档 |
## $regex
### 格式1:{<field>:{:/pattern/,:'<options>'}}
### 格式2:{<field>:{:/pattern/<options>}}
### 兼容PCRE v8.41正则表达式库
#### 在和$in操作符一起使用时,只能使用/pattern/<options>
db.accounts.find({"name":{$in:[/^c/, /^j/]})
db.accounts.find({"name":{$regex:/LIE/,$options:'i'}})
文档游标
db.<collection>.find()
返回一个文档集合游标在不迭代游标的情况下,只列出前20个文档。我们也可以使用游标下标直接访问文档集合中的某一个文档
var myCursor = db.accounts.find();
## 遍历游标
### 遍历完游标中所有的文档之后,或者在10分钟后,游标便会自动关闭
myCursor
### 可以使用noCursorTimeout()函数来保持游标一直有效,当然如果遍历完游标,游标也会关闭。在不遍历游标的情况下,需要手动关闭游标
var myCursor = db.accounts.find().noCursorTimeout();
myCursor.close()
游标函数
cursor.hasNext()
cursor.next()
cursor.forEach()
cursor.limit()
cursor.skip()
cursor.count()
cursor.sort()
## <cursor>.hasNext()
## <cursor>.next()
var myCursor = db.accounts.find({"balance":{$gt:20}});
while(myCursor.hasNext()) {
printjson(myCursor.next());
};
## <cursor>.forEach(<function>)
var myCursor = db.accounts.find({"balance":{$gt:20}};
myCursor.forEach(printjson)
## <cursor>.limit(<number>)
### 限制多少条文档
### 注意:<cursor>.limit(0)是返回所有符合条件的文档
db.accounts.find({"balance":{$gt:20}}).limit(1)
## <cursor>.skip(<offset>)
### 跳过多少条文档
db.accounts.find({"balance":{$gt:20}}).skip(1)
## <cursor>.count(<applySkipLimit>)
### 默认情况下,<applySkipLimit>为false,即<cursor>.count()不会考虑<cursor>.limit()和<cursor>.skip()的效果
db.accounts.find({"balance":"200"}).skip(1).limit(1).count(true)
### 在不提供筛选条件时,<cursor>.count()会从集合的元数据Metadata中取得结果
### 当数据库分布式结构较为复杂时,元数据中的文档数量可能不准确
db.accounts.find().count()
## <cursor>.sort(<document>)
### 这里的<document>定义了排序的要求
### 格式:{field:ordering}
### 1表示由小及大的正向排序,-1表示逆向排序
db.accounts.find().sort({"balance":-1,"name":1})
需要注意的是,<cursor>.skip()
在<cursor>.limit()
之前执行,<cursor>.sort()
在在<cursor>.skip()
和<cursor>.limit()
之前执行
文档投影
db.<collection>.find(<query>,<projection>)
不使用投影时,
db.<collection>.find()
返回符合筛选条件的完整文档,而使用投影可以有选择性的返回文档中的部分字段。
### 格式:{field: inclusion}
#### 1表示返回字段,0表示不返回字段
### 注意:除了文档主键之外,我们不可以在投影文档中混合使用包含和不包含这两种操作,要么在投影文档中列出所有应该包含的字段,要么列出所有不应该包含的字段
db.accounts.fin({},{"name":1})
db.accounts.find({"name":{$lt:"fred"}},{"name":1,"_id":0})
## 在数组字段上使用投影
### $slice操作符可以返回数组字段中的部分元素
#### 返回数组中的第一个元素
db.accounts.find({},{"_id":0,"name":1,"contact":{$slice:1}})
#### 返回数组中的倒数第一个元素
db.accounts.find({},{"_id":0,"name":1,"contact":{$slice:-1}})
#### 此时,会先在数组中执行skip(1)操作,然后执行limit(2)操作
db.accounts.find({},{"_id":0,"name":1,"contact":{$slice:[1,2]}})
### $elemMatch和$操作符可以返回数组字段中满足筛选条件的第一个元素
db.accounts.find({},{"_id":0,"name":1,"contact":{$elemMatch:{$gt:"Alabama"}})
### 当查询条件和后面的筛选条件一样时,可以使用$
db.accounts.find({"contact":{$gt:"Alabama"}},{"_id":0,"name":1,"contact.$":1})