内容参考《MongoDB权威指南第2版》
以下内容基本都是参照《MongoDB权威指南第2版》这本书的内容学习并且测试的,目前是第三章和第四章的内容。我用的MongoDB的版本是4.0。
// 一:创建,更新,删除文档
for (var i = 0; i < 100; i++){
// 插入文档_id id不可以重复,不指定id会自动生成id
db.foo.insert({"no":"no_" + i})
}
// 查找一个文档
db.foo.findOne()
//查找所有文档
db.foo.find()
db.foo.find({"no":"no_99"})
//删除文档,永久删除
db.foo.remove({"_id":"id_48"})
//删除foo集合下所有文档,速度快
db.foo.drop()
db.test01.insert({"name":"jenny","enemies":16,"friends":35})
db.test01.findOne({"name":"jenny"})
//修改文档结构
var jenny = db.test01.findOne({"name":"jenny"});
jenny.relationships = {"enemies":16,"friends":35};
jenny.username = jenny.name;
delete jenny.enemies;
delete jenny.friends;
delete jenny.name;
//使用 update 替换集合中的文档,更新最好按 id 更新,否则容易产生duplicate key 错误
db.test01.update({"name":"jenny"},jenny);
db.test01.findOne({"username":"jenny"})
// 修改 $inc(只能用于整型,长整型,或双精度浮点型值) $set $unset $push
db.analytics.insert({"url":"www.example.com","pageviews":52})
// 使用 $inc 增加 pageviews + 1
db.analytics.update({"url":"www.example.com"},{"$inc":{"pageviews":1}})
db.user.insert({"_id":ObjectId(),"name":"liming","sex":"male","location":"china","age":20,"favorite book":"thinking in java"})
// 使用 $set 修改文档
db.user.update({"name":"liming"},{"$set":{"favorite book":"linux"}})
// 使用 $set 修改键的类型
db.user.update({"name":"liming"},{"$set":{"favorite book":["mysql","oracle","python"]}})
// 使用 $set 设置值
db.user.update({"name":"liming"},{"$set":{"hobby":"coding"}})
db.blog.post.insert({"_id":ObjectId(),"title":"A Bolg Post","content":"这里是content","author":{"name":"danny","email":"[email protected]"}})
// 使用 $set 修改内部文档
db.blog.post.update({"_id":ObjectId("5d025c5030974ea7b440f149")},{"$set":{"author.email":"aaa.qq.com"}})
// 使用 $unset 删除 title 这个键
db.blog.post.update({"_id":ObjectId("5d025c5030974ea7b440f149")},{"$unset":{"title":1}})
// 数组操作
// 使用 $push 添加数组内的一个元素,如果没有数组先创建一个数组
db.blog.post.update({"_id":ObjectId("5d025c5030974ea7b440f149")},{"$push":{"comment":{"name":"danny","content":"这个博客很好","email":"[email protected]"}}})
// 使用 $each 子操作符,通过一个 $push 操作添加多个值
db.stock.ticker.update({"_id":ObjectId("5d02623730974ea7b440f14a")},{"$push":{"hourly":{"$each":[12,56,78,44,77,23]}}})
// $slice -10 表示数组保留10个元素, -10 必须为负数, $sort表示排序 -1 倒序 1为正序
// 不能只将 $slice 或 $sort $push 配合使用,必须使 $each
db.movie.update({"genre":"horror"},{"$push":{"top10":{"$each":["movie01","movie02","movie03"],"$slice":-10}}})
db.movie.update({"genre":"horror"},{"$push":{"top10":{"$each":[{"name":"ironman2","rating":2},{"name":"ironman1","rating":1},{"name":"ironman3","rating":3}],"$slice":-10,"$sort":{"rating":-1}}}})
db.user.findOne({name:"liming"})
db.user.insert({name:"liming"})
// $addToSet 插入不重复的值
db.user.update({name:"liming"},{"$push": {"favorite book":"java"}})
db.user.update({name:"liming"},{"$addToSet": {"favorite book":"java"}})
// $addToSet 与 $each 配合使用插入不重复的值
db.user.update({name:"liming"},{"$addToSet": {"email":{"$each":["[email protected]","[email protected]","[email protected]","[email protected]","[email protected]"]}}})
// $pop -1 表示在从头部删除,1表示从尾部删除
db.user.update({name:"liming"},{"$pop":{"email":1}}})
// $pull 会删除所有匹配的值
db.user.update({name:"liming"},{"$pull":{"favorite book":"java"}})
db.blog.findOne()
db.blog.update({"_id":ObjectId("5d025c0d30974ea7b440f148")},{$push: {"comments":{$each: [{"comment":"好","author":"jhon","vote":1},{"comment":"一般","author":"jack","vote":8},{"comment":"非常好","author":"danny","vote":5}]}}})
// 通过下标获取,下标从 0 开始, 使用 $ 用作定位符
db.blog.update({"_id" : ObjectId("5d025c0d30974ea7b440f148")},{$inc: {"comments.0.vote":2}})
db.blog.update({"comments.author":"jenny"},{$set: {"comments.$.author":"danny"}})
// upsert 一种特殊的更新,如果没有找到符合更新条件的文档就会新建一个文档, update 第三个参数为 true 时则为 upsert
db.blog.findOne({name:"jenny"})
db.blog.find()
db.blog.update({"name":"jenny"},{$push: {"comments":{$each: [{"comment":"好","author":"jhon","vote":1},{"comment":"一般","author":"jack","vote":8},{"comment":"非常好","author":"danny","vote":5}]}}},true)
// $setOnInsert 在创建文档的同时并为它赋值,但在之后的所有更新操作中,这个字段的值都不再改变
db.time.find()
db.time.update({},{"$setOnInsert":{"createAt":new Date()}}, true)
// 更新多个文档,update 默认只会更新查找到的第一个文档
db.author.find()
db.author.insert({"name":"danny","age":18,"hobby":"basketball"})
db.author.insert({"name":"jenny","age":18,"hobby":"soccer"})
// update 默认只会修改一个文档(当前MongoDB版本 4.0 )
db.author.update({"age":18},{"$set":{"hobby":"programming"}},false)
// 第四个参数为true 时 修改所有匹配的文档,false仅修改一个, 默认为false
db.author.update({"age":18},{"$set":{"hobby":"programming"}},false,true)
// 使用变量 blog 存储取得的文档
var blog = db.blog.findOne({name:"jenny"})
console.log(blog)
// findAndModify 在一个操作中返回匹配结果并且更新文档,返回的是更新前的文档
// findAndModify 可以有很多可以使用的字段
// query : 用于检索文档的条件; sort : 用于排序; update : 用于对匹配的文档进行更新(update和remove必须有一个)
// remove : 布尔类型,是否删除文档; new : 布尔类型,表示返回更新前还是更新后的文档,默认是更新前的文档
// fields : 文档中需要返回的字段(可选); upsert : 布尔类型,true 表示是一个 upsert类型,默认为false
var author = db.runCommand({"findAndModify":"author",
"query":{age:18},
"sort":{name:1},
"update":{"$set":{"sex":"女"}}
}).value
console.log(author)
db.author.insert({"_id":1})
db.author.insert({"_id":1})
db.author.insert({"id":1})
// 检查最有一次操作是否出现错误
db.getLastError()
// 二: 查询
// 返回 name 是 liming 并且 age 是 20 的文档
db.user.find({name:"liming",age:20})
// 第二个参数指定需要返回的键,默认 _id 是会被返回的。
// 只返回 name 和 age 的键值
db.user.find({},{name:1,age:1})
// 不返回 _id 的键值
db.user.find({},{name:1,_id:0,age:1})
db.user.insert([{name:"zhao",age:18},{name:"qian",age:19},{name:"sun",age:20},{name:"li",age:21},{name:"zhou",age:22}])
// 条件查询
// "$lt" : 小于
// "$gt" : 大于
// "$lte" : 小于等于
// "$gte" : 大于等于
// "$ne" : 不等于
// 查找 年龄 >18 and <=21 的文档
db.user.find({"age":{"$gt":18,"$lte":21}})
// "$in" 、"$nin": 范围查找
db.user.find({"age":{"$in":[18,20]}})
db.user.find({"age":{"$nin":[18,20]}})
// "$or" : 或者, "$and" "$nor"
db.user.find({"$or":[{age:18},{name:"li"}])
// "$mod" : 返回除以第一个数余数为第二个数的文档, 除以5余2的文档
db.user.find({age:{"$mod":[5,2]}})
// "$not" : 取反,
db.user.find({age:{"$not":{"$mod":[5,2]}}})
// null : 会匹配键值为null 并且没有该键的文档
db.user.insert({name:"zheng","age":null)
db.user.find({age:null})
// 如果只查询 包含该键并且键值为 null 的文档 需要使用 "$exists"
db.user.find({age:{"$in":[null],"$exists":true}})
// 正则表达式 使用Perl兼容的正则表达式(PCRE),查找 name 包含 u 的文档,忽略大小写
db.user.find({name:/u/i})
// 查询数组
db.food.insert({"fruit":["apple","banana","peach"])
db.food.insert({"fruit":["apple","kumquat","orange"])
db.food.insert({"fruit":["cherry","banana","apple"])
// 会查询所有包含有 banana 的文档
db.food.find({"fruit":"banana"})
// $all 多个元素匹配数组,查询既包含 banana 又包含 apple 的文档,顺序无所谓
db.food.find({fruit:{"$all":["banana","apple"]}})
// 对整个数组精确匹配查找 , 如果数组内的元素更换顺序不会匹配
db.food.find({"fruit":["apple","kumquat","orange"])
// 不会匹配
db.food.find({"fruit":["apple","kumquat"])
// 查询数组特定位置的元素,使用 key.index 语法指定下标(索引从 0 开始)
db.food.find({"fruit.1":"banana"})
// $size 查询特定长度的数组, $size 不可以和其他查询条件组合使用,比如 $gt
db.food.find({"fruit":{"$size":3}})
// $slice 返回某个键匹配的数组的一个子集, $slice 会默认返回所有的键值
// 返回后两条评论
db.blog.post.findOne({"author.name":"danny"},{"comment":{"$slice":-2}})
// 跳过前5条评论,再返回5条后的3条评论
db.blog.post.findOne({"author.name":"danny"},{"comment":{"$slice":[5,3]}})
返回一个匹配的元素, 使用$操作符得到一个匹配的元素
db.blog.post.find({"comment.name":"danny"},{"comment.$":1})
// $elemMatch 要求MongoDB同时使用查询条件中的两个语句与一个数组元素进行比较,但是不会匹配非数组元素
db.test02.insert([{"x":[5,25]},{"x":[12,15]}])
db.test02.find({x:{"$elemMatch":{"$gt":10,"$lt":20}}})
// 查询内嵌文档,查询一个完整的子文档,子文档必须精确匹配,并且查询还与顺序相关
db.blog.insert({"content":"dddddd","comments":[{"author":"joe","score":3,"comment":"nice blog"},{"author":"mary","score":6,"comment":"bad blog"}]})
// 查不到, 内嵌文档必须精确匹配
db.blog.find({"comments":{"author":"joe","score":{"$gt":2}})
// 可以查到 精确匹配
db.blog.find({"comments":{"author":"joe","score":3,"comment":"nice blog"}})
// 可以查到, 使用 . 表示进入内嵌文档内部,值针对内嵌文档的特定值进行查询
db.blog.find({"comments.author":"joe","comments.score":{"$gt":2}})
// 可以查到 $elemMatch 将限定条件进行分组,仅当需要对一个内嵌文档的多个键操作时才会用到
db.blog.find({"comments":{"$elemMatch":{"author":"joe","score":{"$gt":2}}}})
// 可以查到 查询符合comments.author是joe的匹配到了第一条 , comments.score是4的匹配到了第二条,会匹配到
db.blog.find({"comments.author":"joe","comments.score":{"$gt":4}})
// 查不到 会将 comments 数组内的所有键值都与 "author":"joe","score":{"$gt":4} 进行匹配
db.blog.find({"comments":{"$elemMatch":{"author":"joe","score":{"$gt":4}}}})
db.blog.find()
// 游标 shell并不立即查询数据库,当执行 hasNext()时查询发往服务器,sell会立刻获取前100个结果或者前4MB数据(两者中较小的),
// 当用光第一组结果,shell会再一次联系数据库
var cursor = db.foo.find()
while(cursor.hasNext()){
var foo = cursor.next()
console.log(foo)
}
var cursor = db.foo.find()
cursor.forEach(function(foo){
print(foo.no)
})
// sort()排序:1 升序,-1 降序 ; skip()跳过前几条数据 ; limit()取多少条数据
// 因为一个键值可能是多种数据类型,混合类型的键排序是预先定义好的 :
// 最小值