Reputation: 496
Usually, I avoid asking a new question as I always find a "close-enough" answer to my problem.
But this time I surprisingly have a fundamental and straightforward question - without any lead.
I have a straightforward MongoDB document that holds two arrays:
The 1st containing three numbers (ints) - each represent a code-number of a selected (predefined) question.
The 2nd was holding 3 Strings - that are the answers given by the user to these three correspondent questions.
For example, let's say subject code 12 is - "What's your 1st dog's name?", and the user's answer was: "Spiky", etc...
So I end up with something like:
{
"_id" : ObjectId("..."),
"questionCodesArray" : [
12,
56,
3
],
"answersArray" : [
"Spiky",
"go swimming",
"blabla.."
]
}
Now, I'd like to be able to allow the users to change their mind and choose a different question and supply a different answer to it.
For this, I need to have only the index of my element and access it via this index to change it using update()
or findAndModify()
[or any other method] and all the answers out there are "key-value style" which is not needed.
In simple Java I would've simply done something like:
questionsCodesArry[index] = newValue;
and
answersArray[index] = newAnswerString;
All my attempts to write a descent query to do this simple index-based updating have failed.
Any help will be appreciated.
Thank you.
Upvotes: 1
Views: 2452
Reputation: 496
Well, after some trials here is a c&p complete and full method to change an array's element by a given index:
public boolean changeArrayValue(DB db, String collectionName, long id, String arrayNameKey, int index, Object newValue)
{
DBCollection collection = db.getCollection(collectionName);
DBObject query = new BasicDBObject("id",id);//unique id is recommended
DBObject update = new BasicDBObject("$set", new BasicDBObject(arrayNameKey+"."+index, newValue));
DBObject result = collection.findAndModify(query, null, null, false, update,true, true);
//Just for precaution
if(result == null)
return false;
return (((BasicDBList)result.get(arrayNameKey)).get(index)).equals(newValue);
}
As you can see the main issue lays in the $set
line here: arrayNameKey+"."+index
.
In the result I've put the needed flags to get the updated result, which is of type BasicDBList<Object>
.
Pleases note that you'll have to add all the needed checks and validations according to your taste. Enjoy..
Upvotes: 0
Reputation: 10918
In plain MongoDB syntax what you need is this:
collection.update({
/*your filter goes here*/
}, {
$set: {
"questionCodesArray.<zero-based-index>": "new value"
}
})
I don't have a Java environment here to translate this into your driver's world. I might be able to do so tonight, though.
Still, I would definitely vote for a different, more natural and less error-prone design where you'd structure your data like so:
{
"_id" : ObjectId("59b635ffad44fad6662d8591"),
"answers" : [
{
"questionCode" : 12,
"answer" : "Spiky"
},
{
"questionCode" : 56,
"answer" : "go swimming"
},
{
"questionCode" : 3,
"answer" : "blabla.."
}
]
}
If that's an option for you I shall happily provide you the right update statement for this layout, too.
Upvotes: 2