从当年写毕业论文学习如何使用mongodb,到现在陆陆续续的在使用。一直都没有系统的去看看mongodb的文档。由于moogoose的原因,最近又在操作
mongodb,想想磨刀不误砍柴工,看看文档,动动笔记录记录。
在mongodb中有db,collection,document数据模型,今天先来说说mongodb的基元document的操作。mongodb所有的操作都围绕document来做。document相当于
传统关系型数据库中的row
插入document
类似关系型数据库,一条条的row插入到table中,而NoSql中的一个个document 插入到collection中。
插入document的语句有如下几种:
db.collection_name.insert()
db.collection_name.insertOne()
db.collection_name.insertMany()
通过字面意思也知道这几种插入方法的不同。其中1既可以插入一个document,也可以插入多个。而2,3是后续版本中添加的。mongodb的所有的写操作都是原子(atomic)。
mongodb的document都包含一个 _id 字段,该字段类似于关系型数据库中的primary
key。其中_id可以在插入文档候自定义赋值,如
db.some_col.insert({"_id":6,
"name": 'suwen'
})
也可以不显示指明,如果没有显示指明则mongodb会根据时间戳+pid+随机数信息生成一个类型为objectid的_id 值。如:
db.some_col.insert({"name":'suwen'})
通过查询,其_id值为5750f3b164cfe92c28a4c2b1。且mongodb含有从 _id中提取时时间戳信息的命令。
查询document
在mongo中document的查询语句如下:
db.collection.find(<query>,<projection>)
db.collection.findOne(<query>,<projection>)
其中query为查询语句,而为optional参数对查询返回的字段进行过滤。可以控制查询结果的传输量。
其中findOne可以直接获取一个document,而find获取多个document。则在获取document的中的某个字段值的时候需要注意。如:
var dd=db.testpoint.findOne({name:"id1"})
dd.name // id1
var dd=db.testpoint.find({name:"id1"})
dd.name //no result to show
dd[0].name //id1
当find()不添加任何参数或者参数为{}的时候,表示查询当前collection中的所有document。
- project
project格式如下:{field1:,field2:..}其中字段值只有0和1两类。其中0表示字段排除,1表示字段包含。
db.testpoint.findOne({name:"id1"},{_id:0}) //查询结果不包含_id 信息
- query
mongo提供了非常丰富的query,来应用不同场景的查询。
大体分为下面几类:
1.简单相等查询
db.some_col.find({"name":"suwen"})
AND条件查询,直接多个字段
db.some_col.find({"name":"suwen",'gender':'male'})
其他的OR条件或者比较查询需要与操作符进搭配使用。
2.与操作符结合判断
mongod提供了一些犹如关系型数据库中的操作符$in,$lt等。如
db.some_col.find({"name":{$in:["suwen,mb"]}})
用法和关系型数据库的in操作符一样。后面会专门写篇文章来学习这些关键字。
3.嵌套和引用文档的查询
mongodb 通过嵌套和应用构建复杂的document,这两者怎么查询呢?
有如下document:
db.users.insert([{
username: 'suwen',
contact: { //嵌套document
phone: '111111111',
email: '1111@qq.com'},
department: { //嵌套document
level: 0,
title: "giser"},
hobby: ['eating','sleeping','hit doudou'] //Array
},
{
username: 'jmb',
contact: { //嵌套document
phone: '222222222',
email: '2222@qq.com'},
department: { //嵌套document
level: 0,
title: "loser"
},
hobby: ['sleeping','eating'] //Array
}])
嵌套document的查询有两种方式:
一是文档完全匹配的形式
如find上面的记录需要使用如下语句:
db.users.find(
{
contact: {
phone: '111111111',
email: '1111@qq.com'
}
})
那么如果我只想以电话作为条件是不是可以使用如下这种形式????
db.users.find(
{
contact: {
phone: '111111111'
}
}) //no results
执行完,发现并没有结果出现。。这也是为何这种方式叫文档完全匹配。如果只使用嵌套文档中的某个字段作为条件来过滤,则需要使用如下第二种方式:
二是通过dot notation的形式,该形式的格式为<document>.<field>
db.users.find(
{
'contact.phone':'111111111'
})
4.Array的查询
有了上面几个基础,再来理解Array的查询就容易多了。 document的字段值可能是一个Array类型。如何对Array的值进行判断,从而来筛选document呢?
一是完全匹配形式。
db.users.find({ hobby: ['eating','sleeping','hit doudou']})
同样其为整个Array的匹配。只有全部匹配的Array才能筛选出。
二是匹配Array中的某个元素
针对Array中的某个元素的匹配,可以使用犹如普通的筛选语句。
db.users.find({ hobby: 'hit doudou'})
除此之外,array还有一种常见方式
三对Array某个位置的元素进行匹配
如对array的index的value为’eating’的进行匹配。
db.users.find({ "hobby.0": 'eating'})
Array除此上面三种方式,还有更为复杂条件匹配。此处按下不表。
update
这个就厉害了。
db.collection.update()
db.collection.updateOne()
db.collection.updateMany()
db.collection.replaceOne()
其中upate(<query>,<update>,<upsert>,<multi>,<writeConcern>)
方法用来更新或者替代
匹配的文档。其中前两个参数为必填参数。
query为匹配的条件filter,update为更新的内容,upsert
这个参数厉害了,当通过query查找没有匹配的document的且upsert参数为true,这个时候,将会在collection中去insert一条document。而multi指定是否同时更新多个document。
前面说到update()用来更新或者替换,那么问题来了,什么时候是对document的更新,什么是替换整个document。
当upate的document中有update操作符如$set,$unset才为更新操作,否则用该document替换匹配的document
细思极恐啊。万一这要是弄混淆了。。。不知道mongodb怎么会这么设计。我想这也是为何在后续版本中,将update()方法拆分几个方法的原因。
delete操作
删除操作有如下几个语句
db.collection.remove()
db.collection.deleteOne()
db.collection.deleteMany()
用法类似,语法如:revmove(<query>,<justone>,<writeConcern>)
。其中query为匹配的条件,其和查询中的条件格式一
样。默认情况下,remove对所有匹配的记录进行删除,但是通过将参数justone
设置为true,则只删除匹配记录中的一条记录。那么问题来了,如果匹配多
个记录该删除那条呢?此时官方文档狡猾的推荐使用db.collection.findAndDelete()
。可以对查询的结果按照条件排序,然后再删除第一条记录。
##总结
mongodb在版本迭代的过程中,一个操作有多个方式实现。个人觉着还是使用更为精细的控制,比如插入用insertOne或者insertMany。避免造成不必要的误操作。