MongoDB基本操作之CRUD
原文作者: xingguang
原文链接:https://www.tiance.club/post/1234652124.html
创建文档
命令有三种:
创建单个文档:db.collection.insertOne() 创建单个或多个文档:db.collection.insert() 创建多个文档:db.collection.insertMany()
insertOne
示例:
db.goods.insertOne({ name:"哈士奇饼干", price:33, })
返回结果:
{ "acknowledged": true, "insertedId": ObjectId("5e9c52e32a170000ea003e5a") //5e9c544c2a170000ea003e5b为本次插入数据的主键id }
插入复合主键
db.goods.insertOne({ _id:{id:123,type:‘shop‘}, name:"这个是复合组件", price:20.58, })
insertMany
示例:
db.goods.insertMany([ {name:"哈士奇饼干1",price:33,}, {name:"神奇宝贝一只1",stock:100,price:20.58,} ])
返回结果:
{ "acknowledged": true, "insertedIds": [ ObjectId("5e9c56b72a170000ea003e5d"), ObjectId("5e9c56b72a170000ea003e5e") ] } 原文作者: xingguang 原文链接:[https://www.tiance.club/post/1234652124.html](https://www.tiance.club/post/1234652124.html)
insert
示例:
db.goods.insert([ {name:"哈士奇饼干1",price:33,}, {name:"神奇宝贝一只1",stock:100,price:20.58,} ])
返回结果:
BulkWriteResult({ "nRemoved" : 0, "nInserted" : 2, //插入成功的数量 "nUpserted" : 0, "nMatched" : 0, "nModified" : 0, "writeErrors" : [ ] })
查询文档
读取全部文档
既不筛选,也不投射
db.collection.find();
示例:
db.goods.find();
返回结果:
// 1 { "_id": ObjectId("5e9c48b42a170000ea003e45"), "name": "纸巾一包", "price": 100 } // 2 { "_id": ObjectId("5e9c48eb2a170000ea003e48"), "name": "奶茶一杯", "price": 20.58 } // 3 { "_id": ObjectId("5e9c56b72a170000ea003e5d"), "name": "哈士奇饼干1", "price": 33 }
匹配查询
示例:
//查询名字为"纸巾一包"并且价格为100元的数据 db.goods.find({name:"纸巾一包",price:100})
返回结果
{ "_id": ObjectId("5e9c48b42a170000ea003e45"), "name": "纸巾一包", "price": 100 }
复合主键查询
db.goods.find({"_id.type":"shop"})
操作符
比较操作符
{:{$:}}
$eq 匹配字段值相等的文档 (可以用于string和int类型) =
$ne 匹配字段值不等的文档 !=
$gt 匹配字段值大于查询值的文档 >
$gte 匹配字段值大于或等于查询值的文档 >=
$lt 匹配字段值小于查询值的文档 <
$lte 匹配字段值小于或等于查询值的文档 <=
$in 匹配字段值与任意查询值相等的文档 "in"
$nin 匹配字段值与任意查询值不相等的文档 "not in"
//匹配查询 db.goods.find({name:{$eq:"纸巾一包"}})
//in查询 db.goods.find({"name":{$in:["纸巾一包","奶茶一杯"]}})
//读取价格大于32元且小于101元的商品 db.goods.find({price:{$gt:32,$lt:101}})
//复合组件查询 db.goods.find({"_id.type":{$eq:"shop"}}) db.goods.find({"_id.type":{$in:["shop"]}})
逻辑操作符
$not 匹配筛选条件不成立的文档
$and 匹配多个筛选条件全部成立的文档
$or 匹配至少一个筛选条件成立的文档
$nor 匹配多个筛选条件全部不成立的文档
逻辑运算符示例:
//查询价格不小于32元的商品 db.goods.find({price:{$not:{$lt:32}}}) //相当于下面的取反 db.goods.find({price:{$lt:32}})
//获取价格为100,并且名称为"纸巾一包"的商品 db.goods.find({ $and:[ {price:{$eq:100}}, {name:"纸巾一包"} ] }) //可以简写如下 db.goods.find({price:{$eq:100},name:"纸巾一包"})
//获取价格不是100,并且名称不为"纸巾一包"的商品 db.goods.find({ $nor:[ {price:{$eq:100}}, {name:"纸巾一包"} ] }) 注意:nor也会筛选出并不包含查询字段的文档!!比如会把没有price和name字段的文档也查出来!
字段操作符
$exists 匹配包含查询字段的文档 $type 匹配字段符合查询值的文档
$type对应的类型和BSON类型序号
Double 1 String 2 Object 3 Array 4 Binary data 5 Undefined 6 已废弃。 Object id 7 Boolean 8 Date 9 Null 10 Regular Expression 11 JavaScript 13 Symbol 14 JavaScript (with scope) 15 32-bit integer 16 Timestamp 17 64-bit integer 18 Min key 255 Query with -1. Max key 127
示例
//查询复合主键中存在type字段的数据 db.goods.find({"_id.type":{$exists:true}})
//查询存在name字段的数据 db.goods.find({name:{$exists:true}})
//查询类型为普通主键和复合主键的数据 db.goods.find({_id:{$type:["objectId","object"]}})
//查询类型为string的数据 db.goods.find({name:{$type:["string"]}})
数组操作符
$all 匹配数组字段中包含所有查询值的文档 $elemMatch 匹配数组字段中至少存在一个值满足筛选条件的文档
示例
先插入数据 db.goods.insert( [ { name:"皮卡丘一只", price:100, contact:["111111","Alabama","US"] }, { name:"小火龙一只", price:120, contact:[["222222","333333"],"Beijing","China"] } ] )
原文作者: xingguang
原文链接:https://www.tiance.club/post/1234652124.html
//查询contact字段中同时包含"China"和"Beijing"字段的文档 db.goods.find({contact:{$all:["China","Beijing"]}})
//查询联系方式中包含"222222","333333"的文档,注意,这里的数组如果只有"222222"是查询不到的,这里是数组全等的关系 db.goods.find({contact:{$all:[["222222","333333"]]}})
//查询电话号码范围在大于111110和小于222222之间的数据 db.goods.find({contact:{$elemMatch:{$gt:"111110",$lt:"222222"}}})
//查询电话号码范围在"大于111110和小于222222之间"并且"大于211111和小于444444之间"的数据 db.goods.find({ contact:{$all:[ {$elemMatch:{$gt:"111111",$lt:"222222"}}, {$elemMatch:{$gt:"211111",$lt:"444444"}} ]} })
运算操作符
{<field>:{:/pattern/,:‘<options>‘}} {<field>:{:/pattern/<options>}} $regex 在和$in操作符一起使用时,只能使用/pattern/<options>
//读取name字段以"皮"或"j"开头的文档数据 db.goods.find({name:{$in:[/^皮/,/^j/]}}) //读取name字段包含LIE(不区分大小写)的文档数据 db.goods.find({name:{$regex:/LIE/,$options:‘i‘}})
游标
游历完游标中所有文档之后,或者在10分钟之后,游标便会自动关闭
可以使用noCursorTimeout()函数来保持游标一直有效
var myCursor=db.goods.find().noCursorTimeout()
在这之后,在不遍历游标的情况下,你需要主动关闭游标
myCursor.close()
原文作者: xingguang
原文链接:https://www.tiance.club/post/1234652124.html
游标函数
cursor.hasNext() //当还有没遍历完的游标文档时,返回true cursor.next() //获取下一次遍历的游标文档 cursor.forEach(<function>) //遍历游标中所有指向的文档 cursor.limit(<number>) //返回指定条数 cursor.skip(<offest>) //跳过文档中指定数量的文档(传入1表示跳过第一篇文档) cursor.count(<applySkipLimit>) //默认情况下,<applySkipLimit>为false,即cursor.count()不会考虑cursor.skip()和cursor.limit()的效果 cursor.sort(<document>) //这里的<document>定义了排序的要求(1从小到大排序,-1从大到小排序)
var myCursor=db.goods.find(); while(myCursor.hasNext()){ printjson(myCursor.next()); } var myCursor=db.goods.find(); myCursor.forEach(printjson)
db.goods.find().limit(1) db.goods.find().skip(1) db.goods.find().limit(1).count() //返回所有文档总数 db.goods.find().limit(1).count(true) //返回一篇文档
//price字段从大到小排序,并且name字段由小到大排序 (相当于mysql中同时两个排序条件的规则) db.goods.find().sort({price:-1,name:1})
注意事项
cursor.skip(),cursor.limit(),cursor.count()
优先级:count()->skip()->limit()
cursor.skip()在cursor.limit()之前执行 db.goods.find().limit(5).skip(3) 结果返回的是5篇文章,从第4篇到第9篇文章
cursor.count()在cursor.skip()和cursor.limit()之前执行 db.goods.find().limit(5).skip(3).sort({price:-1})
文档投影
db.goods.find(<query>,<projection>) 不使用投影时,db.goods.find()返回符合筛选条件的完整文档 使用投影可以只返回指定的字段
{field:inclusion} 1表示返回部分字段,0表示不返回字段,(1和0不可组合使用,_id字段除外) //只返回name字段 db.goods.find({},{name:1,_id:0}) //返回除name之外的字段 db.goods.find({},{name:0})
//$slide:2,表示返回前2条,-2表示返回倒数2条,[1,2]表示返回第二条到第三条 db.goods.find({},{name:1,content:{$slide:[1,2]}})
$elemMatch和$操作符可以返回数组字段中满足筛选条件的第一个元素
//返回content数组字段中第一个排序大于"Alabama"的数据,(没content字段的文档也会被返回) db.goods.find({},{name:1,content:{$elemMatch:{$gt:"Alabama"}}}) //返回content数组字段中第一个排序大于"Alabama"的数据 db.goods.find({content:{$gt:"Alabama"}},{name:1,"content.$":1,})
更新操作
注意:
1、
db.goods.update(where查询条件,更新的值,其它条件)
db.goods.update({"uid":3},{$rename:{"name":"alias"}},{multi:true})
2、文档更新操作只会更新一篇文档,即使条件符合多篇文档,也只会更新一篇,如果想要更新所有符合条件的文档,需要添加第三个参数{multi:true}
文档更新操作符
$set 更新或新增字段 $unset 删除字段 $rename 重命名字段 {$rename:{<field1>:<newName1>,<field2>:<newName2>}} $inc 加减字段值 (字段不存在时,会默认创建且值为加减的值) $mul 相乘字段值 (字段不存在时,会默认创建且值为0 ) $min 比较减少字段值 (保留最小的值)(字段不存在会自动创建且值为指定的值)(类型不一致按BSON数据类型排序规则比较) $max 比较增大字段值 (保留最大的值)(字段不存在会自动创建且值为指定的值)(类型不一致按BSON数据类型排序规则比较)
//($rename)重命名写法 db.goods.update({"uid":3},{$rename:{"name":"alias"}})
//($rename)将数组字段content中的name字段迁移到最外面的name字段 db.goods.update({"uid":3},{$rename:{"content.name":"name"}})
//($rename)将最外面的name字段迁移到数组字段content中的name字段 db.goods.update({"uid":3},{$rename:{"name":"content.name"}})
//($inc)将条件uid=3的文档,price字段加一 db.goods.update({"uid":3},{$inc:{"price":1}})
//($min)源字段大于50时,修改成50 db.goods.update({"uid":3},{$min:{"price":50}}) (源price值为30时,不变,保留30)
BSON数据类型排序规则 最小 Null Numbers(ints,longs,doubles,decimals) Symbol,String Object Array BinData ObjectId Boolean Date 最大 Regular Expression
数组更新操作符
$addToSet 向数组中增添元素 $pop 从数组中移除元素 $pull 从数组中移除指定元素 $pullAll 从数组中有选择性地移除元素 $push 向数组中增添元素
//($addToSet)将content数组字段添加"nihao","wohao"两个值 db.goods.update({"uid":3},{$addToSet:{"content":{$each:["nihao","wohao"]}}})
//$pull删除content数组中包含"皮"字的字段 db.goods.update({"uid":3},{$pull:{"content":{$regex:/皮/}}})
{$pullAll:{<field>:[<vaule1>,<vaule2>]}} 相当于 {$pull:{<field>:{$in:[<vaule1>,<vaule2>]}}}
更新操作符
$ 第一个符合条件的占位符 $[] 数组中的所有元素
更新数组中的特定元素
$是数组中第一个符合筛选条件的数组元素的占位符,搭配更新操作符使用,可以对满足筛选条件的数组元素进行更新
db.goods.update({<array>:<query selector>},<update operator>:{"<array>.$",vaule})
$[]指代数组字段中的所有元素,搭配更新操作符使用,可以对数组中的所有元素进行更新
db.goods.update({<array>:<query selector>},<update operator>:{"<array>.$[]",vaule})
//源数据 { "_id": ObjectId("5e9f08904757000020000235"), "content": [ "nihao", "我很好" ], "uid": 3, "name": "nihao", "num": 1, "num1": 0 }
//将content数组中值为"nihao"的替换成"updated" db.goods.update({ uid:3, content:"nihao" }, { $set: { "content.$":"updated" } })
将content数组中所有字段替换成"updated" db.goods.update({ uid:3 }, { $set: { "content.$[]":"updated" } })
更新文档选项
{multi:}
更新多个文档
到目前为止,我们在update命令中使用的筛选条件只对应一篇文档
在默认情况下,即使筛选条件对应了多篇文档,update命令仍然只会更新一篇文档
将所有name值为"nihao"的文档num值改成10 db.goods.update({ name:"nihao" }, {$set: {"num":10}},{multi:true})
原子性
在MongoDB中,更新单个的文档操作是原子性的。默认情况下,如果一个update()更新多个文档,那么对每个文档的更新是原子性的,但是对整个update而言则不是原子性的。有可能存在前一个文档更新成功,后面的文档更新失败的情况。由于单个文档的更新是原子性的,如果两个更新同时发生,就会出现阻塞,先到的先执行,所以文档最终结果由靠后的操作决定。 **简单的说就是对同一篇文档进行更新,文档最终结果以最后的更新操作为结果**
删除命令
db.collection.remove() 删除文档 db.collection.drop() 删除集合
注:
1、删除文档默认是删除所有符合条件的文档,和update操作不一样,如果需要指定只删除一篇文档,加上第二个参数({justOne:true})
删除文档
db.<collection>.remove(<query>,<options>) <options>声明了一些删除操作的参数 db.goods.remove()
//删除name值为"nihao"的所有文档 db.goods.remove({name:"nihao"})
//删除name值为"nihao"的一篇文档({justOne:true}) db.goods.remove({name:"nihao"},{justOne:true})
//删除集合内的所有文档 db.goods.remove({})
删除集合
db.<collection>.drop(<writeConcern>,<document>) db.goods.drop()
这里的writeConcern文档定义了本次集合删除操作的安全写级别、
drop命令可以删除整个集合,包括集合中的所有文档,以及集合的索引
原文作者: xingguang
原文链接:https://www.tiance.club/post/1234652124.html