MongoDB概念
- database:数据库。一个MongoDB实例可以容纳多个数据库。
- collection:集合。类似于关系型数据库中的表。
- document:文档。类似于关系型数据库中的行。
- field:域。类似于关系型数据库中的字段。
常用的命令
show dbs:显示所有的数据库
db:显示当前数据库对象
use XXX:连接到指定的数据库,XXX为数据库名
创建与删除
使用 use DATABASE_NAME
命令可以创建数据库。如果数据库不存在就创建,如果存在就切到该数据库。刚创建的数据库在用show dbs
命令时是不显示出来的,需要插入一条数据后使用show dbs
命令才会显示。
使用db.dropDatabase()
命令删除当前数据库。
增删改查
新增
使用insert()或save()方法向集合中插入文档。
语法:db.COLLECTION_NAME.insert(document)
db.col.insert({
"name" : "ZZ",
"name_cn" : "造字法",
"order" : 0,
"update_time" : 1463404597556,
"delete_flag" : false
})
使用insert()方法后,MongoDB会自动给你添加一个_id字段,并自动给予一个值。使用save()方法,如果不指定_id字段save()方法就类似于insert()方法,如果指定_id字段,则会更新该_id的数据(其实就是修改)。
删除
使用remove()方法删除集合中的文档。
语法:
db.COLLECTION_NAME.remove(
< query语句 >,
{
justOne: < boolean >,
writeConcern: < document >
}
)
query语句:删除文档的条件(可选)。
justOne : (可选)如果设为 true 或 1,则只删除一个文档。
writeConcern :(可选)抛出异常的级别。
示例:
db.col.remove({"name":"ZZ"})
修改
使用update()或save()方法向集合中插入文档。
update()语法:
db.COLLECTION_NAME.update(
< query查询条件 >,
< update语句 >,
{
upsert: < boolean >,
multi: < boolean >,
writeConcern: < document >
}
)
query语句:更新的查询条件,类似于SQL语句的where。
update语句:要更新的对象以及更新操作符(如:$),类似于SQL语句的set。
upsert:可选,这个参数的意思是,如果不存在update的记录,是否插入新对象;true为插入,默认是false,不插入。
multi:可选,mongodb默认是false,只更新找到的第一条记录;如果这个参数为true,就把按条件查出来多条记录全部更新。
writeConcern:可选,抛出异常的级别。
示例:
db.col.update({"name":"ZZ"},{$set:{"name_cn":"造字"}})
db.col.update({"name":"ZZ"},{$set:{"name_cn":"造字"}},{multi:true})
save()语法:
db.COLLECTION_NAME.save(
< document >,
{
writeConcern: < document >
}
)
document:文档数据。
writeConcern:可选,抛出异常的级别。
查询
使用find()方法对集合进行查询。
语法:
db.COLLECTION_NAME.find(query, projection)
query:查询的条件语句
projection:映射关系语句
示例:
db.dimensions.find()
db.dimensions.find({"name":"ZZ"})
条件
比较操作符
操作符 | 语法格式 |
---|---|
等于 | { < field >: < value > } |
$eq(等于) | { < field >: { $eq: < value > } } |
$gt(大于) | { < field >: { $gt: < value > } } |
$gte(大于等于) | { < field >: { $gte: < value > } } |
$lt(小于) | { < field >: { $lt: < value > } } |
$lte(小于等于) | { < field >: { $lte: < value > } } |
$ne(不等于) | { < field >: { $ne: < value > } } |
$in | { < field >: { $in: [< value1 >, < value2 >, … < valueN > ] } } |
$nin | { < field >: { $nin: [< value1 >, < value2 >, … < valueN > ] } } |
逻辑操作符
操作符 | 语法格式 |
---|---|
AND | {key1:value1, key2:value2} |
$and(AND操作) | { $and: [ { < expression1 > }, { < expression2 > } , … , { < expressionN > } ] } |
$or(OR操作) | { $or: [ { < expression1 > }, { < expression2 > } , … , { < expressionN > } ] } |
$not(NOT操作) | { field: { $not: { < operator-expression > } } } |
$nor(NOT OR操作) | { $nor: [ { < expression1 > }, { < expression2 > }, … { < expressionN > } ] } |
示例代码:
db.t_resources.find({"create_time":1463233651537,"update_time":1463416983501})
db.inventory.find( { $and: [ { price: { $ne: 1.99 } }, { price: { $exists: true } } ] } )
db.inventory.find( { $or: [ { quantity: { $lt: 20 } }, { price: 10 } ] } )
db.inventory.find( { price: { $not: { $gt: 1.99 } } } )
db.inventory.find( { $nor: [ { price: 1.99 }, { sale: true } ] } )
其他常用的操作符
操作符 | 语法格式 | 说明 |
---|---|---|
$exists | { field: { $exists: < boolean > } } | 是否存在 |
$type | { field: { $type: < BSON type number > or < String alias > } } | 基于BSON类型来检索集合中匹配的数据类型,并返回结果 |
$all | { < field >: { $all: [ < value1 > , < value2 > … ] } } | 数组中的值全部包含 |
示例代码:
db.articles.find( { tags: { $all: [ [ "ssl", "security" ] ] } } )
db.addressBook.find( { "zipCode" : { $type : 2 } } )
db.records.find( { b: { $exists: false } } )
排序
使用sort()对数据进行排序。sort()方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而-1是用于降序排列。
语法:db.COLLECTION_NAME.find().sort({field: value})
示例:
db.dimensions.find().sort({'name_cn':1,'update_time':-1})
limit和skip方法
如果要读取指定数量的数据记录,可以使用limit()方法。
语法:db.COLLECTION_NAME.find().limit(NUMBER)
可以使用skip()方法跳过一定数量来读取数据。
语法:db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)
所以,skip()方法和limit()方法结合可以用来分页。
示例:
db.dimensions.find().skip(10).limit(10)
索引
创建索引来提升查询性能是很常见的做法。
在MySQL中explain显示了MySQL如何使用索引来处理select语句以及连接表。同理,Mongo中的EXPLAIN用来描述查询路径,通过判断查询使用了哪个索引来帮助开发者诊断慢查询。如:db.numbers.find( {num: {"$gt": 199995 }} ).explain()
创建索引的示例:
db.numbers.ensureIndex({num: 1})
或者
db.numbers.createIndex({num: 1})
在MongoDB v3.0.0以后,建议使用的是createIndex()方法,ensureIndex()方法是不赞成在v3.0.0以后的Mongo版本中使用的。
语法:db.collection.createIndex( <key and index type specification>, <options> )
语法中 Key 值为你要创建的索引字段,1为指定按升序创建索引,如果你想按降序来创建索引指定为-1即可。
下表是一些比较常用的创建索引时候的附加参数:
操作符 | 类型 | 说明 |
---|---|---|
background | Boolean | 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 “background” 可选参数。 “background” 默认值为false。 |
unique | Boolean | 建立的索引是否唯一。指定为true创建唯一索引。默认值为false. |
name | string | 索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。 |
sparse | Boolean | 对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false. |
expireAfterSeconds | integer | 指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间. |
weights | document | 索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。 |
示例代码:
db.numbers.createIndex({num: 1}, {background: true})
聚合
MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。
Aggregation Pipeline
语法:db.collection.aggregate(pipeline, options)
,其中pipeline是一个管道数组,options是选项。
我们以一张官方文档上的图来说明一下聚合操作:
上图中我们看到了\$match,\$group。这两个是什么呢? 答案就在以下常用的piple操作列表。
- $project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
- $limit:用来限制MongoDB聚合管道返回的文档数。
- $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
- $unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
- $group:将集合中的文档分组,可用于统计结果(参数与group方法不同哦~)。
- $sort:将输入文档排序后输出。
- $geoNear:输出接近某一地理位置的有序文档。
- $lookup:将Left Outer Join引入到MongoDB。
- \$match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
以上各操作的用法详见:MongoDB文档
distinct方法
MongoDB的distinct命令是获取特定字段中不同值列表的最简单工具。该命令既适用于单键,也适用于数组键。distinct默认覆盖整个集合,但也可以通过查询选择器进行约束。
语法:db.collection.distinct(field, query)
示例:
db.products.distinct("tags")
db.inventory.distinct( "item.sku", { dept: "A" } )
group方法
gourp方法的作用与SQL中的 “SELECT <…> GROUP BY <…>”的作用一样。
语法:db.collection.group({ key, reduce, initial [, keyf] [, cond] [, finalize] })
示例:
results = db.reviews.group({
key:{
user_id:true
},
initial:{
reviews:0,
votes:0
},
reduce:function(doc,aggregator){
aggregator.reviews +=1;
aggregator.votes += doc.votes;
},
finalize:function(doc){
doc.average_votes = doc.votes / doc.reviews;
}
})
group方法的各个参数说明如下:
- key,描述分组字段的文档。如上例,我们根据user_id分组,所以设置user_id:true。
- keyf,这是一个JavaScript函数,应用于文档之上,为该文档生成一个键,当用于分组的键需要计算时,这个函数非常有用。
- initial,作为聚合结果初始值的文档。reduce函数第一次运行时,该初始文档会作为聚合器的第一个值,通常会包含所有要聚合的键。
- reduce,用于执行聚合的JavaScript函数。该函数接受两个参数:正被迭代的当前文档和用于存储聚合结果的聚合器文档。聚合器的初始值就是初始文档。reduce函数并不返回任何内容,它只不过是修改聚合器对象。
- cond,过滤要聚合文档的查询选择器。如果不希望分组操作处理整个集合,就必须提供一个查询选择器。
- finalize,在返回结果集之前应用于每个结果文档的JavaScript函数。该函数支持对分组操作的结果进行后置处理。
Map-Reduce
Map-Reduce是一种计算模型,简单的说就是将大批量的工作(数据)分解(MAP)执行,然后再将结果合并成最终结果(REDUCE)。
MongoDB提供的Map-Reduce非常灵活,对于大规模数据分析也相当实用。
语法:
db.collection.mapReduce(
<map>,
<reduce>,
{
out: <collection>,
query: <document>,
sort: <document>,
limit: <number>,
finalize: <function>,
scope: <document>,
jsMode: <boolean>,
verbose: <boolean>,
bypassDocumentValidation: <boolean>
}
)
同样的,来一张官方的图:
主要的参数说明如下;
- map,应用于每个文档之上的JavaScript函数。该函数必须调用emit()来选择要聚合的键和值。
- reduce,一个JavaScript函数,接受一个键和一个值列表。该函数对返回值的结构有严格要求,必须总是与values数组所提供的结构一致。reduce函数通常会迭代一个值的列表,在此过程中对其进行聚合。
- query,用于过滤映射处理的集合的查询选择器。该参数的作用与group的cond参数相同。
- sort,对于查询的排序。
- limit,一个整数,指定了查询和排序的条数。
- out,该参数决定了如何返回输出内容。要将所有输出作为命令本身的结果,传入{inline: 1}。请注意,这仅适用于结果集符合16 MB返回限制的情况。
参考:
- http://www.runoob.com/mongodb/mongodb-tutorial.html
- 《MongoDB 实战》
- 《MongoDB官方文档》