MongoDB详解
一、简介
MongoDB是一款强大、灵活、且易于扩展的通用型数据库
1、易用性
1)MongoDB是一款面向文档的数据库,而不是关系型数据库,因此而有着更好的扩展性。
2)通过在文档中嵌入文档和数组,面向文档的方法能够仅使用一条记录来表现复杂的层级关系。
3)MongoDB没有预定义模式(predefined schema):文档的键和值不再有固定的类型和大小;这样没有固定的模式,添加或删除字段就变得容易了。
4)使用MongoDB开发时能够进行快速迭代,所以开发进程得以加快。
2、易扩展性
PS:当数据量不断增长,增长到存储极限时,就需要扩展数据库了;数据库的扩展分为纵向扩展和横向扩展:纵向扩展就是使用性能更好的机器,
横向扩展就是使用更多的机器。
1)MongoDB的设计采用横向扩展,它能很容易的在多台服务器之间进行数据分割
2)MongoDB能够自动处理跨集群的数据和负载,自动重新分配文档,并将用户的请求路由到正确的机器上。
3、丰富的功能
1)索引
- 支持通用二级索引,允许多种快速查询,且提供唯一索引、复合索引、地理空间索引、全文索引
2)存储JavaScript
- 开发人员可以直接在服务端存取JavaScript的函数和值
3)聚合
- 支持聚合管道,用户能通过简单的片段创建复杂的集合,并通过数据库自动优化
4)特殊的集合类型
- 支持存在时间有限的集合,适用于那些将在某个时刻过期的数据,如会话session。类似地,MongoDB也支持固定大小的集合,用于保存近期数据,如日志。
5)文件存储
- 支持一种非常易用的协议,用于存储大文件和文件元数据。MongoDB并不具备一些在关系型数据库中很普遍的功能,如链接join和复杂的多行事务。省略
这些的功能是处于架构上的考虑,或者说为了得到更好的扩展性,因为在分布式系统中这两个功能难以高效地实现。
4、卓越的性能
1)MongoDB把尽可能多的内存用作缓存cache,视图为每次查询自动选择正确的索引。
2)只要有可能,数据库服务器就会将处理逻辑交给客户端。这种精简方式的设计是MongoDB能够实现如此高性能的原因之一。
二、MongoDB基础知识
1、文档是MongoDB的核心概念。文档就是键值对的一个有序集{'msg':'hello','foo':3}。类似于python中的有序字典。
需要注意的是:
#1、文档中的键/值对是有序的。
#2、文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)。
#3、MongoDB区分类型和大小写。
#4、MongoDB的文档不能有重复的键。
#5、文档中的值可以是多种不同的数据类型,也可以是一个完整的内嵌文档。文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。 文档键命名规范:
#1、键不能含有\0 (空字符)。这个字符用来表示键的结尾。
#2、.和$有特别的意义,只有在特定环境下才能使用。
#3、以下划线"_"开头的键是保留的(不是严格要求的)。
2、集合就是一组文档。如果将MongoDB中的一个文档比喻为关系型数据的一行,那么一个集合就是相当于一张表
1)集合存在于数据库中,为了管理方便,我们应该将不同格式和类型的数据插到不同的集合,但集合并没有固定的结构,
也就意味着我们完全可以把不同格式和类型的数据插入到同一个集合中。
2)使用“.”组织子集合
比如一个具有博客功能的应用可能包含两个集合,分别是blog.posts和blog.authors,这是为了使组织结构更清晰,
这里的blog集合(这个集合甚至不需要存在)跟它的两个子集合没有任何关系;在MongoDB中,使用子集合来组织数据非常高效,值得推荐。
3)当第一个文档插入时,集合就会被创建。合法的集合名:
- 集合名不能是空字符串""。
- 集合名不能含有\0字符(空字符),这个字符表示集合名的结尾。
- 集合名不能以"system."开头,这是为系统集合保留的前缀。
- 用户创建的集合名字不能含有保留字符。
3、数据库:在MongoDB中,多个文档组成集合,多个集合可以组成数据库
数据库也通过名字来标识。数据库名可以是满足以下条件的任意UTF-8字符串:
#1、不能是空字符串("")。
#2、不得含有' '(空格)、.、$、/、\和\0 (空字符)。
#3、应全部小写。
#4、最多64字节。 有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库。
#1、admin: 从身份认证的角度讲,这是“root”数据库,如果将一个用户添加到admin数据库,这个用户将自动获得所有数据库的权限。
再者,一些特定的服务器端命令也只能从admin数据库运行,如列出所有数据库或关闭服务器
#2、local: 这个数据库永远都不可以复制,且一台服务器上的所有本地集合都可以存储在这个数据库中
#3、config: MongoDB用于分片设置时,分片信息会存储在config数据库中
4、强调:把数据库名添加到集合名前,得到集合的完全限定名,即命名空间
- 例如:
如果要使用cms数据库中的blog.posts集合,这个集合的命名空间就是
cmd.blog.posts。命名空间的长度不得超过121个字节,且在实际使用中应该小于100个字节
三、基本数据类型
1、在概念上,MongoDB的文档与Javascript的对象相近,因而可以认为它类似于JSON。JSON(http://www.json.org)是一种简单的数据表示方式:
其规范仅用一段文字就能描述清楚(其官网证明了这点),且仅包含六种数据类型。
2、这样有很多好处:易于理解、易于解析、易于记忆。然而因为只有null、布尔、数字、字符串、数字和对象这几种数据类型,
所以JSON的表达能力有一定的局限。
3、虽然JSON具备的这些类型已经具有很强的表现力,但绝大数应用(尤其是在与数据库打交道时)都还需要其他一些重要的类型。
例如,JSON没有日期类型,这使得原本容易的日期处理变得麻烦。另外,JSON只有一种数字类型,无法区分浮点数和整数,更别说区分32位和64位了。
再者JSON无法表示其他一些通用类型,如正则表达式或函数。
4、MongoDB在保留了JSON基本键/值对特性的基础上,添加了其他一些数据类型。在不同的编程语言下,这些类型的确切表示有些许差异。
下面说明了MongoDB支持的其他通用类型,以及如何在文档中使用它们:
#1、null:用于表示空或不存在的字段
d={'x':null}
#2、布尔型:true和false
d={'x':true,'y':false}
#3、数值
d={'x':3,'y':3.1415926}
#4、字符串
d={'x':'egon'}
#5、日期
d={'x':new Date()}
d.x.getHours()
#6、正则表达式
d={'pattern':/^egon.*?nb$/i} 正则写在//内,后面的i代表:
i 忽略大小写
m 多行匹配模式
x 忽略非转义的空白字符
s 单行匹配模式 #7、数组
d={'x':[1,'a','v']} #8、内嵌文档
user={'name':'egon','addr':{'country':'China','city':'YT'}}
user.addr.country #9、对象id:是一个12字节的ID,是文档的唯一标识,不可变
d={'x':ObjectId()}
5、_id和ObjectId
五、CRUD操作
1、数据库操作
#1、增
use config #如果数据库不存在,则创建数据库,否则切换到指定数据库。 #2、查
show dbs #查看所有
要想显示出刚创建的数据库,我们需要向数据库插入一些数据。
db.table1.insert({'a':1}) #3、删
use config #先切换到要删的库下
db.dropDatabase() #删除当前库
2、集合操作
#1、增
当第一个文档插入时,集合就会被创建
> use database1
switched to db database1
> db.table1.insert({'a':1})
WriteResult({ "nInserted" : 1 })
> db.table2.insert({'b':2})
WriteResult({ "nInserted" : 1 }) #2、查
> show tables
table1
table2 #3、删
> db.table1.drop()
true
> show tables
table2
3、文档操作
增
#创建一个user的局部变量,这是一个JavaScript对象
user={
"name":"ming",
'is_nb':true,
'hobbies':['music','read','game']
} db.userinfo.insert(user)
db.userinfo.find() user1={
"name":"asb",
'is_sb':true,
'hobbies':['music','sports']
}
user2={
"name":"egon",
'is_sb':'wxx',
'hobbies':['music','read','dancing']
} user3={
"name":"alex",
'is_sb':false,
'hobbies':['music','read','girls']
}
db.userinfo.insertMany([user1,user2,user3]) #一次插入多个文档
改
复制代码
update() 方法用于更新已存在的文档。语法格式如下:
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)
参数说明:对比update db1.t1 set name='EGON',sex='Male' where name='egon' and age=18; query : 相当于where条件。
update : update的对象和一些更新的操作符(如$,$inc...等,相当于set后面的
upsert : 可选,默认为false,代表如果不存在update的记录不更新也不插入,设置为true代表插入。
multi : 可选,默认为false,代表只更新找到的第一条记录,设为true,代表更新找到的全部记录。
writeConcern :可选,抛出异常的级别。 更新操作是不可分割的:若两个更新同时发送,先到达服务器的先执行,然后执行另外一个,不会破坏文档。
update用法介绍
#1、最简单的更新就是用一个新的文档完全替换匹配的文档。这适用于大规模式迁移的情况。例如对下面的用户文档做
一个比较大的调整
> db.user.find().pretty()
{
"_id" : ObjectId("5a5b3a74c126b4b2cbb57e3f"),
"name" : "ming",
"girl_friends" : 20,
"height" : 170
} # 先找到要修改的对象
> var obj=db.user.findOne({'name':'ming'})
> obj
{
"_id" : ObjectId("5a5b3a74c126b4b2cbb57e3f"),
"name" : "ming",
"girl_friends" : 20,
"height" : 170
}
# 修改
> obj.detail={'girl_friends':20,'height':170}
{ "girl_friends" : 20, "height" : 170}
> obj.username=obj.name
egon # 删掉不要的
> delete obj.girl_friends
true
> delete obj.height
true
> delete obj.name
true # 完成更新
> db.user.update({'name':'ming'},obj)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.find()
{ "_id" : ObjectId("5a5b3a74c126b4b2cbb57e3f"), "detail" : { "girl_friends" : 20, "height" : 170}, "username" : "ming" }
简单更新
2、一个常见的错误
db.user.insert({'name':'ming','age':10})
db.user.insert({'name':'ming','age':20})
db.user.insert({'name':'ming','age':30})
> db.user.find()
{ "_id" : ObjectId("5a5b3ecac126b4b2cbb57e43"), "name" : "ming", "age" : 10 }
{ "_id" : ObjectId("5a5b3ecbc126b4b2cbb57e44"), "name" : "ming", "age" : 20 }
{ "_id" : ObjectId("5a5b3ecdc126b4b2cbb57e45"), "name" : "ming", "age" : 30 } # 找到的是第二个ming,他要过生日,于是长了一岁
> var obj=db.user.findOne({'name':'ming','age':20})
> obj.age++ # 我们的条件只定位到第二条记录这一条记录,所以更新是没问题的,
> db.user.update({'name':'ming','age':20},obj)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) # 我们的条件定位到了多条记录,而obj对象的_id是一定的,文档中的_id是唯一的,我们无法将三条改成同一个_id,所以报错
> db.user.update({'name':'ming'},obj) #报错 # 删掉后,更新成功,但默认改的是第一条
> delete obj._id
true
> obj
{ "name" : "ming", "age" : 21 }
> db.user.update({'name':'ming'},obj)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.find()
{ "_id" : ObjectId("5a5b40f6c126b4b2cbb57e46"), "name" : "ming", "age" : 21 }
{ "_id" : ObjectId("5a5b40f6c126b4b2cbb57e47"), "name" : "ming", "age" : 20 }
{ "_id" : ObjectId("5a5b40f6c126b4b2cbb57e48"), "name" : "ming", "age" : 30 }
> # 所以针对这种情况,我们还以_id作为条件保证只定位到我们想要修改的对象,并且比起随机字符串,_id的查找速度更快
> db.user.update({'_id':ObjectId("5a5b40f6c126b4b2cbb57e47")},obj) # ps: 改多条
> db.user.update({'name':'ming'},obj,{'multi':true})
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 9,
"errmsg" : "multi update only works with $ operators" #只能用修改器
}
})
> db.user.update({'name':'ming'},{$set:obj},{'multi':true})
WriteResult({ "nMatched" : 3, "nUpserted" : 0, "nModified" : 1 })
一个常见的错误
通常文档只会有一部分需要更新。可以使用原子性的更新修改器,指定对文档中的某些字段进行更新。
更新修改器是种特殊的键,用来指定复杂的更新操作,比如修改、增加后者删除 #=======>1、"$set"修改器
> db.user.find()
{ "_id" : ObjectId("5a5b51a257147a04b81f2bb4"), "name" : "egon", "age" : 10 }
{ "_id" : ObjectId("5a5b51a257147a04b81f2bb5"), "name" : "egon", "age" : 20 }
{ "_id" : ObjectId("5a5b51a357147a04b81f2bb6"), "name" : "egon", "age" : 30 }
#完全覆盖原文档
> db.user.update({'_id':ObjectId("5a5b51a257147a04b81f2bb4")},{'age':111})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.find()
{ "_id" : ObjectId("5a5b51a257147a04b81f2bb4"), "age" : 111 }
{ "_id" : ObjectId("5a5b51a257147a04b81f2bb5"), "name" : "egon", "age" : 20 }
{ "_id" : ObjectId("5a5b51a357147a04b81f2bb6"), "name" : "egon", "age" : 30 }
> #$set只更新原文档的一部分
> db.user.update({'_id':ObjectId("5a5b51a257147a04b81f2bb5")},{'$set':{'age':222}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.find()
{ "_id" : ObjectId("5a5b51a257147a04b81f2bb4"), "age" : 111 }
{ "_id" : ObjectId("5a5b51a257147a04b81f2bb5"), "name" : "egon", "age" : 222 }
{ "_id" : ObjectId("5a5b51a357147a04b81f2bb6"), "name" : "egon", "age" : 30 } # 有则更新,无则新增
> db.user.update({'age':30},{'$set':{'addr':{'country':'China','city':'BJ'}}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.user.find()
{ "_id" : ObjectId("5a5b51a257147a04b81f2bb4"), "age" : 111 }
{ "_id" : ObjectId("5a5b51a257147a04b81f2bb5"), "name" : "egon", "age" : 222 }
{ "_id" : ObjectId("5a5b51a357147a04b81f2bb6"), "name" : "egon", "age" : 30, "addr" : { "country" : "China", "city" : "BJ" } } # 修改内嵌文档
db.user.update({'age':30},{'$set':{'addr.country':'CHINA'}}) # $unset 删除该键值对
db.user.update({'age':30},{'$unset':{'addr':'什么值都行'}}) #=======>2、增加和减少
"$inc"修改器用来增加已经有的键的值(负数则为减少),或者该键不存在那就创建一个。只能用于整型、长整型或双浮点
的值。
对于更新分析数据、因果关系、投票或者其他有变化数值的地方,使用这个都会非法方便 例如:
> db.analytics.find()
{ "_id" : ObjectId("5a5b4cb2126d610970c553ab"), "url" : "http://www.baidu.com", "pv" : 2 }
> db.analytics.update({'url':'http://www.baidu.com'},{'$inc':{'pv':1}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.analytics.find()
{ "_id" : ObjectId("5a5b4cb2126d610970c553ab"), "url" : "http://www.baidu.com", "pv" : 3 }
使用修改器时,_id的值不能改变。其他的键值,包括其他的唯一索引的键,都是可以更改的。
注意:整个文档替换时可以改变_id #=======>3、往数组内添加元素
如果数组已经存在,"$push"会向已有的数组末尾加入一个元素,要是没有就创建一个新的数组。
例如提交博客的评论 db.blog.insert({'_id':1,'name':'alex意外死亡的真相'}) db.blog.update({'_id':1},{'$push':{'comments':{"name":"egon","content":'alex是谁???'}}})
db.blog.update({'_id':1},{'$push':{'comments':{"name":"wxx","content":'我去,真的假的'}}})
db.blog.update({'_id':1},{'$push':{'comments':{"name":"yxx","content":'吃喝嫖赌抽,欠下两个亿'}}}) > db.blog.find().pretty()
{
"_id" : 1,
"name" : "alex意外死亡的真相",
"comments" : [
{
"name" : "egon",
"content" : "alex是谁???"
},
{
"name" : "wxx",
"content" : "我去,真的假的"
},
{
"name" : "yxx",
"content" : "吃喝嫖赌抽,欠下两个亿"
}
]
} # 一次加多个"$push"
db.blog.update({'_id':1},{'$push':{'comments':{'$each':[{'name':'oldboy','content':'鼓掌'},{'name':'oldgirl','content':'一鞠躬'}]}}}) > db.blog.find().pretty()
{
"_id" : 1,
"name" : "alex意外死亡的真相",
"comments" : [
{
"name" : "egon",
"content" : "alex是谁???"
},
{
"name" : "wxx",
"content" : "我去,真的假的"
},
{
"name" : "yxx",
"content" : "吃喝嫖赌抽,欠下两个亿"
},
{
"name" : "oldboy",
"content" : "鼓掌"
},
{
"name" : "oldgirl",
"content" : "一鞠躬"
}
]
} # 限制大小"$slice",只留最后n个
db.blog.update({'_id':1},{'$push':{'comments':{'$each':[
{'name':'xxx','content':'二鞠躬'},
{'name':'yyy','content':'三鞠躬'},
{'name':'yyy','content':'四鞠躬'},
{'name':'zzz','content':'五鞠躬'},
{'name':'mmm','content':'六鞠躬'},
{'name':'nnn','content':'七鞠躬'},
],
'$slice':-7
}}}) > db.blog.find().pretty()
{
"_id" : 1,
"name" : "alex意外死亡的真相",
"comments" : [
{
"name" : "oldgirl",
"content" : "一鞠躬"
},
{
"name" : "xxx",
"content" : "二鞠躬"
},
{
"name" : "yyy",
"content" : "三鞠躬"
},
{
"name" : "yyy",
"content" : "四鞠躬"
},
{
"name" : "zzz",
"content" : "五鞠躬"
},
{
"name" : "mmm",
"content" : "六鞠躬"
},
{
"name" : "nnn",
"content" : "七鞠躬"
}
]
} #=======>4、The $sort element value must be either 1 or -1"
# '$sort':{'name': 1}升序排
db.blog.update({'_id':1},{'$push':{'comments':{'$each':[
{'name':'aaa','content':'礼毕'},
],
'$slice':-3,
'$sort':{'name': 1}
}}}) > db.blog.find().pretty()
{
"_id" : 1,
"name" : "alex意外死亡的真相",
"comments" : [
{
"name" : "yyy",
"content" : "三鞠躬"
},
{
"name" : "yyy",
"content" : "四鞠躬"
},
{
"name" : "zzz",
"content" : "五鞠躬"
}
]
} # '$sort':{'name': -1} 降序排
db.blog.update({'_id':1},{'$push':{'comments':{'$each':[
{'name':'aaa','content':'礼毕'},
],
'$slice':-2,
'$sort':{'name': -1}
}}}) > db.blog.find().pretty()
{
"_id" : 1,
"name" : "alex意外死亡的真相",
"comments" : [
{
"name" : "yyy",
"content" : "四鞠躬"
},
{
"name" : "aaa",
"content" : "礼毕"
}
]
} #注意:不能只将"$slice"或者"$sort"与"$push"配合使用,且必须使用"$each" #=======>5、避免添加重复 "$addToSet"
> db.urls.insert({'_id':1,'urls':[]})
WriteResult({ "nInserted" : 1 })
> db.urls.find()
{ "_id" : 1, "urls" : [ ] } db.urls.update({'_id':1},{'$addToSet':{'urls':'http://www.baidu.com'}})
db.urls.update({'_id':1},{'$addToSet':{'urls':'http://www.baidu.com'}})
db.urls.update({'_id':1},{'$addToSet':{'urls':'http://www.baidu.com'}})
db.urls.update({'_id':1},{'$addToSet':{'urls':'http://www.python.org'}})
> db.urls.find()
{ "_id" : 1, "urls" : [ "http://www.baidu.com", "http://www.python.org" ] } db.urls.update({'_id':1},{
'$addToSet':{
'urls':{
'$each':['http://www.baidu.com','http://www.baidu.com','http://www.xxx.com']
}
}
})
> db.urls.find()
{ "_id" : 1, "urls" : [ "http://www.baidu.com", "http://www.python.org", "http://www.xxx.com" ] } #=======>6、删除元素
如果把数组看成是队列或者栈,可以用"$pop",这个修改器可以从数组任何一端删除元素。
{"$pop":{"key":1}} 从数组末尾删除一个元素
{"$pop":{"key":-1}} 从头部删除 > db.queue.insert({'_id':1,'queue':[]})
WriteResult({ "nInserted" : 1 })
# 入队列
db.queue.update({'_id':1},{'$push':{'queue':'alex'}})
db.queue.update({'_id':1},{'$push':{'queue':'egon'}})
db.queue.update({'_id':1},{'$push':{'queue':'wxx'}})
db.queue.update({'_id':1},{'$push':{'queue':'yxx'}}) > db.queue.find()
{ "_id" : 1, "queue" : [ "alex", "egon", "wxx", "yxx" ] } # 出队列
db.queue.update({'_id':1},{"$pop":{"queue":-1}})
db.queue.update({'_id':1},{"$pop":{"queue":-1}})
db.queue.update({'_id':1},{"$pop":{"queue":-1}}) # "$pull" 把符合条件的统统删掉,而$pop只能按照位置删除
db.queue.update({'_id':1},{"$pull":{"queue":'yxx'}}) #=======>7、基于位置的数组修改器
db.blog.insert({'_id':1,'name':'alex意外死亡的真相'}) db.blog.update({'_id':1},{'$push':{'comments':{"name":"egon","content":'alex是谁???','thumb':20}}})
db.blog.update({'_id':1},{'$push':{'comments':{"name":"wxx","content":'我去,真的假的','thumb':30}}})
db.blog.update({'_id':1},{'$push':{'comments':{"name":"yxx","content":'吃喝嫖赌抽,欠下两个亿','thumb':40}}}) > db.blog.find().pretty()
{
"_id" : 1,
"name" : "alex意外死亡的真相",
"comments" : [
{
"name" : "egon",
"content" : "alex是谁???",
"thumb" : 20
},
{
"name" : "wxx",
"content" : "我去,真的假的",
"thumb" : 30
},
{
"name" : "yxx",
"content" : "吃喝嫖赌抽,欠下两个亿",
"thumb" : 40
}
]
} 根据下标修改
db.blog.update({'_id':1},{'$set':{'comments.0.thumb':200}}) 必须查询才知道下表,所以提供了$,$ 代表根据条件匹配出的元素
db.blog.update({'comments.name':'wxx'},{'$set':{'comments.$.thumb':300}}) #=======>8、upsert与multi
db.col.update( { "count" : { $gt : 5 } } , { $set : { "test5" : "OK"} },true,true ) #全部添加加进去
修改器
查
# 查找一条
db.userinfo.findOne()
# 查找所有
db.userinfo.find()
db.userinfo.find().pretty() #格式化显示 # 多个and条件
db.user.find({'name':'egon','age':{'$gt':20}}) # 也可不写条件,代表匹配所有
db.user.find({}) # 规定显示结果中有哪些key没有哪些key
> db.user.find({},{'_id':0,'name':1,'age':1})
{ "name" : "egon", "age" : 10 }
{ "name" : "egon", "age" : 20 }
{ "name" : "egon", "age" : 30 } # "$lt" "lte" "$gt" "gte" "$ne",其中"$ne"能用于所有数据类型
db.user.find({'age':{'$gte':10,'$lt':30}}) # or查询,or的条件放到[]内,注意:一个{}内逗号分开的多个条件相当于and
db.user.find({'$or':[{'name':'egon'},{'age':{'$gte':30}}]}) # in和nin
db.user.find({'age':{'$in':[10,11,12,20]}})
db.user.find({'age':{'$nin':[10,11,12,20]}}) # {'$mod':[2,1]},对2取余如果为1则匹配成功
db.user.insert({'_id':1,'name':'egon','age':10})
db.user.insert({'_id':2,'name':'egon','age':20})
db.user.insert({'_id':3,'name':'egon','age':30}) > db.user.find()
{ "_id" : 1, "name" : "egon", "age" : 10 }
{ "_id" : 2, "name" : "egon", "age" : 20 }
{ "_id" : 3, "name" : "egon", "age" : 30 } > db.user.find({'_id':{'$mod':[2,1]}})
{ "_id" : 1, "name" : "egon", "age" : 10 }
{ "_id" : 3, "name" : "egon", "age" : 30 } # not 取反
> db.user.find({'_id':{'$not':{'$mod':[2,1]}}})
{ "_id" : 2, "name" : "egon", "age" : 20 } # {'key':null} 匹配key的值为null或者没有这个key # 正则表达式
> db.user.find({'name':/^e.*?n$/i})
{ "_id" : 1, "name" : "egon", "age" : 10 }
{ "_id" : 2, "name" : "egon", "age" : 20 }
{ "_id" : 3, "name" : "egon", "age" : 30 } # 查询数组
> db.food.insert({'fruit':['apple','banana','peach']})
WriteResult({ "nInserted" : 1 })
> db.food.find({'fruit':'banana'}) #只要存在就可以
{ "_id" : ObjectId("5a5b7ad057147a04b81f2bc3"), "fruit" : [ "apple", "banana", "peach" ] } > db.food.find({'fruit':{'$all':['banana','apple']}}) #既有banana又有apple > db.food.find({'fruit.1':'banana'}) #按照位置 > db.blog.find().pretty()
{
"_id" : 1,
"name" : "alex意外死亡的真相",
"comments" : [
{
"name" : "egon",
"content" : "alex是谁???",
"thumb" : 200
},
{
"name" : "wxx",
"content" : "我去,真的假的",
"thumb" : 300
},
{
"name" : "yxx",
"content" : "吃喝嫖赌抽,欠下两个亿",
"thumb" : 40
},
{
"name" : "egon",
"content" : "xxx",
"thumb" : 0
}
]
}
db.blog.find({},{'comments':{"$slice":-2}}).pretty() #查询最后两个
db.blog.find({},{'comments':{"$slice":[1,2]}}).pretty() #查询1到2 # 数组和范围查询的相互作用
db.test.insert({'x':5})
db.test.insert({'x':15})
db.test.insert({'x':25})
db.test.insert({'x':[5,25]}) > db.test.find({'x':{'$gt':10,'$lt':20}})
{ "_id" : ObjectId("5a5b8310b9b1b7388a40f993"), "x" : 15 }
{ "_id" : ObjectId("5a5b8310b9b1b7388a40f995"), "x" : [ 5, 25 ] }
#发现连非数组的也找出来了,如果只想匹配数组,则用$elemMatch
> db.test.find({'x':{"$elemMatch":{'$gt':10,'$lt':20}}}) #匹配不到内容
> db.test.find({'x':{"$elemMatch":{'$gt':5,'$lt':115}}}) #25属于该范围
{ "_id" : ObjectId("5a5b8310b9b1b7388a40f995"), "x" : [ 5, 25 ] } #如果只想匹配非数组需要建立索引,结合min与max使用
删
db.userinfo.deleteOne({ 'is_sb': true }) #删除多个中的第一个
db.userinfo.find()
db.userinfo.deleteMany( { 'x'': 1 } ) # 删除x=1的全部
db.userinfo.deleteMany({}) #删除全部
MongoDB详解的更多相关文章
- centos7安装mongodb详解
记录一下linux下安装mongodb数据库过程. 安装mongodb #下载linux版本的tar文件# 例如笔者下载的是:mongodb-linux-x86_64-rhel70-3.4.4.tg ...
- CentOS 安装 Mongodb详解 --- 无Linux基础
先去官方下载离线安装包:https://www.mongodb.com/ ftp连接一下服务器,把离线包上传上去 XShell连接一下: 解压文件(你输一点就可以按tab键,它会自动补全):tar - ...
- mongodb 详解 error:10061 由于目标计算机积极拒绝,无法连接解决方法
mongodb下载地址(32位):下载地址 自己选择版本 建立如下与mongodb并行的两个文件夹data和log. 然后建立mongo.config. 在mongo.config配置文件中输入: # ...
- MongoDB详解学习历程
MongoDB是一个基于分布式文件存储的数据库,它是介于关系数据库和非关系数据库之间的产品. MongoDB支持的数据结构非常松散,类似json的bjson格式,因此可以存储比较复杂的数据类型.Mon ...
- CentOS 安装 Mongodb详解 --- 有Linux基础
安装包:https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-3.4.1.tgz 安装过程 安装pstree小工具,以及其使用 关闭 ...
- MongoDB各种查询操作详解
这篇文章主要介绍了MongoDB各种查询操作详解,包括比较查询.关联查询.数组查询等,需要的朋友可以参考下 一.find操作 MongoDB中使用find来进行查询,通过指定find的第一个参数可 ...
- MongoDB执行计划分析详解
要保证数据库处于高效.稳定的状态,除了良好的硬件基础.高效高可用的数据库架构.贴合业务的数据模型之外,高效的查询语句也是不可少的.那么,如何查看并判断我们的执行计划呢?我们今天就来谈论下MongoDB ...
- 详解 Node + Redux + MongoDB 实现 Todolist
前言 为什么要使用 Redux? 组件化的开发思想解放了繁琐低效的 DOM 操作,以 React 来说,一切皆为状态,通过状态可以控制视图的变化,然后随着应用项目的规模的不断扩大和应用功能的不断丰富, ...
- MongoDB数据库详解
第1章 数据库管理系统 1.1 前言 01.数据的定义:文字.图像.地理位置信息(坐标.经纬度)等 02.数据库管理系统的定义:建立.存取和管理数据,保证数据安全和完整性的软件 03.常见的数据库管理 ...
随机推荐
- DRF教程7-token认证
Authentication 认证是将一个传入的请求和一组标识凭据相关联的机制,比如请求过来的用户,或者用户登录时携带的token. 然后权限策略就能使用这些凭据来决定是否允许这个请求. REST框架 ...
- idea配置maven和gradle,阿里云镜像私服
安装Gradle 从官方网站下载安装包,解压到目录 设置环境变量 PATH=D:\gradle\gradle-3.4.1\bin GRADLE_HOME=D:\gradle\gradle-3.4.1 ...
- 弃用serv-u,改用 Xlight FTP
Serv-u 强大,设置也较麻烦一点,针对serv-u的攻击也很丰富.试用期只有一个月,破解版的用着也不放心 Xlight FTP 设置简单,个人版免费使用,感觉良好!
- python 批量下载 spring 的 xsd
#coding=utf-8 import os import urllib import urllib2 import re from bs4 import BeautifulSoup # 利用 ur ...
- Dev Express Report 学习总结(一) 基础知识总结
Dev Express,一个非常优秀的报表控件.像其他报表一样,该报表也包括几个主要部分:Report Header,Page Header,Group Header,Detail,Group Foo ...
- java字符串转Date
public static Date StrToDate(String str) { SimpleDateFormat format = new SimpleDateFormat("yyyy ...
- Android NDK开发 Jni中打日志LOG(二)
HelloJni.c文件中,加入头文件和函数声明.最终文件如下: #include <jni.h> #include <string.h> #include<androi ...
- Python函数调用
1.同级目录下的调用 - src |- mod1.py |- test1.py 若在程序test1.py中导入模块mod1.py,则直接使用 import mod1 或 from mod1 impor ...
- 2019.03.21 读书笔记 基元类型的Parse与TryParse 性能与建议
Parse转换失败时会抛出异常,耗损性能,如果转换成功,则与TryParse无差异.查看源码,tryparse的代码更多一些,在失败时,反而性能更优,主要是抛出异常耗损了性能.所以在不确定是用Tryp ...
- 局部安装webpack时,使用webpack命令时提示webpack不是内部命令解决方法
现在js发展太快了,根本看不懂啊.于是乎想做做功课,于是乎看到了这些“奇怪”的写法,原来好多都是遵循了 ECMASCRIPT6,好吧,在本地看看怎么用的吧.写在本地的环境下, 发现各种报错,根本不能用 ...