Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to move an item in a MongoDB array?

Is there a way to update a document array to move an item from one index to another? e.g.

{
   name: "myDoc",
   items: ["it1", "it2", "it3"]
}

As a result for JQuery-UI Sortable event it2 and it3 switched places. As a result I want to update their position in the myDoc which is stored in MongoDB.

like image 567
Guy Korland Avatar asked Jun 12 '13 20:06

Guy Korland


2 Answers

Here is another way to move an element to a new position which will swap the positions of it2 and it3...

  1. Remove the element from the array using $pull [ Docs Here ].

    update({"name": "myDoc"}, {$pull: {"items" : "it3"}});
    
  2. Insert the element in the new position using $push. [ Docs Here ].

    update({"name": "myDoc"}, { 
        $push: { 
            "items" : { $each : [ "it3" ], $position : 1 }
        }
    });
    

When to Use

Pouzor's answer to use $set might be simpler and perform better for many use cases.

However, if multiple users are simultaneously adding, removing, and re-ordering array items this method means you won't overwrite each other's changes.

It might also be more efficient in some cases (e.g. large array elements) because less data is being written.

GOTCHA: List of Lists

If the list you are reordering is an array of arrays you need to use the $all operator with $pull [ Docs Here ]

Take this example:

{
    name: "myDoc",
    items: [  
        [ "User", "dofij20r91dj93" ],   
        [ "User", "239vjvidjfsldf" ], 
        [ "User", "2309jvdsjdkk23" ]
    ]
}

Here's the code to remove the first list from the list of lists:

update({"name": "myDoc"}, {
    $pull: {
        "items" : {
            $all : [ "User", "dofij20r91dj93" ]  // the sub-list to $pull
        }
    }
});

List of Objects

This is easy. Say you have the following list of objects:

{
    name: "myDoc",
    items: [  
        { type: "User",  id: "dofij20r91dj93", name: "Dave" },   
        { type: "Group", id: "239vjvidjfsldf", name: "Accountants" }, 
        { type: "User",  id: "2309jvdsjdkk23", name: "Toni" }
    ]
}

You can $pull like this:

update({"name": "myDoc"}, {
    $pull: { 
        "items" : { type: "User", id: "dofij20r91dj93" } 
    }
});
like image 137
Lucidity Avatar answered Oct 06 '22 11:10

Lucidity


For now, there is no way to do this directly in mongo with any driver.

You need to do this in your application and set the array with mongo.

ex:

var new_array = ["it2","it1","it3"];//Do your sort/place in js

$mongo_connexion->update({"name": "myDoc"}, {$set: {"items" : new_array}});
like image 36
Pouzor Avatar answered Oct 06 '22 12:10

Pouzor