Samuel Rabini
Samuel Rabini

Reputation: 143

Multiple update in mongodb using java

I've this document:

{
        "_id" : ObjectId("54140782b6d2ca6018585093"),
        "user_id" : ObjectId("53f4ae1ae750619418a20467"),
        "date" : ISODate("2014-09-13T08:59:46.709Z"),
        "type" : 0,
        "tot" : 2,
        "additional_info" : {
                "item_id" : ObjectId("540986159ef9ebafd3dcb5d0"),
                "shop_id" : ObjectId("53f4cc5a6e09f788a103d0a4"),
                "ap_id" : ObjectId("53f4cc5a6e09f788a103d0a5")
        },
        "transactions" : [
                {
                        "_id" : ObjectId("54140782b6d2ca6018585091"),
                        "date_creation" : ISODate("2014-09-13T08:59:46.711Z"),
                        "type" : -1
                },
                {
                        "_id" : ObjectId("54140782b6d2ca6018585092"),
                        "date_creation" : ISODate("2014-09-13T08:59:46.788Z"),
                        "type" : 1
                }
        ]
}

and I need to add 2 more field to the first transaction opbject: - date_execution: date - result: this bson document

{ "server_used" : "xxx.xxx.xxx.xxx:27017" , "ok" : 1 , "n" : 1 , "updated_executed" : true} (m_OR.getDocument() in the following code example)

to obtaing that document

    {
        "_id" : ObjectId("54140811b6d25137753c1a1a"),
        "user_id" : ObjectId("53f4ae1ae750619418a20467"),
        "date" : ISODate("2014-09-13T09:02:09.098Z"),
        "type" : 0,
        "tot" : 2,
        "additional_info" : {
                "item_id" : ObjectId("540986159ef9ebafd3dcb5d0"),
                "shop_id" : ObjectId("53f4cc5a6e09f788a103d0a4"),
                "ap_id" : ObjectId("53f4cc5a6e09f788a103d0a5")
        },
        "transactions" : [
                {
                        "_id" : ObjectId("54140811b6d25137753c1a18"),
                        "date_creation" : ISODate("2014-09-13T09:02:09.100Z"),
                        "type" : -1,
                        "result" : {
                                "server_used" : "xxx.xxx.xxx.xxx:27017",
                                "ok" : 1,
                                "n" : 1,
                                "updated_executed" : true
                        },
                        "date_execution" : ISODate("2014-09-13T09:02:15.370Z")
                },
                {
                        "_id" : ObjectId("54140811b6d25137753c1a19"),
                        "date_creation" : ISODate("2014-09-13T09:02:09.179Z"),
                        "type" : 1
                }
        ]
}

The only way I was able to do that is the do 2 separates updates (update is a my wrapper funciont that execute the real updates in mongodb and it works fine):

    // where
    BasicDBObject query = new BasicDBObject();
    query.append("transactions._id", m_Task.ID());

    // new value for result - 1st upd
    BasicDBObject value = new BasicDBObject();
    value.put("$set",new BasicDBObject("transactions.$.date_execution",new Date()));
    update(this._systemDB, "activities", query, value);

    // new value for date_execution - 2nd upd
    value = new BasicDBObject();
    value.put("$set",new BasicDBObject("transactions.$.result",m_OR.getDocument()));
    update(this._systemDB, "activities", query, value);

If I try to do this:

    BasicDBObject value = new BasicDBObject();
    value.put("$set",new BasicDBObject("transactions.$.date_execution",new Date()));
    value.put("$set",new BasicDBObject("transactions.$.result",m_OR.getDocument()));
    or = update(this._systemDB, "activities", query, value);

just the 2nd set will be applied.

Is there any way do avoid the double execution and apply the update with just one call?

Upvotes: 0

Views: 117

Answers (2)

Samuel Rabini
Samuel Rabini

Reputation: 143

Your suggestion was right, just had to fix a little the syntax this way:

BasicDBObject value = new BasicDBObject();
value.put("$set",
        new BasicDBObject("transactions.$.date_execution",new Date())
        .append("transactions.$.result",m_OR.getDocument())
);

This worked perfectly ;)

Thanks! Samuel

Upvotes: 0

Neil Lunn
Neil Lunn

Reputation: 151190

Basic rule of "hash/map" objects is that you can only have one key. It's the "highlander" rule ( "There can be only one" ) applied in general reason. So just apply differently:

BasicDBObject value = new BasicDBObject();
value.put("$set",
    new BasicDBObject("transactions.$.date_execution",new Date())
        .add( new BasicDBObject("transactions.$.result",m_OR.getDocument() )
);

So basically "both" field arguments are part of the "$set" statement as in the serialized form:

{
   "$set": {
       "transactions.$.date_execution": new Date(),
       "transactions.$.result": m_Or.getDocument()
   }
}

Which is basically what you want in the end.

Upvotes: 1

Related Questions