前置知识
find 语法
格式:db.COLLECTION_NAME.find(query, projection)
参数说明:
- query:可选,使用查询操作符指定的查询条件。
- projection:可选,使用投影操作符指定返回的键。如果要在查询时返回文档中所有键值,只需省略该参数即可(默认为省略)。
文档查询条件的构造可以参考下表所示。
操作 | 格式 | 范例 |
---|---|---|
等于 | {<key>:<value>} | db.col.find({"by":"x"}) |
小于 | {<key>:{$lt:<value>}} | db.col.find("likes":{$lt:50}}) |
小于等于 | {<key>:{$lte:<value>}} | db.col.find(("likes":{$lte:50}}) |
大于 | {<key>:{$gt:<value>}} | db.col.find("likes":{$gt:50}}) |
大于等于 | {<key>:{$gte:<value>}} | db.col.find("likes":{$gte:50}}) |
不等于 | {<key>:{$ne:<value>}} | db.col.find("likes":{$ne:50}}) |
包含 | {<key>:{$in:[<value1>,...,<valueN>]}} | db.col.find("likes":{$in:[2,3,4]}}) |
不包含 | {<key>:{$nin:[<value1>,...,<valueN>]}} | db.col.find("likes":{$nin:[2,3,4]}}) |
非 | {<key>:{$not:query}} | db.col.find("likes":{$not:{$lt:50}}}) |
解释 非:where not likes < 50
aggregate() 聚合
db.COLLECTION_NAME.aggregate()
- $sum:
- $avg
- $min
- $max
- $first
$last:根据资源文档的排序获取最后一个文档数据
db.mycol.aggregate([{$group:{_id:"$by_user", last_url:{$last:"$url"}}}])
可以使用 limit、skip、sort 限制返回结果数量、忽略一定数量结果、执行排序处理。
数据准备
创建实验数据集合
itmes 集合,保存订单信息。
db
db.createCollection("items")
插入文档数据
pnumber:商品编号
quantity:商品数量
price:商品价格
db.items.insertMany([
{"quantity":2,"price":5.0, "pnumber":"p003"},
{"quantity":2,"price":8.0, "pnumber":"p002"},
{"quantity":1,"price":4.0, "pnumber":"p002"},
{"quantity":2,"price":4.0, "pnumber":"p001"},
{"quantity":4,"price":10.0, "pnumber":"p003"},
{"quantity":10,"price":20.0, "pnumber":"p001"},
{"quantity":10,"price":20.0, "pnumber":"p003"},
{"quantity":5,"price":10.0, "pnumber":"p002"}
])
格式化显示文档
db.items.find().pretty()
文档查询操作
(1) countDocuments()
统计集合中总共多少文档
db.items.countDocuments({})
(2) distinct()
使用 distinct 命令查询指定键的所有不同值,使用时必须指定集合和键。
例如,对 price 键使用 distinct,会得到所有不同的价格。
db.runCommand({"distinct":"items","key":"price"})
(3) 单条件查询
例如,查询价格大于5的商品数据,大于使用 gt 操作符,操作符前面要带上 $ 符号。
db.items.find({price:{$gt:5}})
(4) 多条件查询
多条件组合查询,各个条件之间默认是 AND 关系。
例如,查询 quantity 为 10 且价格大于等于 5 的商品数据。
db.items.find({quantity:10,price:{$gte:5}})
也可以使用 $or 来进行多条件查询,语法格式如下:
db.collectionName.find(
{
$or:[
{key:value},
{key:value}
]
})
例如,查询 quantity 为 10 或价格大于等于 5 的商品数据。
db.items.find({$or:[{quantity:10},{price:{$gte:5}}]})
还可以将 AND 和 OR 联合使用。
例如,查询 pnumber 为"p003"且 quantity 为 10 或价格大于等于 5 的商品数据
db.items.find({
pnumber:"p003",
$or:[
{quantity:10},
{price:{$gte:5}}
]
})
(5) $in 查询
例如,要找出 quantity为2、4、5的文档。
db.items.find({quantity:{$in:[2,4,5]}})
$nin 将返回与数组中所有条件都不匹配的文档。
要是想返回所有 quantity 不是2、4、5 的文档,就可以用:
db.items.find({quantity:{$nin:[2,4,5]}})
说明
值得注意的是,$in能对单个键做OR查询,但是要对多个键做查询就得使用$or。
使用普通的AND型查询时,总是希望尽可能用最少的条件来限定结果的范围。OR型查询正好相反,第一个条件应该尽可能匹配更多的文档,这样才是最为高效的。
$or 操作符在任何情况下都会正常工作,而如果查询优化器可以更高效地处理$in,则应该优先选择使用$in操作符。
(6) $not 查询
以取模运算符 $mod 为例,$mod 会将查询的值除以第一个给定值,若余数等于第二个给定值则匹配成功。
例如,要查询 quantity 值为奇数的文档。
db.items.find({quantity:{$mod:[2,1]}})
要查询 quantity 值为偶数的文档,添加 $not
db.items.find({quantity:{$not:{$mod:[2,1]}}})
(7) null 查询
null 不仅会匹配值为 null 的文档,还会匹配不包含这个键的文档(即返回缺少这个键的所有文档)。
如果仅想匹配键值为 null 的文档,则既要检查该键的值是否为null,还要通过 $exists 条件判定键值已存在。
db.item.find({price:{$in:[null],$exists:true}})
由于没有$eq(等于)操作符,所以这条查询语句看上去麻烦,但是与只有一个元素的$in效果一样。
(8) aggregate 聚合查询
使用group可以执行更复杂的聚合。先选定分组所依据的键,而后MongoDB就会将集合依据选定键的不同值分成若干组。然后可以对每一个分组内的文档进行聚合,最后可以得到一个结果文档。
例如,统计订单中所有商品的数量,即统计quantity的总和。
db.items.aggregate([{
$group:{_id:null,total:{$sum:"$quantity"}}
}])
例如,通过产品类型来进行分组,然后在统计卖出的数量。
db.items.aggregate([{
$group:{_id:"$pnumber",total:{$sum:"$quantity"}}
}])
例如,通过相同的产品类型来进行分组,然后查询相同产品类型中卖出最多的订单详情。
db.items.aggregate([{
$group:{_id:"$pnumber",max:{$max:"$quantity"}}
}])
例如,通过相同的产品类型来进行分组,然后查询每个订单详情相同产品类型卖出的平均价格。
db.items.aggregate([{
$group:{_id:"$pnumber",price:{$avg:"$price"}}
}])
(9) 管道的使用
例如,希望先通过相同的产品类型来进行分组,统计出各个产品的数量,然后再获取最大的数量,可以使用下面的命令。
db.items.aggregate([
{
$group:{_id:"$pnumber",total:{$sum:"$quantity"}}
},
{
$group:{_id:null, max:{$max:"$total"}}
}
])
(10) 查询选项
1. limit
限制返回结果
db.items.find().limit(3)
2. skip
丢弃结果集中的前n个文档,将剩余文档作为结果返回。在“普通”查询中,如果需要跳过大量的数据,那么这个操作符的效率会很低,因为它必须要先匹配到所有需要跳过的文档,然后再将这些文档丢弃。
例如,跳过前3个结果文档,可以使用如下命令。
db.items.find().skip(3)
3. sort
接受一个对象作为参数,该对象是一组键/值对。
- 键对应文档的键名
- 值代表排序的方向,排序方向可以是1(升序)或者-1(降序)
- 如果指定了多个键,则按照这些键被指定的顺序逐个排序。
例如,要按照pnumber升序以及 price降序排序,可以使用下面的命令。
db.items.find().sort({pnumber:1, price:-1})
4. 分页
当点击“下一页”希望看到更多的结果时,可以通过skip非常简单地实现,只需要略过前3个结果即可(因为前3个已经在第一页显示了)
db.items.find().limit(3).skip(3).sort({price:-1})
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。