Node, MongoDB : Incrementing values of items in array with range query
<p>I have an array of categories under users collection in mongodb. </p>

<p>Basically there is a drag and drop menu of categories in front end, when a drag&amp;drop happens I want to update the database. Since it is not possible to move items in array, I decided to give them a position value "pos" in mongodb and sort them later in angularjs.</p>

<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>categories: [
    {
        "_id" : ObjectId("5776782a57c9580256536656"),
        "title" : "Cars",
        "url" : "cars",
        "pos" : 0
    },
    {
        "_id" : ObjectId("5776786afdcd6ed056edff25"),
        "title" : "Photography",
        "url" : "photography",
        "nodes" : [ 
            {
                "_id" : ObjectId("57767870fdcd6ed056edff26"),
                "title" : "Landscape",
                "url" : "landscape"
            }
        ],
        "pos" : 1
    },
    {
        "_id" : ObjectId("adf9845782578a376161d079"),
        "title" : "Travel",
        "url" : "travel",
        "pos" : 2
    }
]</code></pre>
</div>
</div>
</p>

<p>I'm using nodejs-express as server and here is my code to move categories.</p>

<ul>
<li>oldIndex : position of category before moving</li>
<li>newIndex : new position of category after moving</li>
<li>userId : users object Id</li>
</ul>

<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>    if (newIndex&gt;oldIndex){
        db.collection('users').updateOne({ "_id": userId, "categories.pos": { $gte: oldIndex, $lt: newIndex } }, { $inc : { "categories.$.pos" : -1 } }, function (err, res) {
            console.log(res);
            if (err) callback(0)
            else {
                db.collection('users').updateOne(filter, { $set :  cdata }, function (err, res) {
                    if (err) callback(0);
                    callback(1);
                });
            }
        });
    } else {
        db.collection('users').updateOne({ "_id": userId, "categories.pos": { $gt: newIndex, $lte: oldIndex  } }, { $inc : { "categories.$.pos" : 1 } }, function (err, res) {
            console.log(res);
            if (err) callback(0)
            else {
                db.collection('users').updateOne(filter, { $set :  cdata }, function (err, res) {
                    if (err) callback(0);
                    callback(1);
                });
            }
        });
    }</code></pre>
</div>
</div>
</p>

<p>basically, the code meant to do this</p>

<p><strong>if (newIndex > oldIndex)</strong></p>

<ul>
<li>Category A - 0 (oldIndex)</li>
<li>Category B - 1</li>
<li>Category C - 2</li>
<li>Category D - 3</li>
</ul>

<p>to move A to Index 2</p>

<ul>
<li>Category B - 0 (-1)</li>
<li>Category C - 1 (-1)</li>
<li>Category A - 2 (newIndex)</li>
<li>Category D - 3 (0)</li>
</ul>

<p>and the other way around </p>

<p><strong>if (oldIndex > newIndex)</strong></p>

<ul>
<li>Category A - 0 </li>
<li>Category B - 1</li>
<li>Category C - 2 (oldIndex)</li>
<li>Category D - 3</li>
</ul>

<p>to move C to Index 0</p>

<ul>
<li>Category C - 0 (newIndex)</li>
<li>Category A - 1 (+1)</li>
<li>Category B - 2 (+1)</li>
<li>Category D - 3 (0)</li>
</ul>

<p>In this case, I can't run a find query to see &amp; troubleshoot the results of the query..</p>

<p>with any number of categories, query only updates one value.</p>

<p>I guess I need new pair of eyes.</p>

<p>Thank you.</p>