How to find documents matching multiple criteria - java

I'm trying to query a collection using operands AND'd together. I've got the shell version working:
db.widgets.find({color: 'black, shape: 'round', weight: 100})
I'm unable to find the Java equivalent (using the native driver). I've tried various things, but here is my latest attempt:
// Find all black, round widgets with weight 100
List<BasicDBObject> criteria = new ArrayList<BasicDBObject>();
criteria.add(new BasicDBObject("color", "black"));
criteria.add(new BasicDBObject("shape", "round"));
criteria.add(new BasicDBObject("weight", 100));
DBCursor cur = widgets.find(new BasicDBObject("$and", criteria));
// Get all matching widgets and put them into a list
List<Widget> widgetList = new ArrayList<Widget>();
DBCursor cur = widgets.find(andQuery);
while (cur.hasNext()) {
widgetList.add(new Widget(cur.next()));
}
if (widgetList.isEmpty())
System.out.println("No results found");
Any ideas what is wrong?

BasicDBObject criteria = new BasicDBObject();
criteria.append("color", "black");
criteria.append("shape", "round");
criteria.append("weight", 100);
DBCursor cur = widgets.find(criteria);

Another way to solve same problem is using aggregation:
// To print results
Block<Document> printBlock = new Block<Document>() {
#Override
public void apply(final Document document) {
System.out.println(document.toJson());
}
};
// get db connection and collection
MongoDatabase db= mongoClient.getDatabase("dbname");
MongoCollection<Document> collection= database.getCollection("collectionname");
collection.aggregate(Arrays.asList(Aggregates.match(Filters.eq("key1", "value1")),
Aggregates.match(Filters.eq("key2", "value2")),
Aggregates.match(Filters.eq("key3", "value3")))).forEach(printBlock);
For more details please refer the v 3.4 mongo Aggregation documentation.
http://mongodb.github.io/mongo-java-driver/3.4/driver/tutorials/aggregation/

I think the solution above should also work just fine, given the situation I'd suggest the following as an alternative. This is using Criteria
Query query = new Query();
List<Criteria> criteriaList = new ArrayList<>();
Criteria criteriaCreatedBy1 = new Criteria().where("title").is("input");
criteriaList.add(criteriaCreatedBy1);
Criteria criteriaCreatedBy2 = new Criteria().where("name").is("name input");
criteriaList.add(criteriaCreatedBy2);
query.addCriteria(new Criteria().andOperator(criteriaList.toArray(new Criteria[criteriaList.size()])));
List<Screen> getSearchScreens = mongoTemplate.find(query,Screen.class,"collectionName");

Related

How to distinct query in MongoDB with projection and filters?

I have list of attributes in mongo and I am querying some nested field. Here is my code,
public List<Brand> searchBrands(Request request) {
final MongoCollection<Document> collection = mongoDatabase.getCollection("shop");
final Document query = new Document();
final Document projection = new Document();
final List<Brand> brandList = new ArrayList<>();
query.append("_id", request.getId());
query.append("isActive", true);
if (request.Year() != null) {
query.append("attributes.name", "myYear");
query.append("attributes.value", request.getYear());
}
projection.append("brand.code", 1.0);
projection.append("brand.description", 1.0);
projection.append("_id", 0.0);
Block<Document> processBlock = document -> brandList.
add(Brand.builder().code(document.get("brand",Document.class).getString("code"))
.description(document.get("brand",Document.class).getString("description"))
.build());
collection.find(query).projection(projection).forEach(processBlock);
return brandList;}
Above code return results correctly, 72 item with same brand.code. But I want to fetch distinct according to brand.code How can I do that?
I'm not sure which mongodb client library you're using to create queries for mongodb;
I'm sharing the query that you can run in mongodb console to get the results you want. I hope you know how to create this query using your mongodb client library
db.shop.distinct('brand.code', myQuery)
//Replace myQuery with your query e.g. {isActive: true}

Mongodb Java - How to return all fields of a collection

With the driver Java Mongodb, I am looking for a way to return all fields of one collection.For example, I have a collection "people", how can I get all fields, I want output: 'id','name','city'...
Thanks a lot, I have finally got the answer.
DBCursor cur = db.getCollection("people").find();
DBObject dbo = cur.next();
Set<String> s = dbo.keySet();
From manual:
To return all documents in a collection, call the find method without a criteria document. For example, the following operation queries for all documents in the restaurants collection.
FindIterable<Document> iterable = db.getCollection("restaurants").find();
Iterate the results and apply a block to each resulting document.
iterable.forEach(new Block<Document>() {
#Override
public void apply(final Document document) {
System.out.println(document);
}
});
You'd need to decide on the number of samples that would make sense to you but this would pull the last 10 submissions.
Document nat = new Document().append("$natural",-1);
FindIterable<Document> theLastDocumentSubmitted = collection.find().limit(10).sort(nat);
ArrayList<String>fieldkeys = new ArrayList<String>();
for (Document doc : theLastDocumentSubmitted) {
Set<String> keys = doc.keySet();
Iterator iterator = keys.iterator();
while(iterator.hasNext()){
String key = (String) iterator.next();
String value = (String) doc.get(key).toString();
if(!fieldkeys.contains(key)) {
fieldkeys.add(key);
}
}
}
System.out.println("fieldkeys" + fieldkeys.toString());
Below code will return all fields from given collection.
MongoCollection<Document> mongoCollection = mongoDatabase.getCollection("collection_name");
AggregateIterable<Document> output = mongoCollection.aggregate(Arrays.asList(
new Document("$project", Document("arrayofkeyvalue", new Document("$objectToArray", "$$ROOT"))),
new Document("$unwind", "$arrayofkeyvalue"),
new Document("$group", new Document("_id", null).append("allkeys", new Document("$addToSet", "$arrayofkeyvalue.k")))
));
Below code will return all fields of people collection :
db.people.find()

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);
});

Upgrading mongo search from runCommand to find using Java driver

I am using a Java driver to run some mongo text searches.
An example of my previous code is (where values is a String passed in):
DBCollection coll = db.getCollection("testCollection");
//create the basic object
DBObject searchCmd = new BasicDBObject();
//create the search cmd
searchCmd.put("text", "testCollection"); // the name of the collection (string)
// define the search word
searchCmd.put("search", value); // the term to search for (string)
// define the return values
searchCmd.put("project", new BasicDBObject("score", 1).append("name", 1).append("path", 0).append("_id", 0));
// get the results
BasicDBObject commandResult = db.command(searchCmd);
// Just out the results key
BasicDBList results = (BasicDBList) commandResult.get("results");
then I loop over the "results" and I get for each it score by
// Get the number ii
BasicDBObject element = (BasicDBObject) results.get(ii);
// Now get the score
double score = (double) element.get("score");
I want to upgrade to use find since that seems the way 2.6 and later prefers it. So far I have:
DBCollection coll = db.getCollection("testCollection");
BasicDBObject query = new BasicDBObject();
query.append("$text", new BasicDBObject("$search", value));
DBCursor cursor = coll.find(query);
However, I am not sure how to get the score.
I tried doing something like:
query.append("score", new BasicDBObject("$meta", "textScore"));
But this does not work. I would like to be able to get the name and the score so that I can then insert them into a new collection that will also hold the score.
I can get the name easily by:
while (cursor.hasNext())
{
DBObject next = cursor.next();
String name = next.get("name").toString();
}
But how do I get the score?
I found this interesting page: http://api.mongodb.org/java/current/
it appears that find can take a second DBObject which has the fields.
I created a new object:
BasicDBObject fields = new BasicDBObject();
fields.append("score", new BasicDBObject("$meta", "textScore"));
and I am calling find using:
DBCursor cursor = coll.find(query, fields);
and now I can get the score the same way I can get the name.

Use MongoDB db.collection.remove(query) in java

Is there a way in the MongoDB Java driver to call the db.collection.remove(query) method that I see in the MongoDB shell documentation?
That is, I know the exact criteria that I need to find all the documents I want to delete from MongoDB, but I can't find a way to make one call to remove those records in one trip. All that I can figure out is to find the documents and then delete them one by one.
I see this
http://docs.mongodb.org/manual/reference/method/db.collection.remove/
which implies there should be a way to do it, but I can't figure out the Java calls to get me that to that call.
Thank you for your help
To remove documents with an age property of 25.
MongoClient mongo = new MongoClient(new ServerAddress("localhost", 27017));
DB db = mongo.getDB("thedb");
DBCollection collection = db.getCollection("test");
BasicDBObject query = new BasicDBObject();
query.append("age", 25);
collection.remove(query);
DBCollection and BasicDBObject are two of the most important classes in the Java API.
Also to remove specific values from you document you can use following code with Mongo Java 3.2
Document docToDelete = new Document("Designation", "SE-1");
objDbCollection.findOneAndUpdate(new Document("Company", "StackOverflow"), new Document("$unset", docToDelete));
Above code will first find document having company = StackOverflow and then unset (remove) Designation = SE-1 key/value from that document.
Add and Update Mongo
public class App {
public static void main(String[] args) {
try {
Mongo mongo = new Mongo("localhost", 27017);
DB db = mongo.getDB("yourdb");
// get a single collection
DBCollection collection = db.getCollection("dummyColl");
//insert number 1 to 10 for testing
for (int i=1; i <= 10; i++) {
collection.insert(new BasicDBObject().append("number", i));
}
//remove number = 1
DBObject doc = collection.findOne(); //get first document
collection.remove(doc);
//remove number = 2
BasicDBObject document = new BasicDBObject();
document.put("number", 2);
collection.remove(document);
//remove number = 3
collection.remove(new BasicDBObject().append("number", 3));
//remove number > 9 , means delete number = 10
BasicDBObject query = new BasicDBObject();
query.put("number", new BasicDBObject("$gt", 9));
collection.remove(query);
//remove number = 4 and 5
BasicDBObject query2 = new BasicDBObject();
List<Integer> list = new ArrayList<Integer>();
list.add(4);
list.add(5);
query2.put("number", new BasicDBObject("$in", list));
collection.remove(query2);
//print out the document
DBCursor cursor = collection.find();
while(cursor.hasNext()) {
System.out.println(cursor.next());
}
collection.drop();
System.out.println("Done");
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (MongoException e) {
e.printStackTrace();
}

Categories

Resources