1、MongoDB的基本操作
查看数据库
show dbs;
切换数据库,如果没有对应的数据库则创建
use 数据库名;
创建集合
db.createCollection("集合名")
查看集合
show tables;
show collections;
删除集合
db.集合名.drop();
删除当前数据库
db.dropDatabase();
2、MongoDB集合数据操作(CURD)
(1)数据添加
插入单条数据:db.集合名.insert(文档)
- 文档的数据结构和JSON基本一样。
- 所有存储在集合中的数据都是BSON格式。
- BSON是一种类json的一种二进制形式的存储格式,简称Binary JSON。
例如:
db.lg_resume_preview.insert({name:"张晓峰",birthday:new ISODate("2000-07-01"),expectSalary:15000,gender:0,city:"bj"});
没有指定 _id 这个字段,系统会自动生成,当然我们也可以指定 _id 。
_id 类型是ObjectId 类型是一个12字节 BSON 类型数据,有以下格式: 前4个字节表示时间戳 ObjectId("对象Id字符串").getTimestamp() 来获取接下来的3个字节是机器标识码,紧接的两个字节由进程id组成(PID),最后三个字节是随机数。
插入多条数据:db.集合名.insert([文档,文档])
db.lg_resume_preview.insert([
{name:"张晓丽",birthday:new ISODate("2001-04-01"),
expectSalary:25000,city:'bj'},
{name:"李丽",birthday:new ISODate("2002-06-01"),
expectSalary:18000,city:'sh'}]);
(2)数据查询
比较条件查询:db.集合名.find(条件)
操作 | 条件格式 | 例子 | RDBMS中的条件 | 等于 | {key:value} | db.col.?nd({字段名:值}).pretty() | where 字段名=值 | 大于 | {key:{$gt:value}} | db.col.?nd({字段名:{$gt:值}}).pretty() | where 字段名>值 | 小于 | {key:{$lt:value}} | db.col.?nd({字段名:{$lt:值}}).pretty() | where 字段名<值 | 大于等于 | {key:{$gte:value}} | db.col.?nd({字段名:{$gte:值}}).pretty() | where 字段名>= 值 | 小于等于 | {key:{$lte:value}} | db.col.?nd({字段名:{$lte:值}}).pretty() | where 字段名<= 值 | 不等于 | {key:{$ne:value}} | db.col.?nd({字段名:{$ne:值}}).pretty() | where 字段名!=值 |
注意:当find里面的条件为空时,则会查询所有的数据,pretty()方法,被用来优化我们查询结果的展示,更方便我们观看。
逻辑条件查询:
and 条件
????????MongoDB 的 find() 方法可以传入多个键(key),每个键(key)以逗号隔开,即常规 SQL 的 AND 条件
db.集合名.find({key1:value1, key2:value2}).pretty()
or 条件
db.集合名.find({$or:[{key1:value1}, {key2:value2}]}).pretty()
not 条件
db.集合名.find({key:{$not:{$操作符:value}}).pretty()
分页查询
db.集合名.find({条件}).sort({排序字段:排序方式})).skip(跳过的行数).limit(一页显示多少数据)
(3)数据更新,调用update
$set :设置字段值 $unset :删除指定字段 $inc:对修改的值进行自增
db.集合名.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)
db.集合名.update({条件},{$set:{字段名:值}},{multi:true})
参数说明:
query : update的查询条件,类似sql update查询内where后面的。 update : update的对象和一些更新的操作符(如$set,$inc...)等,也可以理解为sql update中set后面的 upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插,默认是false,不插入。 multi : 可选,MongoDB 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按件查出来多条记录全部更新。 writeConcern :可选,用来指定mongod对写操作的回执行为比如写的行为是否需要确认。
示例:?
db.lg_resume_preview.update({name:"李丽"},
{$inc:{expectSalary:-10000}},
{ multi: false, upsert: false}
)
db.lg_resume_preview.update({name:"李丽"},
{$unset:{expectSalary:""}}, # 删除指定字段时,字段后面的值留空即可
{ multi: false, upsert: false}
)
db.lg_resume_preview.update({name:"李丽"},
{expectSalary:18000},
{ multi: false, upsert: false} # 注意使用这种方式,会造成该条数据除expectSalary字段以外的字段都被删除(因此别忘了添加参数)
)
writeConcern 包括以下字段: { w: <value>, j: <boolean>, wtimeout: <number> } ????????w:指定写操作传播到的成员数量
比如: w=1(默认):则要求得到写操作已经传播到独立的Mongod实例或副本集的primary成员的确认 w=0:则不要求确认写操作,可能会返回socket exceptions和 networking errors w="majority":要求得到写操作已经传播到大多数具有存储数据具有投票的(data-bearing voting)成员(也就是 members[n].votes 值大于0的成员)的确认 ????????j:要求得到Mongodb的写操作已经写到硬盘日志的确认
比如: ????????j=true:要求得到Mongodb(w指定的实例个数)的写操作已经写到硬盘日志的确认。j=true本身并不保证因为副本集故障而不会回滚。 wtimeout:指定write concern的时间限制,只适用于w>1的情况 ????????wtimeout在超过指定时间后写操作会返回error,即使写操作最后执行成功,当这些写操作返回时,MongoDB不会撤消在wtimeout时间限制之前执行成功的数据修改。 ????????如果未指定wtimeout选项且未指定write concern级别,则写入操作将无限期阻止。 指定wtimeout值为0等同于没有wtimeout选项。
(4)数据删除
db.collection.remove(
<query>,
{
justOne: <boolean>,
writeConcern: <document>
}
)
参数说明:
- query :(可选)删除的文档的条件。
- justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值
- false,则删除所有匹配条件的文档。
- writeConcern :(可选)用来指定mongod对写操作的回执行为。
3、MongoDB 聚合操作
(1)聚合操作简介
????????聚合是MongoDB的高级查询语言,它允许我们通过转化合并由多个文档的数据来生成新的在单个文档里不存在的文档信息。一般都是将记录按条件分组之后进行一系列求最大值,最小值,平均值的简单操作,也可以对记录进行复杂数据统计,数据挖掘的操作。聚合操作的输入是集中的文档,输出可以是一个文档也可以是多个文档。
(2)MongoDB 聚合操作分类
- 单目的聚合操作(Single Purpose Aggregation Operation)
- 聚合管道(Aggregation Pipeline)
- MapReduce 编程模型
(3)单目的聚合操作
单目的聚合命令常用的有:
- count():统计集合中数据个数
- distinct():去重
db.lg_resume_preview.find().count() # 对查找到的数据进行统计
db.lg_resume_preview.distinct("city") # 对集合中的数据去重后,进行显示
db.lg_resume_preview.count() # 直接统计集合中数据的个数
(4)聚合管道(Aggregation Pipeline)
db.集合名.aggregate(AGGREGATE_OPERATION)
db.lg_resume_preview.aggregate([{$group:{_id:"$city",city_count:{$sum:1}}}])
????????MongoDB中聚合(aggregate)主要用于统计数据(诸如统计平均值,求和等),并返回计算后的数据结果。
表达式:处理输入文档并输出。表达式只能用于计算当前聚合管道的文档,不能处理其它的文档。
表达式 | 描述 | $sum | 计算总和 | $avg | 计算平均值 | $min | 获取集合中所有文档对应值得最小值 | $max | 获取集合中所有文档对应值得最大值 | $push | 在结果文档中插入值到一个数组中 | $addToSet | 在结果文档中插入值到一个数组中,但数据不重复 | $first | 根据资源文档的排序获取第一个文档数据 | $last | 根据资源文档的排序获取最后一个文档数据 |
????????MongoDB 中使用 db.集合名.aggregate([{},...]) 方法来构建和使用聚合管道,每个文档通过一个由一个或者多个阶段(stage)组成的管道,经过一系列的处理,输出相应的结果。
????????MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。
这里我们介绍一下聚合框架中常用的几个操作:
表达式 | 说明 | $group | 将集合中的文档分组,可用于统计结果。 | $project | 修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。 | $match | 用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。 | $limit | 用来限制MongoDB聚合管道返回的文档数。 | $skip | 在聚合管道中跳过指定数量的文档,并返回余下的文档。 | $sort | 将输入文档排序后输出。 | $geoNear | 输出接近某一地理位置的有序文档。 |
示例:
????????先插入数据
/** 插入数据 */
db.lg_resume_preview.insert({name:"张晓峰",birthday:new ISODate("2000-07-01"),gender:1,expectSalary:15000,city:"bj"})
db.lg_resume_preview.insert({name:"张震",birthday:new ISODate("1995-04-01"),gender:1,expectSalary:18000,city:"bj"})
db.lg_resume_preview.insert({name:"李山",birthday:new Date("1995-04-01"),gender:1,expectSalary:25000,city:"sh"})
db.lg_resume_preview.insert({name:"李笑来",birthday:new Date("1998-04-01 14:20:09"),gender:1,expectSalary:20000,city:"sh"})
db.lg_resume_preview.insert({name:null,birthday:new Date("1992-04-01 14:20:09"),gender:1,expectSalary:30000,city:"sh"})
db.lg_resume_preview.insert({birthday:new Date("1991-05-01 14:20:09"),gender:1,expectSalary:50000,city:"sz"})
db.lg_resume_preview.insert(
[{name:"李丽",birthday:new Date("1996-05-01 14:20:09"),gender:0,expectSalary:21000,city:"sz"},
{name:"李平",birthday:new Date("1997-07-01 14:20:09"),gender:0,expectSalary:22000,city:"sz"}])
? ? ? ? 测试
/** 按照city 进行分组 统计每个city出现的次数*/
db.lg_resume_preview.aggregate([{
$group: {
_id: "$city",
city_count: {
$sum: 1
}
}
}]) // 出现一次加一
db.lg_resume_preview.aggregate({
$group: {
_id: "$city",
city_count: {
$sum: 1
}
}
})
/** 按照city 进行分组 统计每个city 中expectSalary的平均值 */
db.lg_resume_preview.aggregate([{
$group: {
_id: "$city",
avg_sal: {
$avg: "$expectSalary"
}
}
}])
/** 按照city 进行分组 统计每个city的值放入一个数组中 */
db.lg_resume_preview.aggregate([{
$group: {
_id: "$city",
city_name: {
$push: "$city"
}
}
}])
db.lg_resume_preview.aggregate([{
$group: {
_id: "$city",
city_name: {
$addToSet: "$city"
}
}
}])
db.lg_resume_preview.aggregate(
[{
$group: {
_id: "$city",
avgSal: {
$avg: "$expectSalary"
}
}
}, {
$project: {
city: "$city",
sal: "$avgSal"
}
}]
)
db.lg_resume_preview.aggregate(
[{
$group: {
_id: "$city",
count: {
$sum: 1
}
}
}, {
$match: {
count: {
$gte: 2
}
}
}]
)
db.lg_resume_preview.aggregate(
[{
$group: {
_id: "$city",
city_count: {
$sum: 1
}
}
}, {
$match: {
city_count: {
$gte: 2
}
}
}]
)
(5)MapReduce 编程模型
????????Pipeline查询速度快于MapReduce,但是MapReduce的强大之处在于能够在多台Server上并行执行复杂的聚合逻辑。MongoDB不允许Pipeline的单个聚合操作占用过多的系统内存,如果一个聚合操作消耗20%以上的内存,那么MongoDB直接停止操作,并向客户端输出错误消息。
????????MapReduce是一种计算模型,简单的说就是将大批量的工作(数据)分解(MAP)执行,然后再将结果合并成最终结果(REDUCE)。
db.collection.mapReduce(
function() {
emit(key, value);
}, //map 函数
function(key, values) {
return reduceFunction
}, //reduce 函数
{
out: collection,
query: document,
sort: document,
limit: number,
finalize: < function > ,
verbose: < boolean >
}
)
????????使用 MapReduce 要实现两个函数 Map 函数和 Reduce 函数,Map 函数调用 emit(key, value), 遍历collection 中所有的记录, 将 key 与 value 传递给 Reduce 函数进行处理。
参数说明:
表达式 | 说明 | map | 是JavaScript 函数,负责将每一个输入文档转换为零或多个文档,生成键值对序列,作为reduce 函数参数 | reduce | 是JavaScript 函数,对map操作的输出做合并的化简的操作(将key-value变成keyvalues,也就是把values数组变成一个单一的值value) | out | 统计结果存放集合 | query | 一个筛选条件,只有满足条件的文档才会调用map函数。 | sort | 和limit结合的sort排序参数(也是在发往map函数前给文档排序),可以优化分组机制 | limit | 发往map函数的文档数量的上限(要是没有limit,单独使用sort的用处不大) | finalize | 可以对reduce输出结果再一次修改 | verbose | 是否包括结果信息中的时间信息,默认为fasle |
db.lg_resume_preview.mapReduce(
function() {
emit(this.city, this.expectSalary);
},
function(key, value) {
return Array.avg(value)
},
{
query: {
expectSalary: {
$gt: 15000
}
},
out: "cityAvgSal",
finalize: function(key, value) {
return value + 5000; # 对获取到的工资加5000;
}
}
)
|