{"id":1895,"date":"2013-07-14T10:32:29","date_gmt":"2013-07-14T15:32:29","guid":{"rendered":"http:\/\/www.wiredprairie.us\/blog\/?p=1895"},"modified":"2022-06-29T10:35:18","modified_gmt":"2022-06-29T15:35:18","slug":"using-inc-to-increment-a-field-in-a-sub-document-in-an-array-and-a-field-in-main-document","status":"publish","type":"post","link":"https:\/\/www.wiredprairie.us\/blog\/index.php\/archives\/1895","title":{"rendered":"Using $inc to increment a field in a sub-document in an array and a field in main document"},"content":{"rendered":"

(Blog post inspired by question I answered<\/a> on StackOverflow)<\/p>\n

Lets say you have a schema in MongoDB that looks something like this:<\/p>\n

{\n  '_id'<\/span> : 'star_wars'<\/span>,\n  'count'<\/span> : 1234,\n  'spellings'<\/span> : [ \n    { spelling: 'Star wars'<\/span>, total: 10}, \n    { spelling: 'Star Wars'<\/span>, total : 15}, \n    { spelling: 'sTaR WaRs'<\/span>, total : 5} ]\n}<\/pre>\n

Atomically, you\u2019d like to update two fields at one time, the total for a particular spelling which is in a sub document in an array, and the overall count field.<\/p>\n

The way to handle this is to take advantage of the positional array operator<\/a> and the $inc<\/a><\/strong> operator.<\/p>\n

Starting with just updating the count, that\u2019s easy:<\/p>\n

db.movies.update( \n    {_id: \"star_wars\"<\/span>}, \n    { $inc : { 'count'<\/span> : 1 }}\n)<\/pre>\n

The query matches on the document with the _id<\/strong> of star_wars<\/strong>, and increments the count <\/strong>by 1.<\/p>\n

The positional operator is where the mongo-magic comes into play here. If you wanted to just update a single sub-document in the array, add it to the query. First, we\u2019ll try finding the right document:<\/p>\n

db.movies.find( {\n    _id: \"star_wars\"<\/span>, \n    'spellings.spelling'<\/span> : \"Star Wars\"<\/span> }\n)<\/pre>\n

That matches the right document, but also returns all of the elements of the array.<\/p>\n

But, wait, there\u2019s more! When you match on an element\/document of an array, the position of the match is remembered and can be used in the update phase. You do that using the positional operator. Using the document above, you\u2019ll use this: spellings.$.total<\/strong>. If you knew the specific index into the array, the $<\/strong> could have been replaced with the zero-based index number (like a 1<\/strong> for example in this case: spellings.1.total<\/strong>).<\/p>\n

Putting it all together then results in a slick and simple way of incrementing multiple fields in a document.<\/p>\n

db.movies.update( \n    {_id: \"star_wars\"<\/span>,\n     'spellings.spelling'<\/span> : \"Star Wars\"<\/span> },\n    { $inc : \n        { 'spellings.$.total'<\/span> : 1, \n        'count'<\/span> : 1 }})<\/pre>\n

Results:<\/p>\n

{\n  '_id'<\/span> : 'star_wars'<\/span>,\n  'count'<\/span> : 1235,\n  'spellings'<\/span> : [ \n    { spelling: 'Star wars'<\/span>, total: 10}, \n    { spelling: 'Star Wars'<\/span>, total : 16}, \n    { spelling: 'sTaR WaRs'<\/span>, total : 5} ]\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"

(Blog post inspired by question I answered on StackOverflow) Lets say you have a schema in MongoDB that looks something like this: { ‘_id’ : ‘star_wars’, ‘count’ : 1234, ‘spellings’ : [ { spelling: ‘Star wars’, total: 10}, { spelling: ‘Star Wars’, total : 15}, { spelling: ‘sTaR WaRs’, total : 5} ] } Atomically, […]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true},"categories":[4],"tags":[129],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pd5QIe-uz","jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":1857,"url":"https:\/\/www.wiredprairie.us\/blog\/index.php\/archives\/1857","url_meta":{"origin":1895,"position":0},"title":"Finding duplicates in MongoDB via the shell","date":"March 10, 2013","format":false,"excerpt":"I thought this was an interesting question to answer on StackOverflow (summarized here): I\u2019m trying to create an index, but an error is returned that duplicates exist for the field I want to index. What should I do? I answered with one possibility. The summary is that you can use\u2026","rel":"","context":"In "Coding"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1835,"url":"https:\/\/www.wiredprairie.us\/blog\/index.php\/archives\/1835","url_meta":{"origin":1895,"position":1},"title":"How to rewrite a MongoDB C# LINQ with a Projection Requirement using a MongoCursor","date":"January 26, 2013","format":false,"excerpt":"The LINQ Provider for MongoDB does not currently take into account data projections efficiently when returning data. This could mean that you\u2019re unnecessarily returning more data from the database than is needed. So, I\u2019m going to show you the pattern I applied as a replacement for the LINQ queries when\u2026","rel":"","context":"In "Coding"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1442,"url":"https:\/\/www.wiredprairie.us\/blog\/index.php\/archives\/1442","url_meta":{"origin":1895,"position":2},"title":"Nest Thermostat API\/Protocol","date":"January 8, 2012","format":false,"excerpt":"While Nest Labs hasn\u2019t released a formal (documented & supported) API, I thought I\u2019d do a bit of digging to see how they\u2019re using the network and what might be achievable. A few things are going on, the majority as you\u2019d probably expect. The web interface is using a long\u2026","rel":"","context":"In "Coding"","img":{"alt_text":"image","src":"https:\/\/i0.wp.com\/www.wiredprairie.us\/blog\/wp-content\/uploads\/2012\/01\/image_thumb7.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1833,"url":"https:\/\/www.wiredprairie.us\/blog\/index.php\/archives\/1833","url_meta":{"origin":1895,"position":3},"title":"How to view the MongoDB Query when using the C# LINQ Provider","date":"January 26, 2013","format":false,"excerpt":"If you\u2019re using the Official MongoDB C# Driver from 10gen, you may want to occasionally verify that the generated query matches your LINQ query (or at least that it\u2019s building something efficient). Take for example this query: var query = (from r in DataLayer.Database.GetCollection().AsQueryable() where !r.Deleted select new { Id\u2026","rel":"","context":"In "Coding"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1820,"url":"https:\/\/www.wiredprairie.us\/blog\/index.php\/archives\/1820","url_meta":{"origin":1895,"position":4},"title":"Knockout binding for JavaScript route fixup","date":"January 25, 2013","format":false,"excerpt":"Part one. After the first round, I felt compelled to KnockOut the code a bit more. I\u2019d mentioned I wasn\u2019t pleased with the code exactly. It needed some refactoring. So, I\u2019ve created a new Knockout binding handler. This binding handler replaces\u00a0 named parameters with a model\u2019s properties in a path.\u2026","rel":"","context":"In "Coding"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1397,"url":"https:\/\/www.wiredprairie.us\/blog\/index.php\/archives\/1397","url_meta":{"origin":1895,"position":5},"title":"A post not related to Nest thermostat hardware….","date":"January 3, 2012","format":false,"excerpt":"I typed in https:\/\/www.nest.com this evening and instead of the nice looking Nest.com web site, I got this: What?! I hadn\u2019t actually noticed that I\u2019d typed https at first, so I was a bit baffled for a moment. After closer investigation, Nest doesn\u2019t have HTTPS apparently for their marketing\/support web\u2026","rel":"","context":"In "Coding"","img":{"alt_text":"SNAGHTML69c9dbf8","src":"https:\/\/i0.wp.com\/www.wiredprairie.us\/blog\/wp-content\/uploads\/2012\/01\/SNAGHTML69c9dbf8_thumb.png?resize=350%2C200","width":350,"height":200},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/posts\/1895"}],"collection":[{"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/comments?post=1895"}],"version-history":[{"count":2,"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/posts\/1895\/revisions"}],"predecessor-version":[{"id":2389,"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/posts\/1895\/revisions\/2389"}],"wp:attachment":[{"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/media?parent=1895"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/categories?post=1895"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wiredprairie.us\/blog\/index.php\/wpjson\/wp\/v2\/tags?post=1895"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}