3.MangoDB创建、更新、删除文档

写在前面

前面一篇对MongoDB的基本操作有了一个大致的了解,这一篇中,详细讲解MangoDB的创建、更新、删除文档。

1.插入并保存文档

插入是MongoDB中的最基本的方法,那往一个集合中插入数据,上一篇已经说过:

Microsoft Windows XP [版本 5.1.2600]
(C) 版权所有 1985-2001 Microsoft Corp.

C:\Documents and Settings\Administrator>E:

E:\>cd MongoDB

E:\MongoDB>mongo.exe
MongoDB shell version: 2.0.2
connecting to: test
> use php  //选择php数据库
switched to db php
> show collections //查看phps数据库中有哪些集合。
blog
system.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" }
>
上面的文档中,有个“_id”, 本来是要第二篇说的,那这一篇就说说。(引来自:http://www.cnblogs.com/liuhao/archive/2011/12/01/2270649.html)

在一个特定集合内部,需要唯一的标识文档。因此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有两个参数,第一个参数是查询符合条件的文档,即需要对满足这个条件的文档进行更新。第二个参数是修改器文档,即是修改了的内容。

下面看一个例子:

3.MangoDB创建、更新、删除文档_第1张图片

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

Microsoft Windows XP [版本 5.1.2600]
(C) 版权所有 1985-2001 Microsoft Corp.

C:\Documents and Settings\Administrator>E:

E:\>CD MongoDB

E:\MongoDB>mongo.exe
MongoDB shell version: 2.0.2
connecting to: test
> use php
switched to db php
> show collections
blog
system.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文档中friends
true
> delete joe.enemies;//删除文档中enemies
true
> delete joe.name; //删除文档中name
true
> 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":["[email protected]","[email protected]","[email protected]"]}}) //由于user集合中没有一个文档有email键。所以用$set添加一个数组。
> db.user.findOne()
{
        "_id" : ObjectId("4f0d057b081c6af197458524"),
        "age" : 22,
        "email" : [      //添加数组键成功。
                "[email protected]",
                "[email protected]",
                "[email protected]"
        ],
        "relationships" : {
                "friend" : 1000,
                "enemies" : 2
        },
        "sex" : [
                "nv",
                "nan",
                "no"
        ],
        "username" : "joe"
}
> db.user.update({"username":"joe"},{"$push":{"email":"[email protected]"}})  //往sex数组键中加入一条新的email。
> db.user.findOne()
{
        "_id" : ObjectId("4f0d057b081c6af197458524"),
        "age" : 22,
        "email" : [
                "[email protected]",
                "[email protected]",
                "[email protected]",
                "[email protected]"  //成功。
        ],
        "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" : [
                "[email protected]",
                "[email protected]",
                "[email protected]"   //[email protected]已经删除。
        ],
        "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" : [
                "[email protected]",  //[email protected]已删除。
                "[email protected]"
        ],
        "relationships" : {
                "friend" : 1000,
                "enemies" : 2
        },
        "sex" : [
                "nv",
                "nan",
                "no"
        ],
        "username" : "joe"
}
>
那,如果我想删除数组键中指定的某一个键,怎么办。可以用$pull 修改器。

> db.user.update({"username":"joe"},{"$pull":{"email":"[email protected]"}})  //删除email为[email protected]这个元素
> db.user.findOne()
{
        "_id" : ObjectId("4f0d057b081c6af197458524"),
        "age" : 22,
        "email" : [
                "[email protected]"  //已删除。
        ],
        "relationships" : {
                "friend" : 1000,
                "enemies" : 2
        },
        "sex" : [
                "nv",
                "nan",
                "no"
        ],
        "username" : "joe"
}
>
那,添加的时候遇到重复的怎么办。$push是不能去掉重复的,只有你加入,就堆入数组尾部。那么可以用$addToSet来添加数组时候,重复的数据不会添加。

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

3.删除文档

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



你可能感兴趣的:(mongodb,Microsoft,服务器,文档,email,Comments)