MongoDb's $set equivalent in its java Driver - java

Is there a way in which I can modify the value of one of the keys in MongoDb via its Java Driver. I tried out the following:
someCollection.update(DBObject query, DBObject update);
someCollection.findAndModify(DBObject query, DBObject update);
But both the functions completely replace the queried document with the updated document. What is the way to update only one of the value of a particular key as in the case of using $set in the mongo shell.(apart from making a completely new Document with all fields copied and one of the fields updated).

BasicDBObject carrier = new BasicDBObject();
BasicDBObject query = new BasicDBObject();
query.put("YOUR_QUERY_STRING", YOUR_QUERY_VALUE);
BasicDBObject set = new BasicDBObject("$set", carrier);
carrier.put("a", 6);
carrier.put("b", "wx1");
myColl.updateMany(query, set);
This should work, the answer which is accepted is not right above.

Try something like this:
BasicDBObject set = new BasicDBObject("$set", new BasicDBObject("age", 10));
set.append("$set", new BasicDBObject("name", "Some Name"));
someCollection.update(someSearchQuery, set);
Also look at this example.

None of the solutions mentioned above worked for me. I realized that the query should be a Document type and not a BasicDBObject :
Document set = new Document("$set", new Document("firstName","newValue"));
yourMongoCollection.updateOne(new Document("_id",objectId), set);
Where "yourMongoCollection" is of type "MongoCollection" and "objectId" of type "ObjectId"

The previous answer pointed me in the right direction, but the code to add a 2nd object to the update did not work for me. The following did:
BasicDBObject newValues = new BasicDBObject("age", 10);
newValues.append("name", "Some Name");
BasicDBObject set = new BasicDBObject("$set", newValues);
collection.update(someSearchQuery, set);

First, unless I want to reconfigure/reformat/"re-type" my values I'd go only with findAndModify and not update.
Here is a fully working example for c&p purposes... Enjoy:
Boolean updateValue(DB db, DBCollection collection, String id, String key, Object newValue)
{
DBCollection collection = db.getCollection(<collection name>);
// Identify your required document (id, key, etc...)
DBObject query = new BasicDBObject("_ID",<ID or key value>);
DBObject update = new BasicDBObject("$set", new BasicDBObject(key, newValue));
//These flags will guarantee that you'lls get the updated result
DBObject result = collection.findAndModify(query, null, null, false, update,true, true);
//Just for precaution....
if(result == null)
return false;
return result.get(key).equals(newValue);
}

According to the documents, $set is an alise for $addFields, so just use that:
var iterable = collection.aggregate(Arrays.asList(
Aggregates.addFields(new Field("foo", "bar"))
));

Related

Insert a document into another document in MongoDB

I'm trying to add a document in another document.
I am trying to insert a new document with a timestamp as a key and light prox and temp as the content of that document into document sensor_collection.
It's logical that my code doesn't work, because I'm setting a new sensor_collection. Does anyone know how I can set a timestamp document in sensor_collection or is it adviced not to do it this way?
This is the code:
MongoCollection<Document> collection = db.getCollection(Sensor.KEY_COLLECTION);
//append sensor data to existing document
collection.updateOne(doc, new Document("$set",
new Document("sensor_collection", new Document(
String.valueOf(stamp.getCurrentTime()), new Document(
Sensor.KEY_LIGHT, sensorData.getLight())
.append(Sensor.KEY_PROX, sensorData.getProx())
.append(Sensor.KEY_TEMP, sensorData.getTemp())
))));
Currently this code overrides the timestamp that's already in the db.
If you want to append to an existing embedded collection, use $push instead of $set. The $push operator appends a specified value to an array. Something like this:
collection.updateOne(doc, new Document("$push",
new Document("sensor_collection", new Document(
String.valueOf(stamp.getCurrentTime()), new Document(
Sensor.KEY_LIGHT, sensorData.getLight())
.append(Sensor.KEY_PROX, sensorData.getProx())
.append(Sensor.KEY_TEMP, sensorData.getTemp())
))));
For more details on mongo's update operators, check this out
In the Mongodb documentation I found this:
"To specify a <field> in an embedded document or in an array, use dot notation."
I used the $set operator. And I'm setting sensor_collection.timestamp
MongoCollection<Document> collection = db.getCollection(Sensor.KEY_COLLECTION);
//append sensor data to existing document
collection.updateOne(doc, new Document("$set",
new Document("sensor_collection."+String.valueOf(stamp.getCurrentTime()),
new Document(
Sensor.KEY_LIGHT, sensorData.getLight())
.append(Sensor.KEY_PROX, sensorData.getProx())
.append(Sensor.KEY_TEMP, sensorData.getTemp())
)));
This works. Gives:

How to enforce increasing id in Mongo Collection in updating with Java Driver

I have the following code that supposed to update or insert a Mongo document if it does not exist
ByteArrayOutputStream b = new ByteArrayOutputStream();
ObjectOutputStream o = new ObjectOutputStream(b);
o.writeObject(value);
BasicDBObject doc = new BasicDBObject(“objectData”, getBytesForObject(o))
.append(“objectKey”, key)
.append(“LastModified”, mongoDateFormat.format(new Date()));
MongoCollection<BasicDBObject> collection =
getMongoDatabase().getCollection("cache", BasicDBObject.class);
UpdateOptions updateOptions = new UpdateOptions();
updateOptions.upsert(true);
collection.updateOne(new BasicDBObject(“objectKey”, key), new BasicDBObject("$set", doc), updateOptions);
However, this code always inserts _id as 0.
How to fix this?

Mongo DB Remove Duplcates in a field in a Collection Javadriver

I am trying to remove duplicates in a collection using java driver in mongodb.
I am using the code
table = db.getCollection("dummy_data_OLD");
BasicDBObject query = new BasicDBObject("url", 1)
.append("unique", true).append("dropDups", true);
table.createIndex(query);
It will create a unique index , but still duplicates present in the db.
Is there any problem in my code?
This creates an index on the fields url, unique and dropDups. When you want to create an index using options, you need to provide these as a second DBObject.
DBObject fields = new BasicDBObject("url", 1);
DBObject options = new BasicDBObject("unique", true).append("dropDups", true);
db.getCollection("dummy_data_OLD").createIndex(fields, options);

Lucene query with phrase order slop and OR clause

I need to frame a lucene query such that it works for both "convert int to string" and "convert integer to string". Also, in the matched results, there could be more words in between the terms. For example "How could I convert a proper int to a well formatted string". I tried the following:
Query query = new SpanNearQuery(new SpanQuery[] {
new SpanTermQuery(new Term("title", "convert")),
new SpanTermQuery(new Term("title", "int")),
new SpanTermQuery(new Term("title", "string"))
},
50,
true);
return query;
and the following:
MultiPhraseQuery mpq = new MultiPhraseQuery();
mpq.setSlop(50);
mpq.add(new Term("title","convert"));
mpq.add(new Term[]{new Term("title","int"),new Term("title", "integer")});
mpq.add(new Term("title","string"));
return mpq;
and also the following:
BooleanQuery bq = new BooleanQuery();
bq.add(new TermQuery(new Term("title","convert")), Occur.MUST);
BooleanQuery idFilter = new BooleanQuery();
idFilter.setMinimumNumberShouldMatch(1);
idFilter.add(new TermQuery(new Term("title", "int")), BooleanClause.Occur.SHOULD);
idFilter.add(new TermQuery(new Term("title", "integer")), BooleanClause.Occur.SHOULD);
bq.add(idFilter, BooleanClause.Occur.MUST);
bq.add(new TermQuery(new Term("title","string")), Occur.MUST);
return bq;
None of them seem to do what I need. Can someone help me write a valid query which includes both order of terms and also allows to specify "OR" condition? Thanks.
Your first attempt is closest to the mark. The stumbling block there is how to handle int vs integer.
Two approaches for this come to mind. The best approach might be to incorporate a SynonymFilter into your analyzer. This would allow you to set up a synonym automatically converting integer to int at index time, reducing the need to come up with more complex querying logic.
As far as setting it up strictly in the query construction, I don't know of a way to wrap a boolean query into a span query, but a wildcard, or more precisely, a prefix, query seems like it would serve that purpose, which can be used in a SpanNearQuery by wrapping it in a SpanMultiTermQueryWrapper, something like:
Query query = new SpanNearQuery(new SpanQuery[] {
new SpanTermQuery(new Term("title", "convert")),
new SpanMultiTermQueryWrapper(new PrefixQuery(new Term("title", "int"))),
new SpanTermQuery(new Term("title", "string"))
},
50,
true);
return query;
int* may not be quite identical to int OR integer, but hopefully it's close enough.

MongoDB Java pull

i tried to remove an embedded document without succcess.
I'm looking for the java way of following instruction:
db.games.update({'_id': 73}, {$pull: {'goals': {'goal': 4}}})
The Java documentation is pretty clear, you are just constructing BSON objects to match their respective JSON counterparts as used in the shell:
BasicDBObject query = new BasicDBObject("_id", 73);
BasicDBObject fields = new BasicDBObject("goals",
new BasicDBObject( "goal", 4));
BasicDBObject update = new BasicDBObject("$pull",fields);
games.update( query, update );
Using Bson is similar.
Bson query = new Document().append("_id", 73);
Bson fields = new Document().append("goals", new Document().append( "goal", 4));
Bson update = new Document("$pull",fields);
games.updateOne( query, update );

Categories