Flag Counter
© 2017 Tao Peng. All rights reserved.

Mongodb入门(2) --- 常用操作


2016年02月28日

本篇博客主要记录Mongodb常用的一些操作,例如创建数据库,插入,查询数据等。


####1. 查询所有数据库 show dbs: 这条命令用于查询所有存在的数据库。
注意:mongo默认连接的数据库是test数据库,但是你发现在show dbs的时候并不能看到test,这是因为 没有数据的数据库是不会被真正创建的,如果你在test中插入一条数据,那么在show一次就可以了。


####2. 创建数据库 本质上来讲,Mongodb中并没有一条语句或者命令来专门创建数据库,当你使用一个数据库的时候,数据库就会被自动创建。
use dbname: use命令用于切换到dbname这个数据,当数据库不存在的时候,dbname的数据库会被创建(事实上现在还没有被创建,只有当有数据的时候才会被 真正创建); 如果数据库已经存在,那么就切换到当前数据库。


####3. 删除数据库 首先需要使用use切换到需要删除的数据库中,然后使用db.dropDatabase()删除当前数据库。


####4. 克隆/复制数据库 db.cloneDatabase(from_hostname): 从另一个服务器克隆当前选择的数据库,即将IP主机中的数据库克隆到当前主机选择的数据库。
db.copyDatabase(from_dbname, to_dbname, from_hostname): 将from_hostname中的from_dbname拷贝到本机的to_dbname库中。
如果复制源服务器需要验证,命令为: db.copyDatabase(from_dbname, to_dbname, from_hostname, username, password)


####5. 整理数据库 db.repairDatabase(): 能整理碎片并且还可以回收磁盘空间,对磁盘剩余空间需求很大。整理碎片能够提高性能,但是可能会存在一些坑,具体是什么 以后会介绍,慎用。


####6. 查看当前数据库 有两个简单命令可以查看,分别是: dbdb.getName()


####7. 查看数据库状态 db.stats(): 用于查看数据状态,能够得到的信息有:

> db.stats()
{
	"db" : "test2",
	"collections" : 0,
	"objects" : 0,
	"avgObjSize" : 0,
	"dataSize" : 0,
	"storageSize" : 0,
	"numExtents" : 0,
	"indexes" : 0,
	"indexSize" : 0,
	"fileSize" : 0,
	"ok" : 1
}


####8. 查看当前db版本, 查看当前db的连接机器地址 db.version(): 查看mongo版本
db.getMongo(): 查看当前连接的mongo主机


####9. 创建Collection #####方法一 : db.createCollection(name, {capped:<Boolean>, autoIndexId:<Boolean>, size:<number>, max:<number>}): 用于创建collection。下面看下参数:

  • name: Collection的名字。
  • capped: 是否启用集合限制,如果开启需要制定一个限制条件,默认为不启用,这个参数没有实际意义。
  • size: 限制Collection使用空间的大小,默认为没有限制。
  • max: Collection中最大条数限制,默认为没有限制。
  • autoIndexId: 是否使用_id作为索引,默认为true。

<font color=#0099ff>注意</font>: size的优先级比max要高, 即先考虑size条件, 然后考虑max条件。
最简单的创建方式是:

db.createCollection("c1")

上面创建的就是没有大小限制,默认使用_id的collection。

下面再看一条语句:

db.createCollection("c1", {autoIndexId:true, size:1024, max:1024})

上面创建了c1, _id被允许, 最大size是1M空间, 最大条数是1024。

#####方法二 : 使用insert方法, 向一个collection插入数据的时候,如果这个collection不存在,那么会自动创建这个collection。例如:

db.c.insert({name:"item1", age:10})


####10. 得到所有collection; 得到指定名称collection; 查看db所有collection状态 db.getCollectionNames(): 得到数据库中所有的collections。
db.getCollection("name"): 得到指定名称的collection。
db.printCollectionStats(): 显示当前db所有聚集索引的状态。


####11. 删除collection db.c.drop(): 本条语句将名称为c的collection删除。


####12. 查看collection基本信息 下面的代码有假设在people表中进行的,

  • 查询当前collection数据条数: db.people.count()
  • 查看当前collection状态: db.people.stats()
  • 查看当前collection所在的db: db.people.getDB()
  • 查询collection中的数据大小: db.people.dataSize()
  • 查询collection分配的空间大小,包括未使用的空间: db.people.storageSize()
  • 查询collection中索引数据大小: db.people.totalIndexSize()
  • 查询collection中索引 + 数据所占空间: db.people.totalSize()
  • 查询Shard版本信息: db.people.getShardVersion()


####13. 重命名collection db.people.renameCollection("user"): 将people重命名为user。


####14. 创建/查询/删除 索引

  • db.people.createIndex({name: 1}): 创建name增序索引。 也可以创建多个字段索引, 例如: db.people.createIndex({name: 1, age:-1}): 按照name增序以及age降序创建索引。 注意: 你也可以使用ensureIndex方法来创建索引, 但是官方建议大家使用createIndex方法。
  • db.people.getIndexes(): 查询当前collection中所有索引。下面看看输出结果:
[
	{
		"ns" : "test.people",
		"v" : 1,
		"key" : {
			"_id" : 1
		},
		"name" : "_id_"
	},
	{
		"v" : 1,
		"key" : {
			"age" : 1
		},
		"name" : "age_1",
		"ns" : "test.people"
	}
]

注意到里面有一个字段是name: 索引字段名称, 这个字段在删除索引时有用。
同时注意到, 默认会有一个_id的索引。
  • db.people.totalIndexSize(): 查询collection中总索引大小。
  • db.people.reIndex(): 查询当前collection所有index信息。
  • db.people.dropIndex("age_1"): 删除指定名称的索引。
  • db.people.dropIndexes(): 删除所有索引。


####15. collection查询 (🏁:重点)

涉及到下面一些语句/命令:

find, 比较语句例如$gt,$gte,$lt,$lte, ^/$, sort, limit, skip, $or, $and, count, $exists
  • db.people.find(): 查询people表中所有记录, 相当于SQL中select * from people。
  • db.people.find({name:"Andy"}): 查询name为Andy的记录, 不存在就返回空。
  • db.people.find({name:"Keth", age:20}): 查询name是Keth,并且age是20的记录。
  • db.people.find({age:{$gt:20, $lt:30}}): 查询age > 20 && age < 30的记录。
  • db.people.find({age:{$gte:20, $lte:30}}): 查询age >= 20 && age <= 30的记录。
  • db.people.find({name: /str/}): 查询name中包含str字符串的记录,相当于SQL中: select * from people where name like ‘%str%’;
  • db.people.find({name: /^str/}): 查询name以str开头的所有记录。
  • db.people.find({name: /str$/}): 查询name以str结尾的所有记录。
  • db.people.find({}, {name: 1, age: 1}): 返回指定字段数据, 此处仅仅返回name和age两个字段数据。 当然也可以加入限制条件,例如: db.people.find({age:{$gt:20, $lt:30}}, {name: 1, age: 1}),语句返回age > 20 && age < 30的记录中 name和age两个字段数据。
  • db.people.find().sort({name:1, age:-1}): 将查询的结果,首先按照name进行增序排序, 当name相同, 那么按照age进行降序排序。
  • db.people.find().limit(10): 返回结果的前10条数据。
  • db.people.find().skip(10): 跳过返回结果的前10条, 返回这10条之后的结果。
  • db.people.find().skip(3).limit(2).sort({name:-1}): 根据find的返回结果(find中加上一些条件也是可以的!), 首先将结果进行sort排序, 然后将排序后的结果skip前3条数据, 然后返回3条数据之后的数据, limit限制仅仅返回之后的2条数据。 注意语句的执行顺序!
  • db.people.find({$or: [{age:10}, {name:"Andy"}]}): 返回的结果是age=10或者name=”Andy”, 注意:$or后面必须是数组!即:[{…}, {…}, ]形式。
  • db.people.find({$and: [{age:10}, {name:"Andy"}]}): 返回的结果是age=10而且name=”Andy”, 注意:$and后面必须是数组!即:[{…}, {…}, ]形式。
  • db.people.findOne(): 返回第一条结果, 当然可以增加条件, 例如: db.people.findOne({age:10})返回age=10的第一条数据, findOne和limit(1)的性质是一样的。
  • db.people.find().count(): 返回结果数量。
  • db.people.find({age:{$exists:true}}): 返回记录中存在age字段的数据。
  • db.people.find({age:{$in: [10, 11]}}): 返回的是$in数组中存在的字段的数据。

还有很多其他的技巧, 请查看参考中的官网链接。


####16. collection 插入/修改/删除
#####<font color=#0099ff>插入数据</font> insert的基本语法如下:

db.collection.insert(
   <document or array of documents>,
   {
     writeConcern: <document>,
     ordered: <boolean>
   }
)

参数:

  • document: 例如: {name:”A”, age:20}。
  • writeConcern: 和写相关的一些选项, 例如一些特殊值, 或者写超时时间等, 具体见:Write concern
  • ordered: 在同时插入多条数据时, 如果此参数是true, 那么会按照数组中的顺序插入, 如果是false, 插入顺序不一定是数组中的顺序。 需要注意的是: 在插入多条数组中, 一旦出现错误, 如果ordered=true,后面所有没有插入的记录都不会被插入; 如果ordered=false,剩下的记录还会被处理。 默认情况下: ordered=true。
**注意**

:

  • insert插入到一个不存在的collection中的时候, 会自动创建这个collection。
  • 我们可以自行插入_id字段, 注意不可以出现重复字段。如果你自己不插入, 那么系统会默认进行分配这个字段。

下面看一些实例:

  • db.people.insert( { name:"Andy", age:20 } ): 这是最简单的插入方法, 系统会自动创建_id字段。
  • db.people.insert( { _id:1, name:"Andy", age:20 } ): 本条语句中自行增加了_id字段, 你需要自己管理, 不允许_id重复。
  • 下面看同时插入多个情况:
db.people.insert(
       [
           { _id: 1, name: "Andy", age: 50, gender: "male" },
           { name: "Keth", age: 20 },
           { name: "Jim", age: 25 }
       ]
      )

上面就是插入多个数据情况,注意参数必须是数组形式。上面代码的执行结果如下:

{ "_id" : 1, name: "Andy", age: 50, gender: "male" }
{ "_id" : ObjectId("51e0373c6f35bd826f47e9a0"), name: "Keth", age: 20 }
{ "_id" : ObjectId("51e0373c6f35bd826f47e9a1"), name: "Jim", age: 25 }

第一条记录的_id是自己指定的, 后面两条是系统分类的。

  • 在默认情况下, ordered=true,所以上面的多条插入是有序插入,如果想要无序插入,那么可以如下:
db.people.insert(
       [
           { _id: 1, name: "Andy", age: 50, gender: "male" },
           { name: "Keth", age: 20 },
           { name: "Jim", age: 25 }
       ],
       { ordered: false }
      )


#####<font color=#0099ff>修改数据</font> update基本语法如下:

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

参数:

  • query: 代表需要筛选出来的数据条件, 即查询条件。
  • update: 代表更新的数据。
  • upsert: 可选参数, 如果=true, 那么当query没有匹配到文档的时候, 会将更新的数据作为新的数据插入到collection中; 如果=false,则不会。默认是false。
  • multi: 可选参数, 如果=true, 那么会将query匹配到的所有文档都进行更新; 如果=false, 则只更新第一条匹配到的文档。默认是false。
  • writeConcern: 之前在insert已经说过。

<font color=#0099ff>注意:</font> update中只能是和修改相关的操作,例如$set, $inc等。 详细请见: Update Operators

下面看一些实例:

  • db.people.update({age:21}, {$set:{gender:"0",age:11}}): 查询所有的age=21的人,并将这些人的gender设置为0, 将age设置为11。

<font color=#0099ff>注意:</font> 系统默认的multi=false,所以即使是匹配到多条数据,也只会更新第一条,后面的不会被更新,如果想要改变所有 的数据,那么需要将multi设置为true, 如下面代码所示: db.people.update({age:21}, {$set:{gender:"0",age:11}}, {multi:true}), 那么 所有符合条件的记录都会被改变。

  • db.people.update({age:11}, {$set:{gender:"0", addr:"XXX"}, $inc:{age:10}}): 同时执行多个更新操作, 只需要增加相应的操作即可。 上面的语句将符合条件的第一条数据,设置gender和addr,并将age+10。
  • db.people.update({age:12}, {$set:{gender:"0"}, $inc:{age:10}}): 如果数据库中没有age=12的语句, 那么这句是不会执行的。如果需要执行 此语句, 那么需要将upsert设置为true(默认是false)。所以可以改成: db.people.update({age:12}, {$set:{gender:"0"}, $inc:{age:10}}, {upsert:true}), 当查询结果不存在,就会先根据query插入本条数据,然后根据update进行修改更新数据。


#####<font color=#0099ff>删除数据</font> remove比较简单, 基本语法如下:

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

参数:

  • query: 查询条件
  • justOne: 是否只删除一条数据。 =true就是只删除返回的第一条数据; =false就是删除返回的所有数据。默认是false,即删除所有返回数据。

下面看一些实例:

  • db.people.remove( {} ): 删除people所有的数据。
  • db.people.remove( {age:11} ): 删除age=11的所有数据。如果仅仅想删除一条数据,那么可以写成: db.people.remove( {age:11}, {justOne:true} )


#####<font color=#0099ff>其他一些有用的语句</font> 1).save语句:

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

save语句执行insert和update。如果save执行体中没有_id,那么执行的就是insert操作。如果存在_id,那么执行的是update操作。 需要注意:如果_id代表的数据在表中不存在,那么数据会被插入。这是why?因为save执行的update操作中的参数upsert是true。

下面看一些实例:

  • db.people.save( { name: "Andy", age: 40 } ): 没有_id,那么执行的是insert操作,返回的结果是: { “_id” : ObjectId(“50691737d386d8fadbd6b01d”), name: “Andy”, age: 40 }。
  • db.people.save( { _id:1, name: "Andy", age: 40 } ): 存在_id, 那么执行的是update操作, 假设现在表中 不存在_id=1的数据,那么由于upsert=true,就会插入数据,所以结果是: { _id:1, name: “Andy”, age: 40 }。 现在重新执行 db.people.save( { _id:1, name: "Keth", age: 60 } ), 由于存在_id=1数据, 那么原始的数据会被{ _id:1, name: “Keth”, age: 60 } 代替。

2). findAndModify语句

db.collection.findAndModify({
    query: <document>,
    sort: <document>,
    remove: <boolean>,
    update: <document>,
    new: <boolean>,
    fields: <document>,
    upsert: <boolean>,
    bypassDocumentValidation: <boolean>,
    writeConcern: <document>
});

这条语句基本功能是修改并返回一个记录, 默认是返回修改前的记录, 如果想要返回修改后的记录, 将new参数设为true就OK。 <font color=#0099ff>注意:</font> findAndModify只会处理匹配到的一条记录。

参数:

  • query: 匹配条件, 注意:即使query匹配返回多条数据,findAndModify只会处理匹配到的一条记录。
  • sort: 可以将返回的多条数据按照XX进行排序,findAndModify会处理sort后的第一条数据。
  • remove: 如果设置为true,那么需要将返回的数据删除。注意不可以和update同时设定,否则会报错。默认是false。
  • update: 将query返回的数据进行更新。不可以和remove=true同时设定。
  • new: 如果为true,返回的是update之后的记录,否则返回修改前的记录。默认是false。
  • fields: 指定返回哪些字段, 基本格式是: fields: {name:1, age:1, …}。默认返回所有字段。
  • upsert: 用于update没有匹配到的时候,如果true,那么插入。默认是false。
  • bypassDocumentValidation: 是否绕过文档合法性验证。

下面看一些实例:

  • 1.
db.people.findAndModify({
     query: { name: "Andy" },
     sort: { age: 1 },
     update: { $inc: { age: 1 } },
     upsert: true,
     new: true
 })

上面一段代码查询name=”Andy”的所有数据,并按照age增序排序返回结果,findAndModify取得第一条数据, 并将其update一下,即将age+1,如果query数据不存在,那么由于upsert=true,所有数据会被插入,最终数据 被返回,并且返回的是最新的数据,因为new=true。

  • 2.
db.people.findAndModify({
     query: { name: "Andy" },
     remove: true
 })

上面的代码将query到的结果中一条进行删除。

还有很有有用的语句请到官网查看,自己也会慢慢使用,积累。


####参考:
Collection Methods(对表的操作)
mongo Shell Methods(所有mongo shell方法)