1.0 基初知识
在关系数据库会产生一些例如表连接等操作,这样会大大降低系统的性能。而在当前很多应用场景下对性能的要求远远强于传统数据库关注的点,NoSQL(Not only SQL)就是为了解决大规模数据与多样数据种类等问题,尤其是其中大数据的相关问题。
1.0.1 NoSQL特点
- 1、数据模型比较简单;
- 2、对数据库性能要求较高;
- 3、不需要高度的数据一致性;
- 4、对于给定key,比较容易映射复杂值的环境
1.0.2 应用场景
- 1、对数据库高并发读写的需求
- 2、对海量数据的高效率存储和访问的需求
- 3、对数据库的高可扩展性和高可用性的需求
2.0 MongoDB基础认识
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。它的特点是高性能、易部署、易使用,存储数据非常方便。
2.0.1 数据库对比
MongoDB | MySQL |
---|---|
数据库 | 数据库 |
集合(Collection) | 表 |
文档(Document) | 行 |
3.0 基础使用
3.0.1 数据库操作
show dbs//查看数据库
show collections//查看数据库下有哪些collections
show <collection_name>//查看具体的collection内容
db.dropDatabase();//删除当前所在的数据库
3.0.2 集合(Collections)操作
数据库中不能直接插入数据,只能往集合(collections)中插入数据
db.集合名.insert({})//自动创建未创建过的集合
db.集合名.drop()//删掉集合
3.0.3 数据查找
db.集合名.insert({})//数据插入
db.集合名.find({})//查找当前集合所有数据
db.集合名.distinct("过滤字段")//过滤掉字段中的相同数据
db.集合名.find({"字段名":"具体值"})//筛选等于具体值的数据
db.集合名.find({"字段名":{$gt:具体值}})//筛选大于具体指的数据
db.集合名.find({"字段名":{$lt:具体值}})//筛选小于具体指的数据
db.集合名.find({"字段名":{$gte:具体值}})//筛选大于等于具体指的数据
db.集合名.find({"字段名":{$gt:具体值1,$lt}})//筛选大于具体指1的数据,小于具体值2的数据
db.集合名.find({"字段名",/关键字/})//模糊查找,查找包含关键字的数据
db.集合名.find({"字段名",/^xin$/})//查找name开头结尾是"xin"的数据
//**提取指定列**
db.集合.find({},{name:1,age:1})//0,1可以用true和false替代
//**复合查找**
db.集合.find({age:$lte:25},{name:1,age:1})
db.集合名.find({}).sort(字段名:顺序值)//-1表示降序,1表示升序
db.集合名.find({}).limit(数据长度)//查询前几条数据
db.集合名.find({}).skip(跳过的数据长度值)//查找第几条数据之后的所有数据
db.集合名.find({}).limit(数值1).skip(数值2)//查找数值1中的前数值2之后的数据//分页查找
db.集合名.find({$or:[{age:11},{age:22}]})//与查找
db.集合名.findOne({})//查询第一条数据
db.集合名.find({age:{$lte:25}}).count()//查找年龄大于25的数量
db.集合名.find({}).limit(25).count(true)//返回限制之后的数据量
提取指定列:除了 _id 你不能在一个对象中同时指定 0 和 1,如果你设置了一个字段为 0,则其他都为 1,反之亦然。
复合查找,查找age小于等于25的数据,并对这些数据提取出name,和age字段显示
3.0.4 数据更新
db.集合名.updateOne({数据项:数据值},{$set:{修改项:修改值}})//默认只修改第一个document
db.集合名.replaceOne({数据项:数据值},{$set:{修改项:修改值}})//替换单个数据
db.集合.updateMany({name:/g$/},{$set:{name:"long"}})//更新多个
db.集合名.update({数据项:数据值},{$set:{数据项:数据值}},{multi:true})//修改所有匹配项
//更新或替换与指定过滤器匹配的单个文档,或更新与指定过滤器匹配的所有文
db.集合名.update({数据项:数据值},{$set:{修改项:修改值}})档。
3.0.5 数据删除
db.集合名.deleteOne()
db.集合名.deleteMany()
3.0.5 数据插入
db.COLLECTION_NAME.insert(document)
4.0 数据类型(Bson Types)
A serialization format used to store documents and make remote procedure calls in MongoDB. “BSON” is a portmanteau of the words “binary” and “JSON”. Think of BSON as a binary representation of JSON (JavaScript Object Notation) documents. See BSON Types and MongoDB Extended JSON.
Type | Number | Alias | Notes |
---|---|---|---|
Double | 1 | “double” | |
String | 2 | “string” | |
Object | 3 | “object” | |
Array | 4 | “array” | |
Binary data | 5 | “binData” | |
ObjectId | 7 | “objectId” | |
Boolean | 8 | “bool” | |
Date | 9 | “date” | |
Null | 10 | “null” | |
Regular Expression | 11 | “regex” | |
JavaScript | 13 | “javascript” | |
JavaScript (with scope) | 15 | “javascriptWithScope” | |
32-bit integer | 16 | “int” | |
Timestamp | 17 | “timestamp” | |
64-bit integer | 18 | “long” | |
Decimal128 | 19 | “decimal” | New in version 3.4. |
Min key | -1 | “minKey” | |
Max key | 127 | “maxKey” |
可以使用$type操作符根据上表中列出的BSON数据类型从文档中查询数据。
eg: db.test.find({age:{$type:16}}) //16是表格中int值的代表
5.0 数据操作符
5.0.1 比较运算符
Name | Description | 操作 |
---|---|---|
$eq |
等于 | db.test.find({age:{$eq:25}}) |
$gt |
大于 | db.test.find({age:{$gt:25}}) |
$gte |
大于等于 | db.test.find({age:{$gte:25}}) |
$in |
匹配在数组中的任意值 | db.test.find({age:{$in:[25,26]}}) |
$lt |
小于 | db.test.find({age:{$lt:25}}) |
$lte |
小于等于 | db.test.find({age:{$lte:25}}) |
$ne |
不等于 | db.test.find({age:{$ne:25}}) |
$nin |
匹配不在数组中的值 | db.test.find({age:{$nin:[25,26]}}) |
5.0.2 元素匹配运算符
Name | Description | 操作 |
---|---|---|
`$exists | 查询所有指定字段存在的数据 | db.users.find({age: {$exists: true}}); |
$type |
匹配类型 | db.users.find({age:{$type:6}}) |
5.0.3 逻辑运算符
Name | Description | 操作 |
---|---|---|
$and |
与 | { $and: [ { <expression1> }, { <expression2> } , ... , { <expressionN> } ] } |
$not |
非 | { field: { $not: { <operator-expression> } } } |
$nor |
或非 | { $nor: [ { <expression1> }, { <expression2> }, ... { <expressionN> } ] } |
$or |
或 | { $or: [ { <expression1> }, { <expression2> }, ... , { <expressionN> } ] } |
db.inventory.find( {
$and: [ { price: { $ne: 1.99 } }, { price: { $exists: true } } ]
} )
//等价于
db.inventory.find( { price: { $ne: 1.99, $exists: true } } )
5.0.4 评估运算符
Name | Description | 操作 |
---|---|---|
$expr |
允许在查询语言中使用聚合表达式 | { $expr: { <expression> } } |
$jsonSchema |
匹配符合与给定的json纲要的文档 | { $jsonSchema: <schema> } |
$mod |
取模运算 | { field: { $mod: [ 被除数, 余数 ] } } |
$regex |
正则 | { <field>: { $regex: /pattern/<options> } } |
$text |
文本对带有文本索引的字段内容执行文本搜索 | {$text:{$search: <string>,$language: <string>,$caseSensitive: <boolean>,$diacriticSensitive: <boolean>}} |
$where |
匹配满足javascript表达式的文档 |
5.0.5 数组操作运算符
Name | Description | 操作 |
---|---|---|
$all |
匹配所有 | { <field>: { $all: [ <value1> , <value2> ... ] } } |
$elemMatch |
匹配内嵌文档或数组中的部分field | { <field>: { $elemMatch: { <query1>, <query2>, ... } } } |
$size |
匹配数组长度为指定大小的文档 | db.inventory.find( { tags: { $size: 1 } ) |
与$in 只需满足某一个值即可,而$all 必须满足数组]内的所有值
//获取document中arrs数组中数据值大于25小于50的数组元素
db.test.find({arrs:{$elelMatch:{$gte:25,$lte:50}}})
5.0.6 字段更新运算符
Name | Description | 操作 |
---|---|---|
$inc | 将文档中的某个field对应的value自增/减某个数字 | { $inc: { <field1>: <amount1>, <field2>: <amount2>, ... } } |
$currentDate | 设置指定字段为当前时间 | db.users.update( { _id: 1 }, {$currentDate: { lastModified: true, "cancellation.date": { $type: "timestamp" } }, } ) |
$min |
将文档中的某字段与指定值作比较,如果原值小于指定值,则不更新;若大于指定值,则更新 | { $min: { <field1>: <value1>, ... } } |
$max | 与$min功能相反 | { $max: { <field1>: <value1>, ... } } |
$mul | 将文档中的某个field对于的value做乘法操作 | { $mul: { <field1>: <number1>, ... } } |
$rename | 重命名文档中的指定字段的名 | {$rename: { <field1>: <newName1>, <field2>: <newName2>, ... } } |
$set | 更新文档中的某一个字段,而不是全部替换 | { $set: { <field1>: <value1>, ... } } |
$setOnInsert | 配合upsert操作,在作为insert时可以为新文档扩展更多的field | db.collection.update( <query>, { $setOnInsert: { <field1>: <value1>, ... } }, { upsert: true } ) |
$unset | 删除文档中的指定字段,若字段不存在则不操作 | { $unset: { <field1>: "", ... } } |
6.0 数据索引
索引是对数据库表中一列或多列的值进行排序的一种结构,可以让我们查询数据库变得更快。MongoDB的索引几乎与传统的关系型数据库一模一样,这其中也包括一些基本的查询优化技巧。
创建索引
db.collection.createIndex()
注意在 3.0.0 版本前创建索引方法为 db.collection.ensureIndex(),之后的版本使用了 db.collection.createIndex() 方法,ensureIndex() 还能用,但只是 createIndex() 的别名。
查看索引
db.collection.getIndexes()
移除索引
db.collection.dropIndex()
db.collection.dropIndexes()
修改索引,先删除再创建
6.0.0 单一索引
如果插入的文档中不包含uId键,那么该文档中该键的值为null
//插入重复的uId之后就会报错
db.test.createIndex({"uId":1},{"unique":true})
6.0.1 联合索引
通过使用索引,数据库会对数据库中索引中所表示的字段保持已排序状态,也就 是说,我们能够方便的针对该字段进行排序查询,MongoDB能够很快返回结果,但是这种帮助只能在查询字段在首位的情况下才能 生效,如果该字段不在查询的首位,就可能无法使用到该索引带来的好处了,如:
db.users.createIndex({"username":1})
db.users.find().sort({"age": 1, "username" : 1})//此处报错
error: {
"$err" : "too much data for sort() with no index. add an index or specify a smaller limit",
"code" : 10128
}
这样操作后,索引中第一个字段“age”按照升序排列进行排序,第二个字段 “username”也在第一个字段的范围内按照升序排列,eg:
联合索引.jpg
createIndex() 接收可选参数,可选参数列表如下:
Parameter | Type | Description |
---|---|---|
background | Boolean | 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 "background" 可选参数。 "background" 默认值为false。 |
unique | Boolean | 建立的索引是否唯一。指定为true创建唯一索引。默认值为false. |
name | string | 索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。 |
dropDups | Boolean | 3.0+版本已废弃。在建立唯一索引时是否删除重复记录,指定 true 创建唯一索引。默认值为 false. |
sparse | Boolean | 对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false. |
expireAfterSeconds | integer | 指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。 |
v | index version | 索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。 |
weights | document | 索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。 |
default_language | string | 对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语 |
language_override | string | 对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language. |
相关博文参考:
MongoDB索引的使用
MongoDB高级查询
MongoDB官网
7.0 查询分析
explain是非常有用的工具,会帮助你获得查询方面诸多有用的信息。只要对游标调用该方法,就可以得到查询细节。explain会返回一个文档,而不是游标本身
db.tablename.find().explain( "executionStats" )
在explain中输入executionStats会输出查询的时间值:
explain.executionStats.executionTimeMillis
8.0 aggregate聚合管道
管道操作符 | 与MySql对比 | 描述 |
---|---|---|
$project | SELECT | 重命名,删除,修改字段 |
$match | WHERE/HAVING | 条件匹配 |
$lookup | JOIN | 表连接 |
$skip | 跳过文档数量 | |
$limit | LIMIT | 限制文档数量 |
$sort | ORDER BY | 文档排序 |
$group | GROUP | 文档分组 |
collections_name文档结构:
{
"_id" : ObjectId("5c124aaaa616c03bb0b86594"),
"cid" : "1",
"author_id" : 10,
"title" : "标题信息",
"content" : "内容信息",
"description" : "文章描述信息" ,
"zan_count":215
}
db.COLLECTION_NAME.aggragate([
{ $match:{"zan_count":{$gte:100,$lte:500}}//过滤掉赞数量值在100-500的数据},
{ $limit:10//只显示10条 },
{ $skip:2//跳过前两条 },
{ $sort:{author_id:1}//以zan_count 升序排列 },
{ $project:{zan_count:1,cid:1,author_id:1}//过滤字段,_id默认强制保留},
{
$group:{
_id:"$cid",//以cid进行分组
$total:{$sum:"$zan_count"}//将zan_count相加
}
},
{
$lookup:{
from:"articleCagetory",//关联表
local_field:"cid",COLLECTION_NAME//的关联字段
foregin_field:"categoryId",//articleCagetory的关联字段
as:"category"//articleCagetory关联之后的名称
}
}
])
类似上面$sum的管道操作表达式还有
常用表达式操作符 | Description |
---|---|
$addToSet | 将文档指定字段的值去重 |
$max | 文档指定字段的最大值 |
$min | 文档指定字段的最小值 |
$sum | 文档指定字段求和 |
$avg | 文档指定字段求平均 |
$gt | 大于给定值 |
$lt | 小于给定值 |
$eq | 等于给定值 |
网友评论