MongoDB 指令

萌亖 2020-07-27

创建数据库
> use test1
> #直接使用use指令切换数据库即可,但是由于库中没有数据,所以并不会显示在数据库列表中。

查看当前所在库

> db
test1

查看所有库

> show dbs        # 并不会看到刚才所创建的test1库
admin   0.000GB   # 类似于mysql中的mysql库
config  0.000GB    # 类似于mysql中的
local   0.000GB      # 类似于MySQL中的informa库

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

> db.test1.insert( {"name":"张三"} )
> show dbs      # 当新的数据库中有数据后,即可查看到库
admin   0.000GB
config  0.000GB
local   0.000GB
test1   0.000GB

注:默认登录到mongodb是在test库,如果没有创建新的数据库,集合将存放在test数据库中。在mongodb中,集合只有在内容插入后才会创建,也就是说,创建集合(数据表)后要再插入一个文档(记录),集合才会真正创建。
删除数据库

> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
test1   0.000GB
> db
test1
> db.dropDatabase()      # 想要删除某个数据库,进入到那个库,执行该指令即可删除
{ "dropped" : "test1", "ok" : 1 }
> show dbs     # 确认数据库test1被删除
admin   0.000GB
config  0.000GB
local   0.000GB

创建集合
创建集合的语法格式如下:

db.createCollection(name, options)

参数说明:
name:要创建的集合名称。
options:可选参数,指定有关内存大小及索引的选项

options可以是如下参数:

字段类型描述
capped布尔(可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。当该值为 true 时,必须指定 size 参数。
autoIndexId布尔(可选)如为 true,自动在 _id 字段创建索引。默认为 false。
size数值(可选)为固定集合指定一个最大值,以千字节计(KB)。如果 capped 为 true,也需要指定该字段。
max数值(可选)指定固定集合中包含文档的最大数量。

在插入文档时,MongoDB 首先检查固定集合的 size 字段,然后检查 max 字段。

> db.createCollection("ray")        # 创建集合
# show collections或show tables指令都可以查看到已有集合
> show collections
ray
test1
> show tables
ray
test1

带关键参数的创建集合语法

# 创建固定集合 mycol,整个集合空间大小 6142800 KB, 文档最大个数为 5 个。
> db.createCollection("mycol",{capped: true,autoIndexId: true,size:6142800,max:5})
# 当执行该指令后,会提示autoIndexId已经被弃用(它会自动创建索引),但集合依旧创建成功了
# 我设置了最大文档数为5个,是想测试下如果有5个文档后,再继续插入,会怎样?
> db.mycol.insert( {"name":"张笑笑"} )
WriteResult({ "nInserted" : 1 })
> db.mycol.insert({"name1":"张笑笑1"})
WriteResult({ "nInserted" : 1 })
> db.mycol.insert({"name2":"张笑笑2"})
WriteResult({ "nInserted" : 1 })
> db.mycol.insert({"name3":"张笑笑3"})
WriteResult({ "nInserted" : 1 })
> db.mycol.find()     # 查看现有的文档
{ "_id" : ObjectId("5e73967dbd4667d1d9261ccc"), "name" : "张笑笑" }
{ "_id" : ObjectId("5e73968ebd4667d1d9261ccd"), "name1" : "张笑笑1" }
{ "_id" : ObjectId("5e739699bd4667d1d9261cce"), "name2" : "张笑笑2" }
{ "_id" : ObjectId("5e7396a0bd4667d1d9261ccf"), "name3" : "张笑笑3" }
# 继续插入文档
> db.mycol.insert({"name4":"张笑笑4"})
WriteResult({ "nInserted" : 1 })
> db.mycol.insert({"name5":"张笑笑5"})
WriteResult({ "nInserted" : 1 })
> db.mycol.find()      # 会发现,当文档数超过定义的max值,就会覆盖掉最旧的数据,也就是插入的第一条数据
{ "_id" : ObjectId("5e73968ebd4667d1d9261ccd"), "name1" : "张笑笑1" }
{ "_id" : ObjectId("5e739699bd4667d1d9261cce"), "name2" : "张笑笑2" }
{ "_id" : ObjectId("5e7396a0bd4667d1d9261ccf"), "name3" : "张笑笑" }
{ "_id" : ObjectId("5e7396d5bd4667d1d9261cd0"), "name4" : "张笑笑" }
{ "_id" : ObjectId("5e7396e1bd4667d1d9261cd1"), "name5" : "张笑笑5" }

在mongodb中,我们不需要创建集合,当我们插入一些文档时,mongodb会自动创建集合,如下:

> db.mycol2.insert({"name":"I need a job"})    # 插入数据
WriteResult({ "nInserted" : 1 })
> show collections     # 查看集合
mycol2
> db.mycol2.find()    # 查看集合内容
{ "_id" : ObjectId("5e7434b7fc41de8da910239c"), "name" : "I need a job" }

mongodb删除集合
语法格式如下:

> db.collection.drop()

返回值:
如果成功删除选定集合,则drop()方法返回true,否则返回false
示例:

> show collections    # 查看当前集合
mycol2
> db.mycol2.drop()    # 删除集合
true
> show collections     # 再次查看就没有集合了

插入文档
语法:

db.COLLECTION_NAME.insert(document)

示例:
插入文档第一种方法
第一种方法是直接插入文档

> db.col.insert( { title: "学习mongodb的第二天",
... description: "mongodb是一个nosql数据库",
... by: "网上文档",
... url: "cn.bing.com",
... tags: [‘mongodb‘,‘nosql‘,‘databases‘],
... likes: 100
... } )
> db.col.find()    # 查看col集合中的文档如下
{ "_id" : ObjectId("5e7438d8fc41de8da910239d"), "title" : "学习mongodb的第二天", "description" : "mongodb是一个nosql数据库", "by" : "网上文档", "url" : "cn.bing.com", "tags" : [ "mongodb", "nosql", "databases" ], "likes" : 100 }

插入文档第二种方法
第二种方式是将文档定义为变量再进行插入

# 定义变量document
> document=({title: ‘MongoDB‘, 
... description: ‘MongoDB 是一个 Nosql 数据库‘,
... by: ‘cainiao‘,
... url: ‘http://cn.bing.com‘,
... tags: [‘mongodb‘, ‘database‘, ‘NoSQL‘],
... likes: 100
... });

# 执行插入操作

> db.mycol.insert(document)
# 查看插入后的文档数据
> db.mycol.find()
{ "_id" : ObjectId("5e743a2ffc41de8da910239e"), "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }

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

更新文档数据
update()方法

update()方法用于更新已存在的文档,语法:

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

参数说明:

  • query:update的查询条件,类似于sql查询定义的where条件。
  • update:updat的对象和一些更新的操作符(如$,$inc…)等,也可以理解为sql查询set指令定义的。
  • upsert: 可选参数,作用:如果不存在update的记录,是否插入为新的对象,true为插入,默认为false,不插入。
  • multi:可选,mongodb默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查找的多条记录全部更新。
  • writeconcern:可选,抛出异常的级别。

示例:

> db.col.find()   # 查看集合现有内容
{ "_id" : ObjectId("5e7438d8fc41de8da910239d"), "title" : "学习mongodb的第二天", "description" : "mongodb是一个nosql数据库", "by" : "网上文档", "url" : "cn.bing.com", "tags" : [ "mongodb", "nosql", "databases" ], "likes" : 100 }
# 执行更新操作
> db.col.update( {‘title‘: ‘学习mongodb的第二天‘},{$set:{‘title‘:‘mongodb‘}})
> db.col.find()    # 更新内容成功
{ "_id" : ObjectId("5e7438d8fc41de8da910239d"), "title" : "mongodb", "description" : "mongodb是一个nosql数据库", "by" : "网上文档", "url" : "cn.bing.com", "tags" : [ "mongodb", "nosql", "databases" ], "likes" : 100 }

可以看到title由原来的’学习mongodb的第二天’更新为’mongodb’。
以上语句只会修改第一条发现的文档,如果要修改多条相同的文档,则需要设置multi参数为true。如下:

db.col.update( {‘title‘: ‘学习mongodb的第二天‘},{$set:{‘title‘:‘mongodb‘}},{multi:true})

更多实例
只更新第一条记录:

# 条件为:count字段的值大于1,就将test2字段更新为ok,默认只更新匹配到的第一条
db.col.update( { "count" : { $gt : 1 } } , { $set : { "test2" : "OK"} } );

全部更新:

# 条件为:count字段的值大于1,就将test2字段更新为ok,第一个false为upsert的值参数,第二个true为multi的取值参数。
db.col.update( { "count" : { $gt : 3 } } , { $set : { "test2" : "OK"} },false,true );

后面的参考前面的解释即可。关键点也就是在于后面两条true和false的取值。
只添加第一条:

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 );

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

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

参数说明:

  • document:文档数据。
  • writeConcern:可选,抛出异常的级别。

示例:

> db.col.find()    # 查看现有数据
{ "_id" : ObjectId("5e7438d8fc41de8da910239d"), "title" : "mongodb", "description" : "mongodb是一个nosql数据库", "by" : "网上文档", "url" : "cn.bing.com", "tags" : [ "mongodb", "nosql", "databases" ], "likes" : 100 }
# 使用save更新数据
> db.col.find()    # id号必须和现有的id号一致,否则会生成新的文档,而不是更新文档
{ "_id" : ObjectId("5e7438d8fc41de8da910239d"), "title" : "MongoDB", "description" : "mongodb shi yi ge nosql databases", "by" : "runoob", "url" : "http://cn.bing.com", "tags" : [ "mongo", "nosql" ], "like" : 110 }

# 查看更新后的数据
> db.col.find()
{ "_id" : ObjectId("5e7438d8fc41de8da910239d"), "title" : "MongoDB", "description" : "mongodb shi yi ge nosql databases", "by" : "runoob", "url" : "http://cn.bing.com", "tags" : [ "mongo", "nosql" ], "like" : 110 }

删除文档
remove方法

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

参数说明:

  • query:可选,删除文档的条件。
  • justone:可选,如果设为true或1,则只删除1个文档,如果不设置该参数,或使用默认值false,则删除所有匹配条件的文档。
  • writeConcern:可选,抛出异常的级别。

示例:

> db.col.find()     # 查询现有文档
{ "_id" : ObjectId("5e7438d8fc41de8da910239d"), "title" : "MongoDB", "description" : "mongodb shi yi ge nosql databases", "by" : "runoob", "url" : "http://cn.bing.com", "tags" : [ "mongo", "nosql" ], "like" : 110 }
{ "_id" : ObjectId("7f8538d8fc41de8da910239d"), "title" : "MongoDB", "description" : "mongodb shi yi ge nosql databases", "by" : "runoob", "url" : "http://cn.bing.com", "tags" : [ "mongo", "nosql" ], "like" : 110 }
# 删除title为MongoDB的文档:
> db.col.remove( {‘title‘:‘MongoDB‘} )
WriteResult({ "nRemoved" : 2 })   # 返回结果显示删除了两条数据
> db.col.find()    # 再次查看已经没有数据了
# 如果只想是删除第一条找到的记录,可以设置 justOne 为 1,如下:
# 删除title为MongoDB的文档,只删除匹配到的第一个文档:
> db.col.remove( {‘title‘:‘MongoDB‘},1 )
# 如果想要删除所有数据,可以使用以下方式(类似sql中的truncate指令)。
> db.col.remove({}

deleteOne() 和 deleteMany()
不过mongodb经过这么长时间的发展,remove()方法已经过时了,现在官方推荐 deleteOne() 和 deleteMany() 方法。
示例:
注:下面示例中的col是集合名称。

# 删除links等于100的文档
> db.col.deleteOne({likes: 100})
# 删除集合下全部文档
> db.col.deleteMany({})
{ "acknowledged" : true, "deletedCount" : 2 }

查询文档
语法格式:

db.collection.find(query, projection).pretty()

选项说明:

  • query:可选,使用查询操作符指定查询条件。
  • projection:可选,使用投影操作符指定返回的值,查询时返回文档中所有键值,只需神略该参数即可(默认省略).
  • pretty():以易读的方式来读取数据。

示例:

> db.my.find().pretty()    # 以人性化的方式输出my集合中的文档
{
    "_id" : ObjectId("5e75929087edb46897838e76"),
    "title" : "MongoDB",
    "description" : "MongoDB 是一个 Nosql 数据库",
    "by" : "cainiao",
    "url" : "http://cn.bing.com",
    "tags" : [
        "mongodb",
        "database",
        "NoSQL"
    ],
    "likes" : 100
}

mongodb与sql的where语句比较

操作格式范例sql中的类似语句
等于{:}db.col.find({“by”:”cainiao”}).pretty()where by = ‘菜鸟教程’
小于{:{$lt:}}db.col.find({“likes”:{$lt:50}}).pretty()where likes < 50
小于或等于{:{$lte:}}db.col.find({“likes”:{$lte:50}}).pretty()where likes <= 50
大于{:{$gt:}}db.col.find({“likes”:{$gt:50}}).pretty()where likes > 50
大于或等于{:{$gte:}}db.col.find({“likes”:{$gte:50}}).pretty()where likes >= 50
不等于{:{$ne:}}db.col.find({“likes”:{$ne:50}}).pretty()where likes != 50

mongodb and 条件
语法格式如下:

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

在花括号{ }中传入多个key,每个key以逗号隔开,就是and条件。
如下:

# 查找likes值为110并且by的值为cainiao的文档。
> db.my.find({"likes":110,"by":"cainiao"}).pretty()    
{
    "_id" : ObjectId("5e75932387edb46897838e77"),
    "title" : "Mongodb",
    "description" : "MongoDB是一个 Nosql数据库",
    "by" : "cainiao",
    "url" : "cn.bing.com",
    "tags" : [
        "mongodb",
        "database",
        "NoSQL"
    ],
    "likes" : 110
}
# 以上的语句类似于sql中的“where likes=110 and by=‘cainiao‘”。

mongodb or条件

or条件为或关系,语法格式:
>db.col.find(
   {
      $or: [
         {key1: value1}, {key2:value2}
      ]
   }
).pretty()

示例:

# 查看文档中likes值为110或者by的值为“cainiao”的文档。
> db.my.find( {  $or:[  {"likes":110},{"by":"cainiao"}  ] } ).pretty()
{
    "_id" : ObjectId("5e75929087edb46897838e76"),
    "title" : "MongoDB",
    "description" : "MongoDB 是一个 Nosql 数据库",
    "by" : "cainiao",
    "url" : "http://cn.bing.com",
    "tags" : [
        "mongodb",
        "database",
        "NoSQL"
    ],
    "likes" : 100
}
{
    "_id" : ObjectId("5e75932387edb46897838e77"),
    "title" : "Mongodb",
    "description" : "MongoDB是一个 Nosql数据库",
    "by" : "cainiao",
    "url" : "cn.bing.com",
    "tags" : [
        "mongodb",
        "database",
        "NoSQL"
    ],
    "likes" : 110
}

and和or联合使用
以下示例类似于sql语句中的:“where likes>100 and (by=’cainiao’ or by = ‘ray’)”

# 查找likes值大于100并且by的值为cainiao或者ray。
> db.my.find({‘likes‘:{$gt:100}, $or:[ {"by":"cainiao"},{"by":"ray"}]}).pretty()
{
    "_id" : ObjectId("5e75932387edb46897838e77"),
    "title" : "Mongodb",
    "description" : "MongoDB是一个 Nosql数据库",
    "by" : "cainiao",
    "url" : "cn.bing.com",
    "tags" : [
        "mongodb",
        "database",
        "NoSQL"
    ],
    "likes" : 110
}
{
    "_id" : ObjectId("5e75933987edb46897838e78"),
    "title" : "Mongodb",
    "description" : "MongoDB是一个 Nosql数据库",
    "by" : "ray",
    "url" : "cn.bing.com",
    "tags" : [
        "mongodb",
        "database",
        "NoSQL"
    ],
    "likes" : 150
}

mongodb排序
在mongodb中使用sort()方法对数据进行排序,sort()方法可以通过参数指定排序的字段,并且使用1(升序)和-1(降序)来指定排序的方式。
语法格式:

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

示例:

# 查询列表中的数据如下:
> db.my.find()
{ "_id" : ObjectId("5e75929087edb46897838e76"), "title" : "MongoDB", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "cainiao", "url" : "http://cn.bing.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }
{ "_id" : ObjectId("5e75932387edb46897838e77"), "title" : "Mongodb", "description" : "MongoDB是一个 Nosql数据库", "by" : "cainiao", "url" : "cn.bing.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 110 }
{ "_id" : ObjectId("5e75933987edb46897838e78"), "title" : "Mongodb", "description" : "MongoDB是一个 Nosql数据库", "by" : "ray", "url" : "cn.bing.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 150 }
{ "_id" : ObjectId("5e75a81e87edb46897838e79"), "title" : "Mongodb", "description" : "MongoDB是一个 Nosql数据库", "by" : "ray", "url" : "cn.bing.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 88 }

# 以升序来进行排序
> db.my.find().sort({"likes":1}).pretty()
{
    "_id" : ObjectId("5e75a81e87edb46897838e79"),
    "title" : "Mongodb",
    "description" : "MongoDB是一个 Nosql数据库",
    "by" : "ray",
    "url" : "cn.bing.com",
    "tags" : [
        "mongodb",
        "database",
        "NoSQL"
    ],
    "likes" : 88
}
{
    "_id" : ObjectId("5e75929087edb46897838e76"),
    "title" : "MongoDB",
    "description" : "MongoDB 是一个 Nosql 数据库",
    "by" : "cainiao",
    "url" : "http://cn.bing.com",
    "tags" : [
        "mongodb",
        "database",
        "NoSQL"
    ],
    "likes" : 100
}
{
    "_id" : ObjectId("5e75932387edb46897838e77"),
    "title" : "Mongodb",
    "description" : "MongoDB是一个 Nosql数据库",
    "by" : "cainiao",
    "url" : "cn.bing.com",
    "tags" : [
        "mongodb",
        "database",
        "NoSQL"
    ],
    "likes" : 110
}
{
    "_id" : ObjectId("5e75933987edb46897838e78"),
    "title" : "Mongodb",
    "description" : "MongoDB是一个 Nosql数据库",
    "by" : "ray",
    "url" : "cn.bing.com",
    "tags" : [
        "mongodb",
        "database",
        "NoSQL"
    ],
    "likes" : 150
}

# 以降序来进行排序
> db.my.find().sort({"likes":-1}).pretty()
{
    "_id" : ObjectId("5e75933987edb46897838e78"),
    "title" : "Mongodb",
    "description" : "MongoDB是一个 Nosql数据库",
    "by" : "ray",
    "url" : "cn.bing.com",
    "tags" : [
        "mongodb",
        "database",
        "NoSQL"
    ],
    "likes" : 150
}
{
    "_id" : ObjectId("5e75932387edb46897838e77"),
    "title" : "Mongodb",
    "description" : "MongoDB是一个 Nosql数据库",
    "by" : "cainiao",
    "url" : "cn.bing.com",
    "tags" : [
        "mongodb",
        "database",
        "NoSQL"
    ],
    "likes" : 110
}
{
    "_id" : ObjectId("5e75929087edb46897838e76"),
    "title" : "MongoDB",
    "description" : "MongoDB 是一个 Nosql 数据库",
    "by" : "cainiao",
    "url" : "http://cn.bing.com",
    "tags" : [
        "mongodb",
        "database",
        "NoSQL"
    ],
    "likes" : 100
}
{
    "_id" : ObjectId("5e75a81e87edb46897838e79"),
    "title" : "Mongodb",
    "description" : "MongoDB是一个 Nosql数据库",
    "by" : "ray",
    "url" : "cn.bing.com",
    "tags" : [
        "mongodb",
        "database",
        "NoSQL"
    ],
    "likes" : 88
}

mongodb索引
索引相当于书籍中的目录,如果没有索引,mongodb在读取数据时必须扫描集合中的每个文档并选取那些符合查询条件的记录。

这种扫描全集合的查询效率不但浪费系统的资源,而且效率低下,特别是在处理大量的数据时,查询可能要花费几十秒甚至几分钟,这是致命的问题。

索引是一种特殊的数据结构,它存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构。
语法
createIndex()方法基本语法格式如下:

>db.collection.createIndex(keys, options)

语法中 Key 值为要创建的索引字段,1为指定按升序创建索引,-1则为降序创建索引。
示例:

> db.my.createIndex({"title":1})

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

> db.my.createIndex({"by":1,"likes":-1})

createIndex()接受可选参数,可选参数列表如下:

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

示例:

# 后台创建复合索引。
> db.my.createIndex({"name":1,"url":1},{background: true})

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

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

>db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)

示例:

集合中的数据如下:

> db.data.find().pretty()
{
    "_id" : ObjectId("5e75b50287edb46897838e7a"),
    "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" : ObjectId("5e75b50287edb46897838e7b"),
    "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" : ObjectId("5e75b50287edb46897838e7c"),
    "title" : "Neo4j Overview",
    "description" : "Neo4j is no sql database",
    "by_user" : "Neo4j",
    "url" : "http://www.neo4j.com",
    "tags" : [
        "neo4j",
        "database",
        "NoSQL"
    ],
    "likes" : 750
}

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

# 注:下面的_id为固定字段。

> db.data.aggregate([{$group:{_id:"$by_user",numbser:{$sum:1}}}])
{ "_id" : "runoob.com", "numbser" : 2 }    # 作者为runoob.com的文章数为2
{ "_id" : "Neo4j", "numbser" : 1 }   # 作者为neo4j的文章数为1

在上面的例子中,通过字段 by_user 字段对数据进行分组,并计算 by_user 字段相同值的总和。
上述示例中类似于sql语句:

select by_user, count(*) from mycol group by by_user

下面是一些常见的聚合表达式:

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

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

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

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

聚合框架中常用的几个操作:

  • $project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
  • $match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
  • $limit:用来限制MongoDB聚合管道返回的文档数。
  • $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
  • $unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
  • $group:将集合中的文档分组,可用于统计结果。
  • $sort:将输入文档排序后输出。
  • $geoNear:输出接近某一地理位置的有序文档。

示例:
$project

#
> db.data.aggregate({$project:{title:1,by_user:1,}}).pretty()
{
    "_id" : ObjectId("5e75b50287edb46897838e7a"),
    "title" : "MongoDB Overview",
    "by_user" : "runoob.com"
}
{
    "_id" : ObjectId("5e75b50287edb46897838e7b"),
    "title" : "NoSQL Overview",
    "by_user" : "runoob.com"
}
{
    "_id" : ObjectId("5e75b50287edb46897838e7c"),
    "title" : "Neo4j Overview",
    "by_user" : "Neo4j"
}
# 经过$project管道操作,结果中就只有"_id"、"title"、"by_user"三个字段了(默认包含_id字段)。
# 如果不想包含_id字段可以这样:
> db.data.aggregate({$project:{_id:0,title:1,by_user:1}})
{ "title" : "MongoDB Overview", "by_user" : "runoob.com" }
{ "title" : "NoSQL Overview", "by_user" : "runoob.com" }
{ "title" : "Neo4j Overview", "by_user" : "Neo4j" }

$match
data集合数据如下:

> db.data.find()    # 查看现有数据
{ "_id" : ObjectId("5e75b50287edb46897838e7a"), "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" : ObjectId("5e75b50287edb46897838e7b"), "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" : ObjectId("5e75b50287edb46897838e7c"), "title" : "Neo4j Overview", "description" : "Neo4j is no sql database", "by_user" : "Neo4j", "url" : "http://www.neo4j.com", "tags" : [ "neo4j", "database", "NoSQL" ], "likes" : 750 }

$skip示例

> db.data.aggregate({$skip:2}).pretty()   # 跳过集合中的前两个文档,然后开始输出
{
    "_id" : ObjectId("5e75b50287edb46897838e7c"),
    "title" : "Neo4j Overview",
    "description" : "Neo4j is no sql database",
    "by_user" : "Neo4j",
    "url" : "http://www.neo4j.com",
    "tags" : [
        "neo4j",
        "database",
        "NoSQL"
    ],
    "likes" : 750
}

经过$skip管道操作符处理后,前2个文档被”过滤”掉。
$limit示例
$limit用于限制返回的文档数

> db.data.aggregate({$limit:2}).pretty()        # 限制的值为2,所以只能返回2个文档内容。
{
    "_id" : ObjectId("5e75b50287edb46897838e7a"),
    "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" : ObjectId("5e75b50287edb46897838e7b"),
    "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
}

相关推荐