简体   繁体   中英

Update an array using MongoDB

I have JSON like:

{ "_id": "1", "_class": "com.model.Test", "itemList": [ { "itemID": "1", "itemName": "Foo", "resources": [ { "resourceID": "1", "resourceName": "Foo Test1", }, { "resourceID": "2", "resourceName": "Foo Test2", } ] } ] }

I need to be able to update the list of resources. I have done the following:

    BasicDBObject updateQuery = new BasicDBObject();
    updateQuery.put("id", "1");

    BasicDBObject updateCommand = new BasicDBObject();

    List<Resource> resources = populateResources();//Fetch a new list of Resources
    updateCommand.put("$push", new BasicDBObject("resources", resources));


    MongoOperations mongoOperations = mongoConfiguration.getMongoTemplate();
    DBCollection db = mongoOperations.getCollection("myCollection");
    db.save(updateCommand);

I get the follwoing error:

java.lang.IllegalArgumentException: fields stored in the db can't start with '$' (Bad Key: '$push')

When I used:

db.update( updateQuery, updateCommand, true, true );

I got the following exception:

java.lang.IllegalArgumentException: can't serialize class com.model.Test

I've tried: db.updateMulti(updateQuery, updateCommand); I didn't get neither any exceptions nor any updates takes place into the documents.

So what am I missing here !!

The save() method is failing because it is attempting to insert the following document into the collection: {"$push":{"resources":[a list of resources]}}, and "$push" is not a valid key name.

From your question, it appears as though you are attempting to add another resource document to the list of embedded documents, "resources", inside of the embedded document matching {"itemID": "1"}, inside of "itemList". Is this correct?

Dealing with layers of embedded documents is tricky, but it can be done:
Here is how the following document may be inserted into the "resources" list using the JS shell:

> var docToInsert = { "resourceID" : "3", "resourceName" : "Foo Test3"}
> db.myCollection.update({_id:"1", "itemList.itemID":"1"}, {"$push":{"itemList.$.resources":docToInsert}})
> db.myCollection.find().pretty()
{
    "_class" : "com.model.Test",
    "_id" : "1",
    "itemList" : [
        {
            "itemID" : "1",
            "itemName" : "Foo",
            "resources" : [
                {
                    "resourceID" : "1",
                    "resourceName" : "Foo Test1"
                },
                {
                    "resourceID" : "2",
                    "resourceName" : "Foo Test2"
                },
                {
                    "resourceID" : "3",
                    "resourceName" : "Foo Test3"
                }
            ]
        }
    ]
}
> 

The documentation on using the "$" positional operator to update embedded documents may be found in the "Updating" documentation: http://www.mongodb.org/display/DOCS/Updating#Updating-The%24positionaloperator

The documentation on the "$push" modifier is also on the "Updating" page: http://www.mongodb.org/display/DOCS/Updating#Updating-%24push

From the posted code, it appears as though "resources" is a list. It is possible that the method you need to use is $pushAll, used for adding multiple values to a list: http://www.mongodb.org/display/DOCS/Updating#Updating-%24pushAll

Using the Java driver, the above insert may be done like so:

Mongo m = new Mongo("localhost", 27017);
DB db = m.getDB("test");
DBCollection myColl = db.getCollection("myCollection");

BasicDBObject docToInsert = new BasicDBObject("resourceID", "3");
docToInsert.put("resourceName", "Foo Test3");

BasicDBObject updateQuery = new BasicDBObject("_id", "1");
updateQuery.put("itemList.itemID", "1");

BasicDBObject updateCommand = new BasicDBObject("$push", new BasicDBObject("itemList.$.resources", docToInsert));

myColl.update(updateQuery, updateCommand);
System.out.println(myColl.findOne().toString());

The above outputs the following:

{ "_class" : "com.model.Test" , "_id" : "1" , "itemList" : [ { "itemID" : "1" , "itemName" : "Foo" , "resources" : [ { "resourceID" : "1" , "resourceName" : "Foo Test1"} , { "resourceID" : "2" , "resourceName" : "Foo Test2"} , { "resourceID" : "3" , "resourceName" : "Foo Test3"}]}]}

Hopefully, the above will improve your understanding of how updating an embedded document works with Mongo using the Java driver. I notice that this question is also related to Spring ("mongoOperations" is a class from the Spring package), which I am unfortunately not familiar with. If you are still having issues with your update, perhaps another member of the Community who is more familiar with Spring will be able to assist.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM