MangoDB创建、更新、删除文档

来源:互联网 发布:linux命令大全txt下载 编辑:程序博客网 时间:2024/06/06 19:25

1.插入并保存文档

插入是MongoDB中的最基本的方法,那往一个集合中插入数据:

Microsoft Windows XP [版本 5.1.2600](C) 版权所有 1985-2001 Microsoft Corp.C:\Documents and Settings\Administrator>E:E:\>cd MongoDBE:\MongoDB>mongo.exeMongoDB shell version: 2.0.2connecting to: test> use php  //选择php数据库switched to db php> show collections //查看phps数据库中有哪些集合。blogsystem.indexes> db.blog.insert({"title":"okokok","content":"123456","time":"2011023023","comments":"23224"}) //选择blog集合。并插入数据。> db.blog.find() //查看blog集合下所有的文档,已经插入成功。{ "_id" : ObjectId("4f0bc1245a5904bae2b767a8"), "title" : "wowowowo", "content": "hahahahah", "time" : ISODate("2012-01-10T03:38:45.515Z") }{ "_id" : ObjectId("4f0bc11d5a5904bae2b767a7"), "title" : "wowowowo", "content": "hahahahah", "time" : ISODate("2012-01-10T03:38:45.515Z"), "comments" : "hao a hao a " }{ "_id" : ObjectId("4f0cf96bbc8c53013bb90682"), "title" : "okokok", "content" :"123456", "time" : "2011023023", "comments" : "23224" }>

在一个特定集合内部,需要唯一的标识文档。因此MongoDB中存储的文档都由一个"_id"键,用于完成此功能。这个键的值可以是任意类型的,默认试ObjectId对象。ObjectId对象的生成思路是本文的主题,也是很多分布式系统可以借鉴的思路。

为了考虑分布式,“_id”要求不同的机器都能用全局唯一的同种方法方便的生成它。因此不能使用自增主键(需要多台服务器进行同步,既费时又费力),因此选用了生成ObjectId对象的方法。

ObjectId使用12字节的存储空间,其生成方式如下:

|0|1|2|3|4|5|6 |7|8|9|10|11|

|时间戳  |机器ID|PID|计数器   |

前四个字节时间戳是从标准纪元开始的时间戳,单位为秒,有如下特性:

  1. 时间戳与后边5个字节一块,保证秒级别的唯一性;
  2. 保证插入顺序大致按时间排序;
  3. 隐含了文档创建时间;

时间戳的实际值并不重要,不需要对服务器之间的时间进行同步(因为加上机器ID和进程ID已保证此值唯一,唯一性是ObjectId的最终诉求)。

机器ID是服务器主机标识,通常是机器主机名的散列值。

同一台机器上可以运行多个mongod实例,因此也需要加入进程标识符PID。

前9个字节保证了同一秒钟不同机器不同进程产生的ObjectId的唯一性。后三个字节是一个自动增加的计数器(一个mongod进程需要一个全局的计数器),保证同一秒的ObjectId是唯一的。同一秒钟最多允许每个进程拥有(256^3 = 16777216)个不同的ObjectId。

总结一下:时间戳保证秒级唯一,机器ID保证设计时考虑分布式,避免时钟同步,PID保证同一台服务器运行多个mongod实例时的唯一性,最后的计数器保证同一秒内的唯一性(选用几个字节既要考虑存储的经济性,也要考虑并发性能的上限)。"_id"既可以在服务器端生成也可以在客户端生成,在客户端生成可以降低服务器端的压力。

2.更新文档

在MongoDB中更新文档采用db.php.update( )。update有两个参数,第一个参数是查询符合条件的文档,即需要对满足这个条件的文档进行更新。第二个参数是修改器文档,即是修改了的内容。

下面看一个例子:


那么,这个例子我们怎么做呢?

Microsoft Windows XP [版本 5.1.2600](C) 版权所有 1985-2001 Microsoft Corp.C:\Documents and Settings\Administrator>E:E:\>CD MongoDBE:\MongoDB>mongo.exeMongoDB shell version: 2.0.2connecting to: test> use phpswitched to db php> show collectionsblogsystem.indexes> db.user.insert({"name":"joe","friends":32,"enemies":2})  //重新建一个user集合,并插入一条数据。> db.user.findOne()  //这就是变化前的数据。那么如何用update()更新达到效果呢?{        "_id" : ObjectId("4f0d057b081c6af197458524"),        "name" : "joe",        "friends" : 32,        "enemies" : 2}> var joe = db.user.findOne({"name":"joe"}); //第一步:用findOne()找出需要修改的文档,即找出user集合中name为joe的文档,命名为joe。> joe.relationships = {"friend":joe.friends,"enemies":joe.enemies}; //第三步:在joe文档中加入一个新的键relationships,它也是一个文档,它的键friend的值是joe文档中friends的值,enemies键的值是joe文档中enemies键的值。 { "friend" : 32, "enemies" : 2 } > joe.username = joe.name;  //第三步:改name为username,采用的手法是:在joe文档中加入一个新的键username,它的值是joe文档中键name的值。joe> delete joe.friends;  //删除joe文档中friendstrue> delete joe.enemies;//删除文档中enemiestrue> delete joe.name; //删除文档中nametrue> db.user.update({"name":"joe"},joe); //用update更新,导入joe修改器文档。>db.user.findOne({"name":"joe"})  //查看,更新成功!{        "_id" : ObjectId("4f0d057b081c6af197458524"),        "relationships" : {                "friend" : 32,                "enemies" : 2        },        "username" : "joe"}>

3.update()中第二个参数中的几个修改器

前面说到update( )中有两个参数,第二参数是修改器,第2点中,那个例子joe是采用全局覆盖的方法。那么有几个修改器,可以完成更加复杂的更新操作,比如:调整,增加或者删除键,还可能是操作数组或者内嵌文档。

1. "$set"修改器。

"$set"用来修改一个键的值。如果这个键不存在就自动创建,并附上值。下面是一个例子,还是上面的php库中的user集合。

> db.user.update({"username":"joe"},{"$set":{"sex":"nan"}})  //采用"$set"修改器,修改sex键的值为"nan",但是sex键不存在,就自动创建一个,并赋值为"nan"。> db.user.findOne(){        "_id" : ObjectId("4f0d057b081c6af197458524"),        "relationships" : {                "friend" : 32,                "enemies" : 2        },        "sex" : "nan",     //新添加上去了。        "username" : "joe"}>
> db.user.update({"username":"joe"},{"$set":{"sex":"nv"}})  //再次修改sex键的值为nv,因为已经存在,所以就修改。> db.user.findOne(){        "_id" : ObjectId("4f0d057b081c6af197458524"),        "relationships" : {                "friend" : 32,                "enemies" : 2        },        "sex" : "nv",  //sex键修改为"nv"了。        "username" : "joe"}>

“$set” 也可以修改键的数据类型,如想吧sex变成一个数组[“nan”,"nv","no"],哈哈,一会男,一会女!那我们也可以做。

> db.user.update({"username":"joe"},{"$set":{"sex":["nv","nan","no"]}}) //将sex键变成数组。> db.user.findOne(){        "_id" : ObjectId("4f0d057b081c6af197458524"),        "relationships" : {                "friend" : 32,                "enemies" : 2        },         "sex" : [          //修改成功。                "nv",                "nan",                "no"        ],        "username" : "joe"}>

“$set” 同样可以修改内嵌的文档,好比user集合中键relationships是一个文档,那么如何修改这个内嵌文档中friend的值呢。也用"$set" 。

> db.user.update({"username":"joe"},{"$set":{"relationships.friend":1000}})   //采用relationships.friend二级菜单的方式修改,成1000> db.user.findOne(){        "_id" : ObjectId("4f0d057b081c6af197458524"),        "relationships" : {                "friend" : 1000,   //修改成功。                "enemies" : 2        },        "sex" : [                "nv",                "nan",                "no"        ],        "username" : "joe"}>

2.“$inc”修改器。

“$inc”修改器是增加键的值(等同于 +=),不存在这个键就自动增加一个。只能用于(int )整数,长整数,双精度浮点数 键的叠加。比如age =2 1,用$inc增加 2岁,就变成23了。

> db.user.update({"username":"joe"},{"$inc":{"age":20}}) //将user文档中username为joe的age增加20岁。由于age不存在,就自动创建并赋值为20.> db.user.findOne(){        "_id" : ObjectId("4f0d057b081c6af197458524"),        "age" : 20,  //新增age键,值为20。        "relationships" : {                "friend" : 1000,                "enemies" : 2        },        "sex" : [                "nv",                "nan",                "no"        ],        "username" : "joe"}
> db.user.update({"username":"joe"},{"$inc":{"age":2}})  //将age的值增加2岁,由于已经存在,所以会累加> db.user.findOne(){        "_id" : ObjectId("4f0d057b081c6af197458524"),        "age" : 22,  //加上2,变成22。        "relationships" : {                "friend" : 1000,                "enemies" : 2        },        "sex" : [                "nv",                "nan",                "no"        ],        "username" : "joe"}>

3.数组修改器(“$push”、“$pop”、“$pull”、“$addToSet”、“$each”)

当涉及到键为数组的时候,用上面的“$set”就不好使了,就不方便了。那么可以用$push往数组中添加值,用$pop删除前或后的值,用$pull删除数组中指定的值,用$addToSet增加非重复值。

> db.user.update({"username":"joe"},{"$set":{"email":["1@qq.com","2@qq.com","3@qq.com"]}}) //由于user集合中没有一个文档有email键。所以用$set添加一个数组。> db.user.findOne(){        "_id" : ObjectId("4f0d057b081c6af197458524"),        "age" : 22,        "email" : [      //添加数组键成功。                "1@qq.com",                "2@qq.com",                "3@qq.com"        ],        "relationships" : {                "friend" : 1000,                "enemies" : 2        },        "sex" : [                "nv",                "nan",                "no"        ],        "username" : "joe"}> db.user.update({"username":"joe"},{"$push":{"email":"4@qq.com"}})  //往sex数组键中加入一条新的email。> db.user.findOne(){        "_id" : ObjectId("4f0d057b081c6af197458524"),        "age" : 22,        "email" : [                "1@qq.com",                "2@qq.com",                "3@qq.com",                "4@qq.com"  //成功。        ],        "relationships" : {                "friend" : 1000,                "enemies" : 2        },        "sex" : [                "nv",                "nan",                "no"        ],        "username" : "joe"}>

那么我们要删除数组键中的一个值,怎么办呢?用$pop。

> db.user.update({"username":"joe"},{"$pop":{"email": 1}})  //$pop为1的时候,表示从数组尾部删除一个元素。为-1表示从数组头部删除一个元素> db.user.findOne(){        "_id" : ObjectId("4f0d057b081c6af197458524"),        "age" : 22,        "email" : [                "1@qq.com",                "2@qq.com",                "3@qq.com"   //4@qq.com已经删除。        ],        "relationships" : {                "friend" : 1000,                "enemies" : 2        },        "sex" : [                "nv",                "nan",                "no"        ],        "username" : "joe"}> db.user.update({"username":"joe"},{"$pop":{"email":-1}})  //$pop为-1,从头部删除一个元素> db.user.findOne(){        "_id" : ObjectId("4f0d057b081c6af197458524"),        "age" : 22,        "email" : [                "2@qq.com",  //1@qq.com已删除。                "3@qq.com"        ],        "relationships" : {                "friend" : 1000,                "enemies" : 2        },        "sex" : [                "nv",                "nan",                "no"        ],        "username" : "joe"}>

那,如果我想删除数组键中指定的某一个键,怎么办。可以用$pull 修改器。

> db.user.update({"username":"joe"},{"$pull":{"email":"2@qq.com"}})  //删除email为2@qq.com这个元素> db.user.findOne(){        "_id" : ObjectId("4f0d057b081c6af197458524"),        "age" : 22,        "email" : [                "3@qq.com"  //已删除。        ],        "relationships" : {                "friend" : 1000,                "enemies" : 2        },        "sex" : [                "nv",                "nan",                "no"        ],        "username" : "joe"}>

那,添加的时候遇到重复的怎么办。$push是不能去掉重复的,只有你加入,就堆入数组尾部。那么可以用$addToSet来添加数组时候,重复的数据不会添加。

> db.user.update({"username":"joe"},{"$addToSet":{"email":"5@qq.com"}})  //增加5@qq.com。不会重复> db.user.findOne(){        "_id" : ObjectId("4f0d057b081c6af197458524"),        "age" : 22,        "email" : [                "3@qq.com",                "5@qq.com" //添加成功!        ],        "relationships" : {                "friend" : 1000,                "enemies" : 2        },        "sex" : [                "nv",                "nan",                "no"        ],        "username" : "joe"}> db.user.update({"username":"joe"},{"$addToSet":{"email":"5@qq.com"}})  //再次添加5@qq.com。重复了,就不会添加了。> db.user.findOne(){        "_id" : ObjectId("4f0d057b081c6af197458524"),        "age" : 22,        "email" : [                "3@qq.com",                  "5@qq.com"  //没添加成功。        ],        "relationships" : {                "friend" : 1000,                "enemies" : 2        },        "sex" : [                "nv",                "nan",                "no"        ],        "username" : "joe"}>

3.删除文档

mongoDB中删除文档较为简单 db.user.remove(条件),就可以了。