Mongo
MongoDB 是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。、
入门
安装Mongo
windows安装
http://www.runoob.com/mongodb/mongodb-window-install.html
linux安装
https://www.cnblogs.com/pfnie/articles/6759105.html
基本操作
创建数据库
use DATABASE_NAME 创建/切换数据库
查看当前所在库
db 查看当前所在库
查看所有库
show dbs 查看所有库
删除db
db.dropDatabase() 删除库(先进入库use dbname)
创建集合(表)
db.createCollection("tableName")
createCollection四个参数:
capped(布尔型):
如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。当该值为 true 时,必须指定 size 参数。
autoIndexId(布尔型):
如为 true,自动在 _id 字段创建索引。默认为 false。
size(数值型):
为固定集合指定一个最大值(以字节计)。如果 capped 为 true,也需要指定该字段。
max(数值型):
指定固定集合中包含文档的最大数量。
例子:
db.createCollection(
"tablename1",
{
capped : true,
autoIndexId : true,
size : 6142800,
max : 10000
}
)
删除集合(表)
db.tableName.drop()
显示当前db状态
db.stats();
当前db版本
db.version();
查看命令提示
db.help(); db.tableName.help(); db.tableName.find().help();
增删改查
插入文档
db.tableName.insert()
例子:
db.user.insert({ "name" : "zhangsan", "age" : 15})
查询文档
db.tableName.find()
两个参数:
query 条件
例子:
db.tableName.find({"name":"zhangsan"})
projection 返回文档的信息(返回的列)
例子:
db.tableName.find({"name":"zhangsan"}, {"name":0, "age":1})
注意:值只有0和1,1表示显示项,0表示不显示项
条件操作符
sql | 语义 | mongo | 列子 |
---|---|---|---|
> | 大于 | $gt | db.tableName.find({"age":{$gt:15}}) |
< | 小于 | $lt | |
>= | 大于等于 | $gte | |
!= | 不等于 | $ne | |
in | 在...里面 | $in | db.tableName.find({"name":{"$in":["zhangsan","lisi"]}}) |
or | 或者 | $or | db.tableName.find({"gender": "boy", $or: [{"name": "zhangsan"}) |
$type操作符
类型 | 代号值 |
---|---|
Double | 1 |
String | 2 |
Object | 3 |
Array | 4 |
Binary data | 6 |
Object id | 7 |
Boolean | 8 |
Date | 9 |
Null | 10 |
JavaScript | 13 |
模糊查询
正则匹配:
$regex
例子:
db.tableName.find({"name":{$regex:"zhang"}})
删除文档
db.tableName.remove(
<query>,
<justOne>
)
uery :(可选)删除的文档的条件。
justOne : (可选)如果设为 true 或 1,则只删除一个文档。
例子:
db.tableName.remove({"name":"zhangsan"})
更新文档
db.tableName.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)
query : update的查询条件,类似sql update查询内where后面的。
update : update的对象和一些更新的操作符,也可以理解为sql update查询内set后面的。(https://blog.csdn.net/sunnyyoona/article/details/52420210)
upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
writeConcern : 可选,抛出异常的级别。
例子:
db.tableName.update({"name":"zhangsan"}, {"name":"wangwu", age:18})
分页排序
分页
limit与skip
limit(number) 读取指定数量数据
例子:
db.tableName.find().limit(2) 显示两条数据
skip(number) 跳过指定数量的数据
例子:
db.tableName.find().skip(2) 跳过前面两条数据,从第三条开始读取
排序
sort({KEY:1})
例子:
db.tableName.find().sort({"age" : -1}) 1升-1降
注意:skip(), limilt(), sort()三个放在一起执行的时候,执行的顺序是先 sort(), 然后是 skip(),最后是limit()。
索引
查看索引
getIndexes() 方法可以用来查看集合的所有索引
totalIndexSize() 查看集合索引的总大小
创建索引
字段索引
db.tableName.ensureIndex({KEY:1}, {options})
例子:
db.tableName.ensureIndex({"name" : 1})
keys,要建立索引的参数列表。如:{KEY:1},其中key表示字段名,1表示升序排序,也可使用使用数字-1降序。
options,可选参数,表示建立索引的设置。可选值如下:
参数 | 类型 | 描述 |
---|---|---|
background | Boolean | 在后台建立索引,以便建立索引时不阻止其他数据库活动,默认值 false |
unique | Boolean | 创建唯一索引,默认值 false |
name | String | 指定索引的名称,如果未指定,MongoDB会生成一个索引字段的名称和排序顺序串联,名字长度限制为125字节 |
dropDups | Boolean | 创建唯一索引时,如果出现重复删除后续出现的相同索引,只保留第一个 |
sparse | Boolean | 对文档中不存在的字段数据不启用索引,默认值是 false |
v | index version | 索引的版本号 |
weights | document | 索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重 |
复合索引
复合索引也称多字段索引
db.tableName.ensureIndex({"name":1,"age":-1})
多键索引
多键索引与单键索引创建形式相同,区别在于字段的值.值具有多个记录,例如数组。
db.tableName.insert({x:[1,2,3,4]})
过期索引
过期索引只能建立在时间类型上(时间数组也行,数字是以最小时间为标准),不能使用时间戳;不能是复合索引;删除时间不是非常精确(删除也需要时间)。
db.tableName.ensureIndex({"time":1},{expireAfterSeconds:10})
db.zhoucl.insert({"name":"zhangsan"+50, "age":14, "gender":"难","time":new Date()})
//插入数据十秒后将被删除
全文索引(文本索引)
能解决快速文本查找的需求,每张表只允许创建一个全文索引;全文索引只能指定一个$text;
普通全文索引
db.tableName.ensureIndex({"key":"text"})
多列全文索引
db.tableName.ensureIndex({"key":"text", "key2":"text"})
所有列
db.tableName.ensureIndex({"$**":"text"})
查询指定关键字:{"$search" : "查询关键字"}
查询多个关键字(或关系):{"$search" : "查询关键字 查询关键字 ......"}
查询多个关键字(与关系):{"$search" : ""查询关键字" "查询关键字" ......"} # "转义字符
排除多个关键字(排除某一个):{"$search" : ""查询关键字" "查询关键字"...... - 排除关键字"}
相似度查询
db.tableName.find({$text:{$search:"aa bb"}}, {score:{$meta:"textSore"}}})
排序
db.tableName.find({$text:{$search:"aa"}}, {score:{$meta:"textScore"}}).sort({score:{$meta:"textScore"}})
其他类型索引
哈希索引(Hashed Index) 是指按照某个字段的hash值来建立索引,目前主要用于MongoDB Sharded
Cluster的Hash分片,hash索引只能满足字段完全匹配的查询,不能满足范围查询等。
地理位置索引(Geospatial Index)能很好的解决O2O的应用场景,比如『查找附近的美食』、『查找某个区域内的车站』等。
聚合
aggregate主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。
aggregate()是基于数据处理的聚合管道,每个文档通过一个由多个阶段(stage)组成的管道,可以对每个阶段的管道进行分组、过滤等功能,然后经过一系列的处理,输出相应的结果。Mongo还提供了一些聚合函数如:count(),distinct()。
语法:
db.collection.aggregate(pipeline, options)
gourp聚合:
group做的聚合有些复杂。先选定分组所依据的键,此后MongoDB就会将集合依据选定键值的不同分成若干组。然后可以通过聚合每一组内的文档,产生一个结果文档。
$group聚合相关表达式:
表达式 | 描述 | 实例 |
---|---|---|
$sum | 计算总和 | db.mycol.aggregate([{by_user", num_tutorial : {likes"}}}]) |
$avg | 计算平均值 | db.tableName.aggregate([{by_user", num_tutorial : {likes"}}}]) |
$min | 获取集合中所有文档对应值得最小值 | db.tableName.aggregate([{by_user", num_tutorial : {likes"}}}]) |
$max | 获取集合中所有文档对应值得最大值 | db.tableName.aggregate([{by_user", num_tutorial : {likes"}}}]) |
$push | 在结果文档中插入值到一个数组中 | db.tableName.aggregate([{by_user", url : {url"}}}]) |
$addToSet | 在结果文档中插入值到一个数组中,但不创建副本 | db.tableName.aggregate([{by_user", url : {url"}}}]) |
$first | 根据资源文档的排序获取第一个文档数据 | db.tableName.aggregate([{by_user", first_url : {url"}}}]) |
$last | 根据资源文档的排序获取最后一个文档数据 | db.tableName.aggregate([{by_user", last_url : {url"}}}]) |
例子1:
数据如下:
{_id: 1, title: 'MongoDB Overview', description: 'MongoDB is no sql database', by_user: 'runoob.com', url: 'http://www.runoob.com',tags: ['mongodb', 'database', 'NoSQL'],likes: 100},
{_id: 2, title: 'NoSQL Overview', description: 'No sql database is very fast', by_user: 'runoob.com', url: 'http://www.runoob.com', tags: ['mongodb', 'database', 'NoSQL'], likes: 10},
{_id: 3, title: 'Neo4j Overview', description: 'Neo4j is no sql database', by_user: 'Neo4j', url: 'http://www.neo4j.com', tags: ['neo4j', 'database', 'NoSQL'], likes: 750 }
聚合函数如下:
db.tableName.aggregate(
[
{
$group : {
_id : "$by_user",
num_tutorial : {
$sum : 1
}
}
}
]
)
结果如下:
{ "_id" : "runoob.com", "num_tutorial" : 2}
{ "_id" : "Neo4j", "num_tutorial" : 1}
例子2:
数据如下:
{ "_id" : 1, "item" : "abc", "price" : 10, "quantity" : 2, "date" : ISODate("2014-03-01T08:00:00Z") }
{ "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1, "date" : ISODate("2014-03-01T09:00:00Z") }
{ "_id" : 3, "item" : "xyz", "price" : 5, "quantity" : 10, "date" : ISODate("2014-03-15T09:00:00Z") }
{ "_id" : 4, "item" : "xyz", "price" : 5, "quantity" : 20, "date" : ISODate("2014-04-04T11:21:39.736Z") }
{ "_id" : 5, "item" : "abc", "price" : 10, "quantity" : 10, "date" : ISODate("2014-04-04T21:23:13.331Z") }
聚合函数如下:
db.tableName.aggregate([
{
$group : {
_id : { month: { $month: "$date" }, day: { $dayOfMonth: "$date" }, year: { $year: "$date" } },
totalPrice: { $sum: { $multiply: [ "$price", "$quantity" ] } },
averageQuantity: { $avg: "$quantity" },
count: { $sum: 1 }
}
}
]
)
结果如下:
{ "_id" : { "month" : 3, "day" : 15, "year" : 2014 }, "totalPrice" : 50, "averageQuantity" : 10, "count" : 1 }
{ "_id" : { "month" : 4, "day" : 4, "year" : 2014 }, "totalPrice" : 200, "averageQuantity" : 15, "count" : 2 }
{ "_id" : { "month" : 3, "day" : 1, "year" : 2014 }, "totalPrice" : 40, "averageQuantity" : 1.5, "count" : 2 }
其他聚合:
count
db.tableName.find().count() 统计总数
distinct
db.collection_name.distinct(field,query,options) 去重复
管道
MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。
管道表达式:
表达式 | 描述 |
---|---|
$project | 修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档 |
$match | 用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作 |
$limit | 用来限制MongoDB聚合管道返回的文档数 |
$skip | 在聚合管道中跳过指定数量的文档,并返回余下的文档 |
$unwind | 将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值 |
$group | 将集合中的文档分组,可用于统计结果 |
$sort | 将输入文档排序后输出 |
$geoNear | 输出接近某一地理位置的有序文档 |
例子:
db.test.aggregate(
[
{
$group : {
_id : "$by_user",
num_tutorial : {
$sum : 1
}
}
},
{ $skip : 1 }
]
)