How to query only the specific fields in MongoDB with Java? - java

I'm using MongoDB 3.2 and MongoDB Java Driver 3.2. In order to query document I use the following code:
Document query = new Document("fetchStatus", new Document("$lte", fetchStatusParam));
ArrayList<Document> unfetchedEvents = dbC_Events.find(query).into(new ArrayList<Document>());
This query works but the problem is that in this case all fields of the document are retrieved (analog of select * in SQL). In order to optimize query performance, I want to specify fields I really need and fetch only them.
I found couple of examples, such as:
BasicDBObject query = new BasicDBObject();
BasicDBObject fields = new BasicDBObject("Name", 1);
coll.find(query, fields);
but all of them are designed for outdated version of MongoDB Java Driver, e.g. 2.4, while I'm using 3.2.
How can I query only specific fields of document in MongoDB Java Driver 3.2?

There is a .projection() method that is chainable to the query result which allows you to specify fields.
Either expressed as a document, with the familiar and well documented BSON syntax:
ArrayList<Document> unfecthedEvents = collection.find(
new Document("fetchStatus", new Document("$lte", fetchStatusParam))
).projection(
new Document("Name",1)
).into(new ArrayList<Document>());
Or as a fields property builder which really just translates to exactly the same BSON:
ArrayList<Document> unfecthedEvents = collection.find(
new Document("fetchStatus", new Document("$lte", fetchStatusParam))
).projection(
fields(include("Name"))
).into(new ArrayList<Document>());

It worked for me as well:
BasicDBObject whereQuery = new BasicDBObject();
BasicDBObject fields = new BasicDBObject();
// the conditions in where query
whereQuery.put("dzeeClient", dzeeClient);
whereQuery.put("recommendationRunType", planView);
whereQuery.put("recommendedPlans.enrolled",employeeViewed);
// the fields to be returned from the query-only loginId, and remove _id
fields.put("loginId", 1);
fields.put("_id", 0);
FindIterable<Document> cursor = collection.find(whereQuery)
.projection(fields).sort(new BasicDBObject("timeStamp",-1)).limit(1);

Related

Populating combobox with document fields

I'm building a Java application connected to MongoDB about films, and I want to create a ComboBox so I can populate it with the film names. My problem is the only way I have found is populating it with the full document, instead of just getting the film name.
This is what I have so far:
DBCursor films = collection.find();
while(films.hasNext()){
comboBox.addItem(films.next());
}
This is how I create the document:
DBCollection table = db.getCollection("films");
BasicDBObject document = new BasicDBObject();
document.put("title", titulo.getText());
document.put("arg", argumento.getText());
document.put("date", fecha.getText());
document.put("genres", genres);
table.insert(document);
Is there a way to use find to only get the film titles and then display only the value? Thanks in advance.
EDIT
In the supposed duplicated question, the question is related to finding a specific document based on one of its fields. That's not what I need, I need to populate a combobox with one field, but I need to get all my documents.
If you want to get only specific fields in your result set, you will need to use find(DBObject query, DBObject projection) and specify the fields to get in the projection parameter as next:
// Retrieve only the title of all the documents that can be found in the collection
DBCursor cursor = collection.find(
new BasicDBObject(), new BasicDBObject("title", Boolean.TRUE)
);
while (cursor.hasNext()) {
// Add the value of the title to the combo box
comboBox.addItem((String) cursor.next().get("title"));
}
Rather than do a find() pass in the keys you want returned. In this case I believe all you want back is the title. So this should work:
DBCursor films = collection.find({},{"_id":0,"title":1});
while(films.hasNext()){
comboBox.addItem(films.next());
}
DBObject and DBCollection are old 2.x classes.
You can try something like with 3.x driver.
import static com.mongodb.client.model.Projections.*;
MongoClient mongoClient = new MongoClient();
MongoDatabase db = mongoClient.getDatabase("test");
MongoCollection<Document> col = db.getCollection("films");
List<String> titles = col.find().projection(fields(include("titles"), excludeId())).map(document -> document.getString("titles")).into(new ArrayList<>());

Update document in MongoDB with Java

I'm using MongoDB 3.2 and MongoDB Java Driver 3.2. I want to update the value the document having its ID. In order to do that I tried to use the following two approaches (found in Stackoverflow and MongoDB Blog):
Approach #1:
for(String docID : expiredDocsIDs) {
Bson filter = Filters.eq("_id", docID);
Bson updates = Updates.set("isExpired", true);
dbCollection.findOneAndUpdate(filter, updates);
}
Approach #2:
expiredDocsIDs.stream()
.forEach(docID -> {
BasicDBObject searchQuery = new BasicDBObject("_id", docID);
BasicDBObject updateFields = new BasicDBObject();
updateFields.append("isExpired", true);
updateFields.append("fetchStatus", "FETCHED");
BasicDBObject setQuery = new BasicDBObject();
setQuery.append("$set", updateFields);
dbCollection.updateOne(searchQuery, setQuery);
});
None of these approaches does not work.
It iterates over the list of documents IDs, executes the code but at the end of the code, when I check the documents in DB there is no any change in the documents' field I tried to update.
How can I update the specific document in MongoDB?
As BlakesSeven correctly noted, the problem was with a casting of _id field. The original code sent this parameter as String while the correct way is to send a parameter of ObjectId type.
The correct and worked code form MongoDB 3.2:
this.trackedEpisodesReg.entrySet().stream()
.filter(ep -> ep.getValue().isExpired())
.forEach(ep -> {
BasicDBObject updateFields = new BasicDBObject();
updateFields.append("isExpired", true);
BasicDBObject setQuery = new BasicDBObject();
setQuery.append("$set", updateFields);
BasicDBObject searchQuery = new BasicDBObject("_id", new ObjectId(ep.getValue().getEpisodeID()));
dbCollection.updateOne(searchQuery, setQuery);
});

Mongodb java driver aggregation's cursor don't have a skip method?

I am querying the mongodb using mongodb-java-driver aggregation api. And I find when query the db in a aggregation way using com.mongodb.DBCollection.aggregate a cursor interface will be returned.
Here is the method signature:
com.mongodb.DBCollection
public com.mongodb.Cursor aggregate(java.util.List<com.mongodb.DBObject> pipeline,
com.mongodb.AggregationOptions options)
But this returned cursor is not skip-able, ie, it doesn't have a skip method as the DBCursor class does. And the official document don't give a hint of doing that.
Does that mean when I do a aggregate query, and when I want to do a pagenation ,I can only retrieve the whole result set and skip the un-needed items myself?
You could of course skip them yourself programmatically, but there is a way to do it:
Aggregator skip
But you must skip with the aggregate, you can not skip afterwards (Then you would either need to aggregate again or skip programmatically)
{ $skip: <positive integer> }
You should use $skip in mongo aggregation also using java. Let's check following two links
mongo java aggregation
and
mongo $skip in aggregation
Using above two links you able to set your aggregation query as below
// unwind if required
DBObject unwind = new BasicDBObject("$unwind", "$your unwind field");
// create pipeline operations, with the $match
DBObject match = new BasicDBObject("$match", new BasicDBObject("given key", "matching value"));
// Now the $group operation if required
DBObject groupFields = new BasicDBObject("_id", "$group field");
groupFields.put("count", new BasicDBObject("$sum", 1));
DBObject group = new BasicDBObject("$group", groupFields);
// build the $projection operation
DBObject fields = new BasicDBObject("_id", 0);
fields.put("count", "$count");
DBObject project = new BasicDBObject("$project", fields);
// skip
DBObject skip = new BasicDBObject("$skip", positive integer);
// run aggregation
List < DBObject > pipeline = Arrays.asList(match, group, project, skip);
AggregationOutput output = collectionName.aggregate(pipeline);
for (DBObject result: output.results()) {
System.out.println(result);
}

How to search a document and remove field from it in mongodb using java?

I have a device collection.
{
"_id" : "10-100-5675234",
"_type" : "Device",
"alias" : "new Alias name",
"claimCode" : "FG755DF8N",
"hardwareId" : "SERAIL02",
"isClaimed" : "true",
"model" : "VMB3010",
"userId" : "5514f428c7b93d48007ac6fd"
}
I want to search document by _id and then update it after removing a field userId from the result document. I am trying different ways but none of them is working. Please help me.
You can remove a field using $unset with mongo-java driver in this way:
MongoClient mongo = new MongoClient("localhost", 27017);
DB db = (DB) mongo.getDB("testDB");
DBCollection collection = db.getCollection("collection");
DBObject query = new BasicDBObject("_id", "10-100-5675234");
DBObject update = new BasicDBObject();
update.put("$unset", new BasicDBObject("userId",""));
WriteResult result = collection.update(query, update);
mongo.close();
The easiest way is to use the functionality in the java driver:
Query query = new Query();
query.addCriteria(Criteria.where("_id").is(new ObjectId("10-100-5675234")));
Update update = new Update();
update.unset("userId"); //the fields you want to remove
update.set("putInYourFieldHere", "putInYourValueHere"); //the fields you want to add
mongoTemplate.updateFirst(query, update, Device.class);
The above code assumes that your "_id" is your mongodb normal "_id" which means that the variable you are looking for must be encased in the new ObjectId().
Long time since this post was opened, but might be useful for someone in the future.
device.updateMany(eq("_id", "whatever"), unset("userId"));
An ugly way is to replace the old version with the new version of you document (no userid).
BasicDBObject newDocument = new BasicDBObject();
newDocument.put("_type", "Device");
newDocument.put("alias", "new Alias name");
// ...
BasicDBObject searchQuery = new BasicDBObject().append("_id", "10-100-5675234");
collection.update(searchQuery, newDocument);
The MongoDB documentation provides a clear answer to this question: use the $unset update operator.

MongoDB set multiple fields with update

I am trying to set multiple fields with an update in MongoDB using Java
DBObject nameQuery = new BasicDBObject();
nameQuery.put(DBUser.LAST_SEEN_NAME_FIELD, player.getName());
nameQuery.put(DBUser.LAST_SEEN_NAME_LOWER_FIELD, player.getName().toLowerCase());
nameQuery.put(DBUser.UUID_FIELD, new BasicDBObject("$ne", Database.makeStorableUUID(player.getUniqueId())));
DBObject updateFields = new BasicDBObject();
updateFields.put(DBUser.LAST_SEEN_NAME_FIELD, "");
updateFields.put(DBUser.LAST_SEEN_NAME_LOWER_FIELD, "");
DBObject nameUpdate = new BasicDBObject("$set", updateFields);
this.update(nameQuery, nameUpdate);
When this runs it doesn't throw any errors but I would assume there is something wrong with my query or update. I'm hoping someone can point me in the right direction.
I fixed the problem by using updateMulti instead of update.

Categories

Resources