晓夏

YoungCheung

Zhang Sir's technical way

MongoDB数据库常用操作

浏览量:1192

一、MongoDB创建数据库

语法:

MongoDB 创建数据库的语法格式如下:

use DATABASE_NAME

如果数据库不存在,则创建数据库,否则切换到指定数据库。

示例:

创建数据库youngcheung

> use  youngcheung
switched to db youngcheung
> db
youngcheung

如果你想查看所有数据库,可以使用 show dbs 命令:

> show dbs
admin  0.000GB
local  0.000GB
test   0.000GB

可以看到,我们刚创建的数据库 youngcheung并不在数据库的列表中, 要显示它,我们需要向 youngcheung数据库插入一些数据。

> db.youngcheung.insert({"name":"张杨"})
WriteResult({ "nInserted" : 1 })
> show dbs
admin        0.000GB
local        0.000GB
test         0.000GB
youngcheung  0.000GB

MongoDB 中默认的数据库为 test,如果你没有创建新的数据库,集合将存放在 test 数据库中。

二、MongoDB删除数据库


语法:

MongoDB 删除数据库的语法格式如下:

db.dropDatabase()

删除当前数据库,默认为 test,你可以使用 db 命令查看当前数据库名。

示例:

以下实例我们删除了数据库 youngcheung

首先,查看所有数据库:

> show dbs
admin        0.000GB
local        0.000GB
test         0.000GB
youngcheung  0.000GB

接下来我们切换到数据库 youngcheung:

> use youngcheung
switched to db youngcheung
>

执行删除命令

> db.dropDatabase()
{ "dropped" : "youngcheung", "ok" : 1 }
>

最后,我们再通过 show dbs 命令数据库是否删除成功:

> show dbs
admin  0.000GB
local  0.000GB
test   0.000GB

删除集合:

集合删除语法格式如下:

db.collection.drop()

三、MongoDB插入文档

        MongoDB 使用 insert() 或 save() 方法向集合中插入文档,语法如下:

db.COLLECTION_NAME.insert(document)

示例:

以下文档可以存储在 MongoDB 的 youngcheung 数据库 的 col集合中:

> db.col.insert({title: 'MongoDB 教程', 
...     description: 'MongoDB 是一个 Nosql 数据库',
...     by: '张杨',
...     url: 'http://www.osriy.com',
...     tags: ['mongodb', 'database', 'NoSQL'],
...     likes: 100
... })
WriteResult({ "nInserted" : 1 })

以上实例中 col 是我们的集合名,前一章节我们已经创建过了,如果该集合不在该数据库中, MongoDB 会自动创建该集合并插入文档。

查看已插入文档:

> db.col.find()

blob.png

我们也可以将数据定义为一个变量,如下所示:

> document=({title: 'MongoDB 教程', 
...     description: 'MongoDB 是一个 Nosql 数据库',
...     by: '张杨',
...     url: 'http://www.osriy.com',
...     tags: ['mongodb', 'database', 'NoSQL'],
...     likes: 100
... });

执行后显示结果如下:

blob.png

执行插入操作:

> db.col.insert(document)
WriteResult({ "nInserted" : 1 })
>

插入文档你也可以使用 db.col.save(document) 命令。如果不指定 _id 字段 save() 方法类似于 insert() 方法。如果指定 _id 字段,则会更新该 _id 的数据。

四、MongoDB更新文档

MongoDB 使用 update() 和 save() 方法来更新集合中的文档。接下来让我们详细来看下两个函数的应用及其区别。

update() 方法:

update() 方法用于更新已存在的文档。语法格式如下:

db.collection.update(
   <query>,
   <update>,
   {
     upsert: <boolean>,
     multi: <boolean>,
     writeConcern: <document>
   })


参数说明:

  • query : update的查询条件,类似sql update查询内where后面的。

  • update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的

  • upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。

  • multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。

  • writeConcern :可选,抛出异常的级别。

示例:

我们在集合 col 中插入如下数据(上面已经插入了此文档):

db.col.insert({
    title: 'MongoDB 教程', 
    description: 'MongoDB 是一个 Nosql 数据库',
    by: '张杨',
    url: 'http://www.osriy.com',
    tags: ['mongodb', 'database', 'NoSQL'],
    likes: 100
})

接着我们通过 update() 方法来更新标题(title):

> db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}})

blob.png

可以看到标题(title)由原来的 "MongoDB 教程" 更新为了 "MongoDB"。

以上语句只会修改第一条发现的文档,如果你要修改多条相同的文档,则需要设置 multi 参数为 true。

> db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}},{multi:true})
WriteResult({ "nMatched" : 2, "nUpserted" : 0, "nModified" : 2 })
> db.col.find().pretty()
{

blob.png

save()方法
save() 方法通过传入的文档来替换已有文档。语法格式如下:

db.collection.save(
   <document>,
   {
     writeConcern: <document>
   })

参数说明:

  • document : 文档数据。

  • writeConcern :可选,抛出异常的级别。

示例:

以下实例中我们替换了 _id 为 58bdc69d459f6d3c366ce8e3 的文档数据:

> db.col.save({
... "_id" : ObjectId("58bdc69d459f6d3c366ce8e3"),
...     "title" : "MongoDB",
...     "description" : "MongoDB 是一个 Nosql 数据库",
...     "by" : "YoungCheung",
...     "url" : "http://www.osriy.com",
...     "tags" : [
...             "mongodb",
...             "NoSQL"
...     ],
...     "likes" : 110
... })
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
>

替换成功后,我们通过find()命令查看替换后的数据:

> db.col.find().pretty()

blob.png

更多范例:

只更新第一条记录:

db.col.update({"count":{$gt:1}},{$set:{"test2":"OK"}});

全部更新:

db.col.update({"count":{$gt:3},{$set:{"test2":"OK"}},false,true);

只添加第一条:

db.col.update({"count":{$gt:4}},{$set:{"test5":"OK"}},true,false);

全部添加加进去:

db.col.update({"count":{$gt:5}},{$set:{"test5":"OK"}},true,true);

全部更新:

db.col.update({"count":{$gt:15}},{$inc:{"count":1}},false,true);

只更新第一条记录:

db.col.update({"count":{$gt:10}},{$inc:{"count":1}},false,false);

五、删除文档

MongoDB remove()函数是用来移除集合中的数据。

MongoDB数据更新可以使用update()函数。在执行remove()函数前先执行find()命令来判断执行的条件是否正确,这是一个比较好的习惯。

语法:

remove() 方法的基本语法格式如下所示:

db.collection.remove(
   <query>,
   <justOne>)

如果你的 MongoDB 是 2.6 版本以后的,语法格式如下

db.collection.remove(
   <query>,
   {
     justOne: <boolean>,
     writeConcern: <document>
   })


参数说明:

  • query :(可选)删除的文档的条件。

  • justOne : (可选)如果设为 true 或 1,则只删除一个文档。

  • writeConcern :(可选)抛出异常的级别。

示例:

以下文档我们执行两次插入操作:

db.col.insert({title: 'MongoDB 教程', 
    description: 'MongoDB 是一个 Nosql 数据库',
    by: '张杨',
    url: 'http://www.osriy.com',
    tags: ['mongodb', 'database', 'NoSQL'],
    likes: 100
})

使用find()函数查询数据:

> db.col.find()

blob.png

接下来我们移除 title 为 'MongoDB 教程' 的文档

> db.col.remove({'title':'MongoDB 教程'})
WriteResult({ "nRemoved" : 2 })   #删除了两条数据
> db.col.find()
>                                 #数据为空

如果你只想删除第一条找到的记录可以设置 justOne 为 1,如下所示:

db.COLLECTION_NAME.remove(DELETION_CRITERIA,1)

如果你想删除所有数据,可以使用以下方式(类似常规 SQL 的 truncate 命令):

>db.col.remove({})
>db.col.find()
>

六、MongoDB查询文档

语法:

MongoDB 查询数据的语法格式如下:

>db.COLLECTION_NAME.find()

find() 方法以非结构化的方式来显示所有文档。

如果你需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:

> db.col.find().pretty()

示例:

以下实例我们查询了集合 col 中的数据:

> db.col.find().pretty()

blob.png

除了 find() 方法之外,还有一个 findOne() 方法,它只返回一个文档。

MongoDB 与 RDBMS Where 语句比较

如果你熟悉常规的 SQL 数据,通过下表可以更好的理解 MongoDB 的条件语句查询:

操作格式范例RDBMS中的类似语句
等于{<key>:<value>}db.col.find({"by":"张杨"}).pretty()where by = '张杨'
小于{<key>:{$lt:<value>}}db.col.find({"likes":{$lt:50}}).pretty()where likes < 50
小于或等于{<key>:{$lte:<value>}}db.col.find({"likes":{$lte:50}}).pretty()where likes <= 50
大于{<key>:{$gt:<value>}}db.col.find({"likes":{$gt:50}}).pretty()where likes > 50
大于或等于{<key>:{$gte:<value>}}db.col.find({"likes":{$gte:50}}).pretty()where likes >= 50
不等于{<key>:{$ne:<value>}}db.col.find({"likes":{$ne:50}}).pretty()where likes != 50

MongoDB AND 条件

MongoDB 的 find() 方法可以传入多个键(key),每个键(key)以逗号隔开,及常规 SQL 的 AND 条件。

语法格式如下

db.col.find({key1:value1, key2:value2}).pretty()

示例:

以下实例通过 by 和 title 键来查询 张杨 中 MongoDB 教程 的数据

> db.col.find({"by":"张杨", "title":"MongoDB 教程"}).pretty()

blob.png

以上实例中类似于 WHERE 语句:WHERE by='张杨' AND title='MongoDB 教程'


MongoDB OR 条件

MongoDB OR 条件语句使用了关键字 $or,语法格式如下:

db.col.find(
   {
      $or: [
	     {key1: value1}, {key2:value2}
      ]
   }).pretty()

示例:

以下实例中,我们演示了查询键 by 值为 张杨 或键 title 值为 MongoDB 教程 的文档。

>db.col.find({$or:[{"by":"张杨"},{"title": "MongoDB 教程"}]}).pretty()

blob.png

AND 和 OR 联合使用

以下实例演示了 AND 和 OR 联合使用,类似常规 SQL 语句为: 'where likes>50 AND (by = '张杨' OR title = 'MongoDB 教程')'

> db.col.find({"likes": {$gt:50}, $or: [{"by": "张杨"},{"title": "MongoDB 教程"}]}).pretty()

blob.png

七、MongoDB条件操作符号

条件操作符用于比较两个表达式并从mongoDB集合中获取数据。

在本章节中,我们将讨论如何在MongoDB中使用条件操作符。

MongoDB中条件操作符有:

  • (>) 大于 - $gt

  • (<) 小于 - $lt

  • (>=) 大于等于 - $gte

  • (<= ) 小于等于 - $lte

我们使用的数据库名称为"youngcheng" 我们的集合名称为"col",以下为我们插入的数据。

为了方便测试,我们可以先使用以下命令清空集合 "col" 的数据:

db.col.remove({})

插入以下数据

db.col.insert({
    title: 'PHP 教程', 
    description: 'PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言。',
    by: '张杨',
    "url" : "http://www.osriy.com",
    tags: ['php'],
    likes: 200
})

db.col.insert({title: 'Java 教程', 
    description: 'Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言。',
    by: '张杨',
    "url" : "http://www.osriy.com",
    tags: ['java'],
    likes: 150
})

db.col.insert({title: 'MongoDB 教程', 
    description: 'MongoDB 是一个 Nosql 数据库',
    by: '张杨',
    "url" : "http://www.osriy.com",
    tags: ['mongodb'],
    likes: 100
})

使用find()命令查看数据:

blob.png

MongoDB (>) 大于操作符 - $gt

如果你想获取 "col" 集合中 "likes" 大于 100 的数据,你可以使用以下命令:

> db.col.find({"likes":{$gt:100}})

类似于SQL语句:

select * from col where likes > 100;

输出结果如下

blob.png

类似操作还有:

MongoDB(>=)大于等于操作符 - $gte

MongoDB (<) 小于操作符 - $lt

MongoDB (<=) 小于操作符 - $lte

MongoDB 使用 (<) 和 (>) 查询 - $lt 和 $gt

八、MongoDB $type操作符

$type操作符是基于BSON类型来检索集合中匹配的数据类型,并返回结果。

MongoDB 中可以使用的类型如下表所示:

类型数字备注
Double1
String2
Object3
Array4
Binary data5
Undefined6已废弃。
Object id7
Boolean8
Date9
Null10
Regular Expression11
JavaScript13
Symbol14
JavaScript (with scope)15
32-bit integer16
Timestamp17
64-bit integer18
Min key255Query with -1.
Max key127

我们使用的数据库名称为"youngcheung" 我们的集合名称为"col",以下为我们插入的数据。

简单的集合"col"(之前已经插入)

blob.pngMongoDB 操作符 - $type 实例

如果想获取 "col" 集合中 title 为 String 的数据,你可以使用以下命令:

> db.col.find({"title":{$type:2}})

输出结果如下:
blob.png


九、ongoDB Limit与Skip方法


ongoDB Limit方法:

如果你需要在MongoDB中读取指定数量的数据记录,可以使用MongoDB的Limit方法,limit()方法接受一个数字参数,该参数指定从MongoDB中读取的记录条数。

语法:

limit()方法基本语法如下所示:

>db.COLLECTION_NAME.find().limit(NUMBER)

示例:

集合 col 中的数据如下:blob.png

以上实例为查询文档中的两条数据

db.col.find({},{"title":1,_id:0}).limit(2)

blob.png

注:如果你们没有指定limit()方法中的参数则显示集合中的所有数据。

MongoDB Skip() 方法

们除了可以使用limit()方法来读取指定数量的数据外,还可以使用skip()方法来跳过指定数量的数据,skip方法同样接受一个数字参数作为跳过的记录条数。

语法:

skip() 方法脚本语法格式如下:

>db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)

示例:

> db.col.find({},{"title":1,_id:0}).limit(1).skip(1)
{ "title" : "Java 教程" }

注:skip()方法默认参数为 0 。

十、MongoDB 排序

在MongoDB中使用使用sort()方法对数据进行排序,sort()方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而-1是用于降序排列。

语法:

sort()方法基本语法如下所示:

>db.COLLECTION_NAME.find().sort({KEY:1})

示例:

col 集合中的数据如下:

blob.png

以下实例演示了 col 集合中的数据按字段 likes 的降序排列:

> db.col.find({},{"title":1,_id:0}).sort({"likes":-1}

结果如下:

blob.png

注: 如果没有指定sort()方法的排序方式,默认按照文档的升序排列。

十 一、MongoDB索引

        索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构

ensureIndex() 方法

MongoDB使用 ensureIndex() 方法来创建索引。

语法:

ensureIndex()方法基本语法格式如下所示:

>db.COLLECTION_NAME.ensureIndex({KEY:1})

语法中 Key 值为你要创建的索引字段,1为指定按升序创建索引,如果你想按降序来创建索引指定为-1即可。

示例:

>db.col.ensureIndex({"title":1})
>

结果如下:

blob.png

ensureIndex() 方法中你也可以设置使用多个字段创建索引(关系型数据库中称作复合索引)。

db.col.ensureIndex({"title":1})

blob.png

ensureIndex() 接收可选参数,可选参数列表如下:


ParameterTypeDescription
backgroundBoolean建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 "background" 可选参数。 "background" 默认值为false
uniqueBoolean建立的索引是否唯一。指定为true创建唯一索引。默认值为false.
namestring索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。
dropDupsBoolean在建立唯一索引时是否删除重复记录,指定 true 创建唯一索引。默认值为 false.
sparseBoolean对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false.
expireAfterSecondsinteger指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。
vindex version索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。
weightsdocument索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。
default_languagestring对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语
language_overridestring对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language.

示例:

在后台创建索引:

db.values.ensureIndex({open: 1, close: 1}, {background: true})

通过在创建索引时加background:true 的选项,让创建工作在后台执行

十二、MongoDB聚合

    MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。有点类似sql语句中的 count(*)。

aggregate() 方法

MongoDB中聚合的方法使用aggregate()。

语法:

aggregate() 方法的基本语法格式如下所示:

>db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)

示例:

集合中的数据如下:

插入语句:

db.col.insert({title: 'MongoDB Overview', 
    description: 'MongoDB is no sql database',
    by: '张杨',
    "url" : "http://www.osriy.com",
    tags: ['mongodb', 'database', 'NoSQL'],
    likes: 100
})
db.col.insert({title: 'NoSQL Overview', 
    description: 'No sql database is very fast',
     by_user: 'w3cschool.cc',
    "url" : "http://www.osriy.com",
    tags: ['mongodb', 'database', 'NoSQL'],
    likes: 10
})
db.col.insert({title: 'Neo4j Overview', 
    description: 'Neo4j is no sql database',
    by_user: 'Neo4j',
    "url" : "http://www.osriy.com",
    tags: ['neo4j', 'database', 'NoSQL'],
    likes: 750
})

结果如下:

blob.png

现在我们通过以上集合计算每个作者所写的文章数,使用aggregate()计算结果如下:

> db.col.aggregate([{$group : {_id : "$by", num_tutorial : {$sum : 1}}}])
{ "_id" : "张杨", "num_tutorial" : 3 }

以上实例类似sql语句: select by_user, count(*) from mycol group by by_user

在上面的例子中,我们通过字段by_user字段对数据进行分组,并计算by_user字段相同值的总和。

下表展示了一些聚合的表达式:

表达式描述实例
$sum计算总和。db.col.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}])
$avg计算平均值db.col.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}])
$min获取集合中所有文档对应值得最小值。db.col.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}])
$max获取集合中所有文档对应值得最大值。db.col.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}])
$push在结果文档中插入值到一个数组中。db.col.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}])
$addToSet在结果文档中插入值到一个数组中,但不创建副本。db.col.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}])
$first根据资源文档的排序获取第一个文档数据。db.col.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}])
$last根据资源文档的排序获取最后一个文档数据db.col.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}])

管道的概念:

管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的参数。

MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。

表达式:处理输入文档并输出。表达式是无状态的,只能用于计算当前聚合管道的文档,不能处理其它的文档。

这里我们介绍一下聚合框架中常用的几个操作:

  • $project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。

  • $match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。

  • $limit:用来限制MongoDB聚合管道返回的文档数。

  • $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。

  • $unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。

  • $group:将集合中的文档分组,可用于统计结果。

  • $sort:将输入文档排序后输出。

  • $geoNear:输出接近某一地理位置的有序文档。

示例:
1.$project

db.col.aggregate(
    { $project : {
        title : 1 ,
        author : 1 ,
    }}
 );

blob.png

这样的话结果中就只还有_id,tilte和author三个字段了,默认情况下_id字段是被包含的,如果要想不包含_id话可以这样:

db.col.aggregate(
    { $project : {
        _id : 0 ,
        title : 1 ,
        author : 1
    }});

blob.png

2.$match

db.col.aggregate( [
                        { $match : { score : { $gt : 70, $lte : 90 } } },
                        { $group: { _id: null, count: { $sum: 1 } } }
                       ] );

$match用于获取分数大于70小于或等于90记录,然后将符合条件的记录送到下一阶段$group管道操作符进行处理。

3.$skip

> db.col.aggregate(     { $skip : 2 })

经过$skip管道操作符处理后,前2个文档被"过滤"掉。

来源:MongoDB中文网

神回复

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。