只要是数据库那么就绝对离不开最为核心的功能: CRUD, 所以在MongoDB里面对于数据的操作也是支持的, 但是除了增加之外, 其他操作都是很麻烦的。
4.1 数据增加
- 使用 db.collection.insert() 可以实现数据的增加操作
增加一个简单数据
db.insert({"url": "www.mldn.cn"})
如果要想保存多个数据就使用数组
范例: 保存数组
db.infos.insert([
{'url': 'www.mldn.cn'},
{'url': 'www.mldnjavascript.cn'}
])
- 如果保存多条以上数据就
范例: 保存10000个数据
for ( var i = 0 ; i < 10000 ; i++ ) {
db.infos.insert( { "url": "mldn - " + i } )
}
如果数据保存很多的情况下, 列表不会全部列出, 它只会列出部分的内容
4.2 数据查询
任何的数据库之中, 数据的查询操作都是最为麻烦的, 而在MongoDB数据库里面, 对于查询的支持非常到位, 包含有关系运算、逻辑运算、数组运算、正则运算等
首先对于数据的查询操作核心的语法: db.collection.find({查询条件}, {设置显示的字段})
范例: 最简单的用法就是直接使用find()函数完成查询
db.infos.find()
范例:希望查询出url为"www.mldn.cn"的数据
db.infos.find({"url": "www.mldn.cn"})
发现在进行数据查询的时候也是按照JSON的形式设置的相等关系.它的整个开发之中不可能离开JSON数据
对于设置的显示字段严格来讲究就称为数据的投影操作, 如果不需要显示的字段设置"0", 而需要显示的字段设置"1"
范例: 不想显示"_id"
db.infos.find({"url": "www.mldn.cn"}, {"_id": 0})
db.infos.find({"url":"www.mldn.cn"}, {"_id":0, "url": 1})
大部分情况下, 这种投影的意义不大. 同时对于数据的查询也可以使用"pretty()"函数
范例: 漂亮显示
db.infos.find({"url":"www.mldn.cn", {"_id":0,"url":1}).pretty()
数据列多的时候一定可以看出华丽的显示效果
范例: 查询单个数据
db.infos.findOne({"url":"www.mldn.cn"}).pretty()
利用以上的查询可以实现数据格式化输出效果, 前提: 列的内容必须多。
4.2.1 关系运算
在MongoDB里面支持的关系查询操作: 大于($gt)、小于($lt)、 大于等于($gte)、小于等于($lte)、不等于($ne)、等于($eq)
范例: 定义一个学生信息集合
db.students.insert({name: '张三', sex: '男', age: 19, score: 59, address: '海淀区'})
db.students.insert({name: '李四', sex: '女', age: 20, score: 99, address: '朝阳区'})
db.students.insert({name: '王五', sex: '女', age: 19, score: 100, address: '西城区'})
db.students.insert({name: '赵六', sex: '男', age: 30, score: 20, address: '东城区'})
db.students.insert({name: '孙七', sex: '男', age: 19, score: 0, address: '海淀区'})
db.students.insert({name: '王八', sex: '女', age: 25, score: 70, address: '朝阳区'})
db.students.insert({name: '刘九', sex: '男', age: 17, score: 56, address: '海淀区'})
db.students.insert({name: '钱十', sex: '女', age: 19, score: 89, address: '西城区'})
范例: 查询姓名是张三的学生信息
db.students.find({"name": "张三"}).pretty()
范例: 查询性别是男的学生信息
db.students.find({"sex": "男"}).pretty()
范例: 查询年龄大于19的学生
db.students.find("age": {"$gt": 19}).pretty()
范例: 查询成绩大于等于60分的学生
db.students.find({score:{"$gte": 60}}).pretty()
范例: 查询姓名不是王五的信息
db.students.find("name": {"$ne": "王五"}).pretty()
此时与之前最大的区别就在于, 在一个JSON结构里面需要定义其他的JSON结构, 并且这种风格在日后通过程序进行操作的时候依然如此.
4.2.2.逻辑运算
逻辑运算主要就是三种类型: 与($and) 、或($or)、非($nor、$not)
范例: 查询年龄在 19~20岁的学生信息
db.students.find({age:[ {"$gte": 19},{"$lte": 20}]}).pretty()
在进行逻辑运算”$and"的连接最容易, 因为只需要利用","分割若干个条件就可以了。
范例: 查询年龄不是19岁的学生
db.students.find({"age": {"$ne": 19}}).pretty()
范例: 查询年龄大于19岁, 或者成绩大于90分的学生信息
db.students.find({"$or": [
{
"age": {"$gt": 19}
},
{
"score": {"$gt": 90}
}
]}).pretty()
范例: 也可以进行或的求反操作
db.students.find({"$nor": [
{
"age": {"$gt": 19}
},
{
"score": {"$gt": 90}
}
]}).pretty()
针对于或的求反操作可以实现一个求反的操作
在这几个逻辑运算之中, 与的连接最简单, 而或的连接需要为数据设置数组的过滤条件
4.2.3.求模
模的运算使用 "$mod"来完成, 语法"{"$mod": [数字, 余数]}"
范例: 求模
db.students.find({"age": {"$mod": [20, 1]}}).pretty()
4.2.4范围查询
只要是数据库, 必须存在有"$in"(在范围之中)、"$nin"( 不再范围之中 )
范例: 查询姓名是"张三", "李四", "王五"的信息
db.students.find({"name": {"$in": ["张三", "李四", "王五"]}).pretty()
范例: 不在范例
db.students.find({"name": {"$nin": ["张三", "李四", "王五"]}).pretty()
4.2.5数组查询
首先在MongoBD里面是支持数组保存的, 一旦支持了数组保存, 就需要针对于数组的数据进行匹配.
范例:保存一部分数组内容
db.students.insert([
{
name: '谷大神_A',
sex: '男',
age: 19,
score: 89,
address: '海淀区',
course: ['语文', '数学', '英语', '音乐', '政治']
}])
db.students.insert([
{
name: '谷大神_B',
sex: '男',
age: 19,
score: 89,
address: '海淀区',
course: ['语文', '数学']
}])
db.students.insert([
{
name: '谷大神_A',
sex: '男',
age: 19,
score: 89,
address: '海淀区',
course: ['语文', '数学', '英语']
}])
db.students.insert([
{
name: '谷大神_A',
sex: '男',
age: 19,
score: 89,
address: '海淀区',
course: [ '英语', '音乐', '政治']
}])
db.students.insert([
{
name: '谷大神_A',
sex: '男',
age: 19,
score: 89,
address: '海淀区',
course: [ '语文', '政治']
}])
此时的数据包含有数据内容, 而后需要针对于数据数据进行判断, 可以使用几个运算符: $all、$slice、$size、$elemMatch
范例: 查询同时参加语问和数学课程的学生
现在两个数组内容都需要保存, 所以使用{$all: [内容一, 内容二, ...]}
db.students.find({"course": {"$all": ["语文","数学"]}}).pretty()
现在所有显示的学生信息里面包含语文和数学的内容, 而如果差一个内容就不会显示。
虽然"$all" 计算可以用于数组上, 但是也可以用于一个数据的匹配上。
范例: 查询学生地址是"海淀区"的信息
db.students.find({"address": {"$all": ["海淀区"]}).pretty()
既然在集合里面现在保存的是数组信息,那么数组就可以利用索引操作,使用"key.index"的方法来定义索引
范例: 查询数组中第二个内容(index = 1, 索引下标从0开始)为数学的信息
db.students.find({"course.1":"数学"}).pretty()
范例: 要求查询出只参加2门课程的学生
使用$size来进行数量的控制
db.students.find("course: {"$size": 2}).pretty()
发现在进行数据查询的时候只要内容符合条件, 数字的内容就全部显示出来了, 但是现在希望可以控制数组的返回的数量, 那么可以使用"$slice"进行控制。
范例: 返回年龄为19岁所有学生的信息, 但是要求只显示两门参加课程.
db.students.find("age": 19, {"course": {"$slice": 2}}).pretty()
现在只取出前两门的信息,那么也可以设置负数表示取出后两门的信息.
db.students.find({"age": 19}, {"course": {"$slice": -2}}).pretty()
或者只是取出中间部分的信息
db.students.find({"age": 19, {"course": {"$slice: [1, 2]}}}).pretty()
在此时设置的两个数据里面第一个数据表示跳过的数据量, 而第二个表示返回的数量
而$elemMatch操作符输出满足这样条件的文档, 即文档中filed数据中至少一个元素满足全部知道指定的匹配要求
db.students.insert({
resultes: [82, 85, 88, {product: 'xyz}]
})
db.students.find({"resultes": {"$elemMatch": {"$gt": 84,"$lt": 886}}).pretty()
此时85刚好满足 全部要求
还有一种单一条件查询
db.students.find({"resultes": {"$elemMatch": {product: 'xyz}}).pretty()
上面的例子中,因为 $elemMatch 操作符只指定一个查询条件,那么当只有一个查询条件时,使用 $elemMatch 操作符有点大材小用了,你可以将上面的查询替换成下面这样子:
db.students.find({"resultes.product":"xyz"}).pretty()
4.2.6.嵌套集合运算
在MongoDB数据里面每一个集合数据都可以继续保存其他的集合数据, 例如: 有些学生需要保存家长信息
范例: 增加数据
db.students.drop()
db.students.insert({name: '高大拿 - A',sex: '男', age: 19, score: 89, address: '海淀区',
course: ['语文', '数学', '英语', '音乐', '政治'],
parents: [
{name: '高大拿 -A (父亲)', age: 50, job: '工人'},
{name: '高大拿 -A (母亲)', age: 46, job: '职员'}]})
db.students.insert({name: '高大拿 - B',sex: '男', age: 19, score: 89, address: '海淀区',
course: ['语文', '数学'],
parents: [
{name: '高大拿 -B (父亲)', age: 50, job: '处长'},
{name: '高大拿 -B (母亲)', age: 46, job: '局长'}]})
db.students.insert({name: '高大拿 - C',sex: '男', age: 19, score: 89, address: '海淀区',
course: ['语文', '数学', '英语'],
parents: [
{name: '高大拿 -C (父亲)', age: 50, job: '工人'},
{name: '高大拿 -C (母亲)', age: 46, job: '局长'}]})
此时给出的内容是嵌套的集合,而这种集合的数据的判断只能过通过$elemMatch完成。
范例: 查询出父母是局长的信息
db.students.find({
"$and": [
{"$gte": 19},
{"parents": {
"$elemMatch": {job: '局长”}
}}
]
}).pretty()
由于这种查询的时候条件比较麻烦, 所以如果可能, 尽量别搞这么复杂的数据结构组成.
4.2.7. 判断某个字段是否存在
使用"$exists"可以判断某个字段是否存在, 如果设置为True表示存在, 如果设置为false就表示不存在.
范例: 查询具有parents的成员的数据
db.students.find({"parents": {"$exists": true}}).pretty()
范例: 查询不具有course成员的数据
db.students.find({"course": {$exists: false}}).pretty()
可以利用此类查询来进行一些不需要的数据过滤.
4.2.8 条件过滤
实际上习惯于传统关系型数据库开发的我们对于数据的筛选, 可以首先想到的一定是where子句, 所以在MongoDB里面也提供有'$where'.
范例: 使用where进行数据查询
db.students.find({"$where": "this.age > 20"}).pretty()
db.students.find("this.age > 20").pretty()
对于"$where"是可以简化的, 但是这类的操作是属于进行每一行的信息判断, 实际上对于数据量大的情况下并不方便使用. 实际上以上的代码严格来讲是属于编写一个操作的函数
db.students.find(function() {
return this.age > 20
}).pretty()
db.students.find({"$where": function() {
return this.age > 20
}}).pretty()
以上只是查询了一个判断, 如果要想实现多个条件的判断, 那么就需要使用and连接.
db.students.find({"$and": [
{"$where": "this.age > 19"},
{"$where": "this.age < 21"}
]}).pretty()
虽然这种形式的操作可以实现数据查询, 但是最大的缺点是将在MongoDB里面保存的BSON数据变成了Javascript的语法结构, 这样的方式不方便使用数据库索引机制.
4.2.9 正则运算
如果要想实现模糊查询, 那么必须使用正则表达式, 而且正则表达式使用的语言是Perl兼容的正则表达式的形式. 如果要想实现正则使用, 则按照以下的定义格式:
基础语法: {key: 正则标记}
. 完整语法: {key: {"$regex": 正则标记, "$options": 选项}}
|- 对于options主要是设置正则的信息查询的标记
|- 'i' : 忽略字母大小写
|- 'm': 多行查找
|- 'x': 空白字符串除了被转义的或在字符类中意外的完全被忽略
|- 's': 匹配所有的字符(圆点: '.'), 包括换行内容.
|-需要注意的是, 如果是直接使用(javascript )那么只能够使用i和m, 而'x'和’s'必须使用'$regex'
范例: 查询以 '谷'开头的姓名
db.students.find("name": /谷/).pretty()
范例: 查询姓名有字母A
db.students.find({"name": /a/i|).pretty()
db.students.find({"name': {"$regex": /a/i}}).pretty()
如果要执行模糊查询的操作, 严格来讲只需要编写一个关键字就够了
正则操作之中除了可以查询出单个字段的内容之外, 也可以进行数组数据的查询.
范例: 查询数组数据
db.students.find({"course":/语?/}).pretty()
db.students.find({"course":/语/}).pretty()
MongoDB中的正则符号和之前Java正则式有一些小小差别, 不建议使用以前的一些标记.正则就将其应用在模糊数据查询上.
4.2.10 数据排序
在 MongoDB里面数据的排序操作使用"sort"函数, 在进行排序的时候可以有两个顺序: 升序(1)、 降序(-1)
范例: 数据排序
db.students.find().sort({"score": -1}).pretty()
但是在进行排序的过程里面有一种方式称为自然排序, 按照数据保存的先后顺序排序, 使用"$natural"表示
范例: 自然排序
db.students.find().sort({"$natural": -1}).pretty()
在MongoDB数据库里面排序的操作相比较传统关系型数据库的设置要简单.
4.2.11 数据分页显示
在MongoDB里面的数据分页显示也是符合大数据要求的操作函数.
.skip(n) : 表示跨过多少数据行;
.limit(n):取出的数据行的个数限制
: 分页显示(第一页, skip(0)、limit(5))
db.students.find().skip(0).limit(5).sort({"age": -1}).pretty()
范例: 分页显示(第二页, skip()、limit(5))
db.students.find().skip(5).limit(5).sort({"age": -1}).pretty()
这两个分页的控制操作, 就是在以后只要是存在有大数据的信息情况下都会使用它.