版权声明:此文章转载自WebFuse
如需转载请联系听云College团队成员阮小乙,邮箱:ruanqy#tingyun.com
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"})
条件
比较操作符
逻辑操作符
示例代码:
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 } ] } )
其他常用的操作符
示例代码:
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返回限制的情况。
参考:
《MongoDB 实战》
《MongoDB官方文档》