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修饰符。Upsertsupdate中的一个更让人惊喜特性是它完全支持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 fewsurprising behaviors, which is why we dedicate a chapter to it.Update: Replace Versus $setIn its simplest form, update takes 2 arguments: the selector (where) to use and what field toupdate 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'})You should discover updates first surprise. No document is found because the second param-eter we supply is used to replace the original. In other words, the update found a documentby name and replaced the entire document with the new document (the 2nd parameter). Thisis different than how SQL's update command works. In some situations, this is ideal and canbe leveraged for some truly dynamic updates. However, when all you want to do is changethe value of one, or a few fields, you are best to use MongoDB's $set modifier:db.unicorns.update({weight: 590}, {$set: {name: 'Roooooodles', dob: new Date(1979, 7, 18, 18, 44), loves: ['apple'], gender: 'm', vampires: 99}})This'll reset the lost fields. It won't overwrite the new weight since we didn't specify it. Nowif we execute:db.unicorns.find({name: 'Roooooodles'})We get the expected result. Therefore, the correct way to have updated the weight in the firstplace is:db.unicorns.update({name: 'Roooooodles'}, {$set: {weight: 590}})Update ModifiersIn addition to $set, we can leverage other modifiers to do some nifty things. All of theseupdate modifiers work on fields - so your entire document won't be wiped out. For example,the $inc modifier is used to increment a field by a certain positive or negative amount. Forexample, if Pilot was incorrectly awarded a couple vampire kills, we could correct the mistakeby executing:db.unicorns.update({name: 'Pilot'}, {$inc: {vampires: -2}})If Aurora suddenly developed a sweet tooth, we could add a value to her loves field via the$push modifier:db.unicorns.update({name: 'Aurora'}, {$push: {loves: 'sugar'}})The Updating section of the MongoDB website has more information on the other availableupdate modifiers.UpsertsOne of updates more pleasant surprises is that it fully supports upserts. An upsert updatesthe document if found or inserts it if not. Upserts are handy to have in certain situations and,when you run into one, you'll know it. To enable upserting we set a third parameter to true.A mundane example is a hit counter for a website. If we wanted to keep an aggregate countin real time, we'd have to see if the record already existed for the page, and based on thatdecide to run an update or insert. With the third parameter omitted (or set to false), executingthe following won't do anything:db.hits.update({page: 'unicorns'}, {$inc: {hits: 1}});db.hits.find();However, if we enable upserts, the results are quite different:db.hits.update({page: 'unicorns'}, {$inc: {hits: 1}}, true);db.hits.find();Since no documents exists with a field page equal to unicorns, a new document is inserted.If we execute it a second time,the existing document is updated and hits is incremented to2.db.hits.update({page: 'unicorns'}, {$inc: {hits: 1}}, true);db.hits.find();Multiple UpdatesThe final surprise update has to offer is that, by default, it'll update a single document. So far,for the examples we've looked at, this might seem logical. However, if you executed somethinglike:db.unicorns.update({}, {$set: {vaccinated: true }});db.unicorns.find({vaccinated: true});You'd likely expect to find all of your precious unicorns to be vaccinated. To get the behavioryou desire, a fourth parameter must be set to true:db.unicorns.update({}, {$set: {vaccinated: true }}, false, true);db.unicorns.find({vaccinated: true});In This ChapterThis chapter concluded our introduction to the basic CRUD operations available against a col-lection. We looked at update in detail and observed three interesting behaviors. First, unlikean SQL update, MongoDB's update replaces the actual document. Because of this the $setmodifier is quite useful. Secondly, update supports an intuitive upsert which is particularlyuseful when paired with the $inc modifier. Finally, by default, update only updates the firstfound document.Do remember that we are looking at MongoDB from the point of view of its shell. The driverand library you use could alter these default behaviors or expose a different API. For example,the Ruby driver merges the last two parameters into a single hash: {:upsert => false, :multi => false}.译者努力翻译,希望转载者注明文章出处及作者。谢谢