日期:2014-05-16  浏览次数:20479 次

Allan 译 The Little MongoDB Book (Chapter 2 - Updating)
Chapter 2 - Updating
在第一章中我们介绍了四个CRUD(create, read, update和delete)操作中的三个。在这一章中了解我们跳过的个:update。 Update有几个让人惊叹的行为,这也就是为什么我们为什么用一章来介绍它。

Update: Replace Versus $set
在它最简单的形式,update带有两个参数:要使用的选择器(where)和要更新的字段。如果Roooooodles已经设置了重量,我们可以执行:

db.unicorns.update({name: 'Roooooodles'}, {weight:  590})

(如果你在使用你的unicorns并且它并没有任何的原始数据,那么现在就去删除所有的文件并插入第一章中的数据)

如果是在真实的编码中,你可能根据_id来更新记录,但是因为我并不知道MongoDB为你生成了什么_id是什么,所以我们选择使用name。现在,如果我们查看更新的记录:

db.unicorns.find({name: 'Roooooodles'})

你会发现update让你第一个惊讶的地方。因为我们执行的第二个参数将会替换掉原有的数据,所以你不会查找到任何数据。换句话说,update根据name查找到一个文件,并用第二个参数替换掉整个文件。这和SQL的update操作是不同的。在某些情况下,这样做是理想,这可以真正的动态更新提供补充。然而,当我想做的只是想更换一个值,或几个值,你最好使用MongoDB的 $set 修饰符。

db.unicorns.update({weight: 590}, {$set: {name: 'Roooooodles', dob: new Date
(1979, 7, 18, 18, 44), loves: ['apple'], gender: 'm', vampires: 99}})

它将重置所有丢失的字段。因为我们没的指定weight,所以它不会被重写。现在如果我们执行:

db.unicorns.find({name: 'Roooooodles'})

我们会得到希望的结果。因此,正确的更新体重的方式为:

db.unicorns.update({name: 'Roooooodles'}, {$set: {weight: 590}})

Update修饰符
除了$set,我们可以补充另外几个修饰符来做一些性感的东西。所有的这些update修饰符都是工作在字段上,所以你的整个文件不会被清除。例如,$inc修饰符通过包含一个正数或负数来实现字段值的增加。例如,如果Pilot被错误的增加了两个杀死吸血鬼战绩,我们可以通过这样来改正:

db.unicorns.update({name: 'Pilot'}, {$inc: {vampires: -2}})

如果Aurora突然爱吃甜食,我们可以通过$push修饰符来为她的loves字段添加值:

db.unicorns.update{(name: 'Aurora'}, {$push: {loves: 'sugar'}})

MongoDB官网上的Updating章节提供了另外的有用的update修饰符。

Upserts
update中的一个更让人惊喜特性是它完全支持upserts。一个upserts如果发现文件就更新,否则就插入之。Upserts在某些情况下特别灵活,当你使用了一次,你就知道了。把第三个参数设置为true就可支持upserting。

一个最常见的例子就是网站计数器。如果我们想要实时保持一个总数,我们将不得不查看这一页的记录是否已经存在,并且根据它来决定要运行update或insert。省略了第三个参数(或者设置为false),执行下面的命令将不会做任何东西:

db.hits.update({page: 'unicorns'}, {$inc: {hits: 1}});
db.hits.find();

然而,如果我们使用upserts,结果将会完全不同:

db.hits.update({page: 'unicorns'}, {$inc: {hits: 1}}, true);
db.hits.find();

因为没有page等于unicorns,一个新文件会被插入。如果我们第二次执行它,那么已存在的hits将会增加到2。

db.hits.update({page: 'unicorns'}, {$inc: {hits: 1}}, true);
db.hits.find();

Multiple Updates
现在介绍update提供的最后一个惊喜,默认情况下,它会更新单个文件。目前来说,所有我们已经看到的这些例子,还是符合逻辑的。然而,如果我们像下面这样执行命令:

db.unicorns.update({}, {$set: {vaccinated: true }});
db.unicorns.find({vaccinated: true});

如果你希望你的珍贵的独角兽都注射疫苗。要想达到你想要的效果,第四个参数必须设置为true:

db.unicorns.update({}, {$set: {vaccinated: true}}, false, true);
db.unicorns.find({vaccinated: true});

In This Chapter
本章结束了对collection中的基本CURD操作。我们介绍了update中的有意思的三个行为特性。首先,不同于SQL更新,MongoDB的更新会取代实际的文件。正因为此,$set修饰符特别的有用。第二,update支持upsert,这对于成对的$inc
修饰符会很有帮助。最后,默认情况下,update只会更新第一个查找到的文件。

一定要记住我们查看MongoDB是从它的shell窗囗。驱动器和类库通过不同的API可能会修改默认的行为。例如,Ruby驱动器把最后两个参数合并为{:upsert =>false, :multi=>false}。



原文:

Chapter 2 - Updating
In chapter 1 we introduced three of the four CRUD (create, read, update and delete) oper-
ations. This chapter is dedicated to the one we skipped over: update. Update has a few
surprising behaviors, which is why we dedicate a chapter to it.
Update: Replace Versus $set
In its simplest form, update takes 2 arguments: the selector (where) to use and what field to
update with. If Roooooodles had gained a bit of weight, we could execute:
db.unicorns.update({name: 'Roooooodles'}, {weight: 590})
(if you've played with your unicorns collection and it doesn't have the original data anymore,
go ahead and remove all documents and re-insert from the code in chapter 1.)
If this was real code, you'd probably update your records by _id, but since I don't know what
_id MongoDB generated for you, we'll stick to names. Now, if we look at the updated record:
db.unicorns.find({name: 'Roooooodles'})